Skip to content

Commit ee294fa

Browse files
committed
Refactor type model in an attempt to make extension easier
1 parent d1c63c9 commit ee294fa

21 files changed

+581
-355
lines changed

src/hyperjump/embedded.test.js

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,11 @@ import { describe, test, beforeEach, afterEach, expect, beforeAll, afterAll } fr
22
import { MockAgent, setGlobalDispatcher } from "undici";
33
import { toAbsoluteIri } from "@hyperjump/uri";
44
import { Hyperjump } from "./index.js";
5-
import { fromJref, toJref } from "../jref/index.js";
5+
import { fromJref } from "../jref/index.js";
6+
import { toJson } from "../json/jsonast-util.js";
67

78
/**
89
* @import { DocumentNode } from "./index.js"
9-
* @import { JrefNode } from "../jref/index.js"
10-
* @import { Reviver } from "../jref/index.js"
1110
*/
1211

1312

@@ -20,23 +19,22 @@ describe("JSON Browser", () => {
2019
beforeAll(() => {
2120
/** @type (uri: string, text: string, embedded?: Record<string, DocumentNode>) => DocumentNode */
2221
const parseToDocument = (uri, text, embedded = {}) => {
23-
/** @type Reviver<JrefNode | undefined> */
24-
const embeddedReviver = (node, key) => {
25-
if (key === "$embedded" && node.type === "json" && node.jsonType === "object") {
22+
const rootNode = fromJref(text, uri, (node, key) => {
23+
if (key === "$embedded" && node.jsonType === "object") {
2624
for (const propertyNode of node.children) {
2725
const embeddedUri = toAbsoluteIri(propertyNode.children[0].value);
28-
const embeddedJref = toJref(propertyNode.children[1], uri);
26+
const embeddedJref = toJson(propertyNode.children[1]);
2927
embedded[embeddedUri] = parseToDocument(embeddedUri, embeddedJref, embedded);
3028
}
3129
return;
3230
} else {
3331
return node;
3432
}
35-
};
33+
});
3634

3735
return {
3836
type: "embedded-document",
39-
children: [fromJref(text, uri, embeddedReviver)],
37+
children: [rootNode],
4038
uri: uri,
4139
fragmentKind: "json-pointer",
4240
embedded: embedded
@@ -81,7 +79,7 @@ describe("JSON Browser", () => {
8179
const uri = `${testDomain}/main#/foo`;
8280
const subject = await hyperjump.get(uri);
8381

84-
expect(toJref(subject, uri)).to.equal(`42`);
82+
expect(toJson(subject)).to.equal(`42`);
8583
});
8684

8785
test("getting the main document from an embedded document", async () => {
@@ -100,7 +98,7 @@ describe("JSON Browser", () => {
10098
const uri = `${testDomain}/main#/foo`;
10199
const subject = await hyperjump.get(uri);
102100

103-
expect(toJref(subject, uri)).to.equal(`42`);
101+
expect(toJson(subject)).to.equal(`42`);
104102
});
105103

106104
test("getting an embedded document from an embedded document", async () => {
@@ -119,7 +117,7 @@ describe("JSON Browser", () => {
119117
const uri = `${testDomain}/main#/foo`;
120118
const subject = await hyperjump.get(uri);
121119

122-
expect(toJref(subject, uri)).to.equal(`42`);
120+
expect(toJson(subject)).to.equal(`42`);
123121
});
124122

125123
test("a cached document takes precence over an embedded document", async () => {
@@ -148,7 +146,7 @@ describe("JSON Browser", () => {
148146
const uri = `${testDomain}/main#/foo`;
149147
const subject = await hyperjump.get(uri);
150148

151-
expect(toJref(subject, uri)).to.equal(`42`);
149+
expect(toJson(subject)).to.equal(`42`);
152150
});
153151
});
154152
});

src/hyperjump/generators.test.js

Lines changed: 16 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,7 @@
11
import { describe, test, beforeEach, afterEach, expect } from "vitest";
22
import { MockAgent, setGlobalDispatcher } from "undici";
33
import { Hyperjump } from "./index.js";
4-
import { toJref } from "../jref/index.js";
5-
6-
/**
7-
* @import { JrefNode } from "../jref/index.js"
8-
* @import { JsonCompatible } from "../json/index.js"
9-
*/
4+
import { toJson } from "../json/jsonast-util.js";
105

116

127
describe("JSON Browser", () => {
@@ -44,11 +39,11 @@ describe("JSON Browser", () => {
4439
const generator = hyperjump.iter(subject);
4540

4641
const first = await generator.next();
47-
expect(toJref(/** @type NonNullable<any> */ (first.value), uri)).to.equal(`1`);
42+
expect(first.value && toJson(first.value)).to.equal(`1`);
4843
const second = await generator.next();
49-
expect(toJref(/** @type NonNullable<any> */ (second.value), uri)).to.equal(`2`);
44+
expect(second.value && toJson(second.value)).to.equal(`2`);
5045
const third = await generator.next();
51-
expect(toJref(/** @type NonNullable<any> */ (third.value), uri)).to.equal(`2`);
46+
expect(third.value && toJson(third.value)).to.equal(`2`);
5247
expect((await generator.next()).done).to.equal(true);
5348
});
5449

@@ -95,11 +90,11 @@ describe("JSON Browser", () => {
9590
const generator = hyperjump.values(subject);
9691

9792
const first = await generator.next();
98-
expect(toJref(/** @type NonNullable<any> */ (first.value), uri)).to.equal(`1`);
93+
expect(first.value && toJson(first.value)).to.equal(`1`);
9994
const second = await generator.next();
100-
expect(toJref(/** @type NonNullable<any> */ (second.value), uri)).to.equal(`2`);
95+
expect(second.value && toJson(second.value)).to.equal(`2`);
10196
const third = await generator.next();
102-
expect(toJref(/** @type NonNullable<any> */ (third.value), uri)).to.equal(`2`);
97+
expect(third.value && toJson(third.value)).to.equal(`2`);
10398
expect((await generator.next()).done).to.equal(true);
10499
});
105100

@@ -124,17 +119,17 @@ describe("JSON Browser", () => {
124119
const subject = await hyperjump.get(uri);
125120
const generator = hyperjump.entries(subject);
126121

127-
const a = /** @type [string, JsonCompatible<JrefNode>] */ ((await generator.next()).value);
128-
expect(a[0]).to.equal("a");
129-
expect(toJref(a[1], uri)).to.equal(`1`);
122+
const a = await generator.next();
123+
expect(a.value && a.value[0]).to.equal("a");
124+
expect(a.value && toJson(a.value[1])).to.equal(`1`);
130125

131-
const b = /** @type [string, JsonCompatible<JrefNode>] */ ((await generator.next()).value);
132-
expect(b[0]).to.equal("b");
133-
expect(toJref(b[1], uri)).to.equal(`2`);
126+
const b = await generator.next();
127+
expect(b.value && b.value[0]).to.equal("b");
128+
expect(b.value && toJson(b.value[1])).to.equal(`2`);
134129

135-
const c = /** @type [string, JsonCompatible<JrefNode>] */ ((await generator.next()).value);
136-
expect(c[0]).to.equal("c");
137-
expect(toJref(c[1], uri)).to.equal(`2`);
130+
const c = await generator.next();
131+
expect(c.value && c.value[0]).to.equal("c");
132+
expect(c.value && toJson(c.value[1])).to.equal(`2`);
138133

139134
expect((await generator.next()).done).to.equal(true);
140135
});

src/hyperjump/get.test.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { describe, test, beforeEach, afterEach, expect } from "vitest";
22
import { MockAgent, setGlobalDispatcher } from "undici";
33
import { Hyperjump } from "./index.js";
4-
import { toJref } from "../jref/index.js";
4+
import { toJson } from "../json/jsonast-util.js";
55

66

77
describe("JSON Browser", () => {
@@ -41,7 +41,7 @@ describe("JSON Browser", () => {
4141
const browser = new Hyperjump();
4242
const subject = await browser.get(uri);
4343

44-
expect(toJref(subject, uri, undefined, " ")).to.eql(jref);
44+
expect(toJson(subject, undefined, " ")).to.eql(jref);
4545
});
4646

4747
test("follow fragment-only reference", async () => {
@@ -63,7 +63,7 @@ describe("JSON Browser", () => {
6363
const browser = new Hyperjump();
6464
const subject = await browser.get(`${uri}#/bar`);
6565

66-
expect(toJref(subject, uri)).to.eql(`42`);
66+
expect(toJson(subject)).to.eql(`42`);
6767
});
6868

6969
test("follow reference to another document", async () => {
@@ -87,7 +87,7 @@ describe("JSON Browser", () => {
8787
const browser = new Hyperjump();
8888
const subject = await browser.get(uri);
8989

90-
expect(toJref(subject, uri)).to.eql(`"bar"`);
90+
expect(toJson(subject)).to.eql(`"bar"`);
9191
});
9292

9393
test("follow a reference to another document with a fragment", async () => {
@@ -113,7 +113,7 @@ describe("JSON Browser", () => {
113113
const browser = new Hyperjump();
114114
const subject = await browser.get(uri);
115115

116-
expect(toJref(subject, uri)).to.eql(`24`);
116+
expect(toJson(subject)).to.eql(`24`);
117117
});
118118
});
119119
});

src/hyperjump/hyperjump.d.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { JsonCompatible } from "../json/jsonast.d.ts";
1+
import type { JsonNode } from "../json/jsonast.d.ts";
22
import type { JrefNode } from "../jref/jref-ast.d.ts";
33
import type { UriSchemePlugin } from "./uri-schemes/uri-scheme-plugin.d.ts";
44
import type { DocumentNode, MediaTypePlugin } from "./media-types/media-type-plugin.d.ts";
@@ -29,7 +29,7 @@ export class Hyperjump<T extends JrefNode = JrefNode> {
2929
* @throws {@link RetrievalError}
3030
* @throws {@link json.JsonPointerError}
3131
*/
32-
get: (uri: string, options?: GetOptions) => Promise<JsonCompatible<T>>;
32+
get: (uri: string, options?: GetOptions) => Promise<JsonNode<T>>;
3333

3434
/**
3535
* Add support for a
@@ -93,27 +93,27 @@ export class Hyperjump<T extends JrefNode = JrefNode> {
9393
* This is like indexing into an object or array. It will follow any
9494
* references it encounters so it always returns a JSON compatible value.
9595
*/
96-
step: (key: string, node: JsonCompatible<T>) => Promise<JsonCompatible<T>>;
96+
step: (key: string, node: JsonNode<T>) => Promise<JsonNode<T>>;
9797

9898
/**
9999
* Iterate over an array node. It will follow any references it encounters so
100100
* it always yields JSON compatible values.
101101
*/
102-
iter: (node: JsonCompatible<T>) => AsyncGenerator<JsonCompatible<T>, void, unknown>;
102+
iter: (node: JsonNode<T>) => AsyncGenerator<JsonNode<T>, void, unknown>;
103103

104104
keys: typeof jsonObjectKeys;
105105

106106
/**
107107
* Iterate over the values of an object. It will follow any references it
108108
* encounters so it always yields JSON compatible values.
109109
*/
110-
values: (node: JsonCompatible<T>) => AsyncGenerator<JsonCompatible<T>, void, unknown>;
110+
values: (node: JsonNode<T>) => AsyncGenerator<JsonNode<T>, void, unknown>;
111111

112112
/**
113113
* Iterate over key/value pairs of an object. It will follow any references it
114114
* encounters so it always yields JSON compatible values.
115115
*/
116-
entries: (node: JsonCompatible<T>) => AsyncGenerator<[string, JsonCompatible<T>], void, unknown>;
116+
entries: (node: JsonNode<T>) => AsyncGenerator<[string, JsonNode<T>], void, unknown>;
117117
}
118118

119119
export class RetrievalError extends Error {

src/hyperjump/hyperjump.js

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,12 @@ import { HttpUriSchemePlugin } from "./uri-schemes/http-scheme-plugin.js";
55
import { FileUriSchemePlugin } from "./uri-schemes/file-scheme-plugin.js";
66
import { JsonMediaTypePlugin } from "./media-types/json-media-type-plugin.js";
77
import { JrefMediaTypePlugin } from "./media-types/jref-media-type-plugin.js";
8-
import { pointerGet, pointerStep } from "../jref/jref-util.js";
9-
import { jsonObjectHas, jsonObjectKeys, jsonValue } from "../json/jsonast-util.js";
8+
import { jsonObjectHas, jsonObjectKeys, jsonValue, pointerGet, pointerStep } from "../json/jsonast-util.js";
109
import { mimeMatch } from "./utilities.js";
1110

1211
/**
13-
* @import { JrefNode } from "../jref/jref-ast.js"
14-
* @import { JsonCompatible } from "../json/jsonast.js"
12+
* @import { JrefJrefNode, JrefNode } from "../jref/jref-ast.js"
13+
* @import { JsonNode } from "../json/jsonast.js"
1514
* @import { UriSchemePlugin } from "./uri-schemes/uri-scheme-plugin.js"
1615
* @import { DocumentNode, MediaTypePlugin } from "./media-types/media-type-plugin.js"
1716
* @import * as API from "./hyperjump.d.ts"
@@ -22,7 +21,7 @@ import { mimeMatch } from "./utilities.js";
2221
// TODO: Support filters
2322

2423
/**
25-
* @template {JrefNode} [T=JrefNode]
24+
* @template {JrefNode<any>} [T=JrefJrefNode]
2625
* @implements API.Hyperjump<T>
2726
*/
2827
export class Hyperjump {
@@ -72,7 +71,7 @@ export class Hyperjump {
7271
// TODO: How should cache work?
7372

7473
const cachedDocument = this.#cache[id];
75-
const embeddedDocument = options?.referencedFrom ? this.#cache[options.referencedFrom].embedded?.[id] : undefined;
74+
const embeddedDocument = options.referencedFrom ? this.#cache[options.referencedFrom]?.embedded?.[id] : undefined;
7675
let document = cachedDocument ?? embeddedDocument;
7776

7877
if (!document) {
@@ -97,12 +96,12 @@ export class Hyperjump {
9796
return await this.#followReferences(node);
9897
}
9998

100-
/** @type (node: T) => Promise<JsonCompatible<T>> */
99+
/** @type (node: T) => Promise<JsonNode<T>> */
101100
async #followReferences(node) {
102-
if (node?.type === "jref-reference") {
103-
return this.get(node.value, { referencedFrom: node.documentUri });
101+
if ("jrefType" in node) {
102+
return this.get(node.href, { referencedFrom: node.documentUri });
104103
} else {
105-
return /** @type JsonCompatible<T> */ (node);
104+
return /** @type JsonNode<T> */ (node);
106105
}
107106
}
108107

src/hyperjump/node-functions.test.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ import { MockAgent, setGlobalDispatcher } from "undici";
33
import { Hyperjump } from "./index.js";
44

55
/**
6-
* @import { JsonCompatible } from "../json/index.js"
7-
* @import { JrefNode } from "../jref/index.js"
6+
* @import { JsonNode } from "../json/index.js"
7+
* @import { JrefJrefNode } from "../jref/index.js"
88
*/
99

1010

@@ -26,7 +26,7 @@ describe("JSON Browser", () => {
2626
describe("object has property", () => {
2727
const hyperjump = new Hyperjump();
2828

29-
/** @type JsonCompatible<JrefNode> */
29+
/** @type JsonNode<JrefJrefNode> */
3030
let node;
3131

3232
beforeEach(async () => {

src/hyperjump/step.test.js

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { describe, test, beforeEach, afterEach, expect } from "vitest";
22
import { MockAgent, setGlobalDispatcher } from "undici";
33
import { Hyperjump } from "./index.js";
4-
import { toJref } from "../jref/index.js";
4+
import { toJson } from "../json/jsonast-util.js";
55

66

77
describe("JSON Browser", () => {
@@ -34,7 +34,7 @@ describe("JSON Browser", () => {
3434
const subject = await hyperjump.get(uri);
3535
const foo = await hyperjump.step("foo", subject);
3636

37-
expect(toJref(foo, uri)).to.eql(`42`);
37+
expect(toJson(foo)).to.eql(`42`);
3838
});
3939

4040
test("local reference to value", async () => {
@@ -53,7 +53,7 @@ describe("JSON Browser", () => {
5353
const subject = await hyperjump.get(uri);
5454
const foo = await hyperjump.step("bar", subject);
5555

56-
expect(toJref(foo, uri)).to.eql(`42`);
56+
expect(toJson(foo)).to.eql(`42`);
5757
});
5858

5959
test("local reference to local reference to value", async () => {
@@ -73,7 +73,7 @@ describe("JSON Browser", () => {
7373
const subject = await hyperjump.get(uri);
7474
const foo = await hyperjump.step("baz", subject);
7575

76-
expect(toJref(foo, uri)).to.eql(`42`);
76+
expect(toJson(foo)).to.eql(`42`);
7777
});
7878

7979
test("local reference to external reference to value", async () => {
@@ -99,7 +99,7 @@ describe("JSON Browser", () => {
9999
const subject = await hyperjump.get(uri);
100100
const foo = await hyperjump.step("baz", subject);
101101

102-
expect(toJref(foo, uri)).to.eql(`42`);
102+
expect(toJson(foo)).to.eql(`42`);
103103
});
104104

105105
test("external reference to value", async () => {
@@ -125,7 +125,7 @@ describe("JSON Browser", () => {
125125

126126
const foo = await hyperjump.step("bar", subject);
127127

128-
expect(toJref(foo, uri)).to.eql(`42`);
128+
expect(toJson(foo)).to.eql(`42`);
129129
});
130130

131131
test("external reference to local reference to value", async () => {
@@ -154,7 +154,7 @@ describe("JSON Browser", () => {
154154

155155
const foo = await hyperjump.step("baz", subject);
156156

157-
expect(toJref(foo, uri)).to.eql(`42`);
157+
expect(toJson(foo)).to.eql(`42`);
158158
});
159159
});
160160
});

0 commit comments

Comments
 (0)