Skip to content

Commit eecdbf0

Browse files
committed
Refactor types again
1 parent 2108213 commit eecdbf0

13 files changed

+221
-240
lines changed

src/hyperjump/embedded.test.js

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { fromJref } from "../jref/index.js";
66
import { toJson } from "../json/jsonast-util.js";
77

88
/**
9-
* @import { DocumentNode } from "./index.js"
9+
* @import { JrefJrefNode } from "../jref/jref-ast.js"
1010
*/
1111

1212

@@ -17,8 +17,27 @@ describe("JSON Browser", () => {
1717
const testMediaType = "application/prs.hyperjump-embedded-test";
1818

1919
beforeAll(() => {
20-
/** @type (uri: string, text: string, embedded?: Record<string, DocumentNode>) => DocumentNode */
20+
/**
21+
* @typedef {{
22+
* type: "embedded-document";
23+
* children: JrefJrefNode[];
24+
* uri: string;
25+
* fragmentKind: "json-pointer";
26+
* embedded?: Record<string, EmbeddedDocumentNode>;
27+
* }} EmbeddedDocumentNode
28+
*/
29+
30+
/** @type (uri: string, text: string, embedded?: Record<string, EmbeddedDocumentNode>) => EmbeddedDocumentNode */
2131
const parseToDocument = (uri, text, embedded = {}) => {
32+
/** @type EmbeddedDocumentNode */
33+
const embeddedDocument = {
34+
type: "embedded-document",
35+
children: [],
36+
uri: uri,
37+
fragmentKind: "json-pointer",
38+
embedded: embedded
39+
};
40+
2241
const rootNode = fromJref(text, uri, (node, key) => {
2342
if (key === "$embedded" && node.jsonType === "object") {
2443
for (const propertyNode of node.children) {
@@ -32,13 +51,11 @@ describe("JSON Browser", () => {
3251
}
3352
});
3453

35-
return {
36-
type: "embedded-document",
37-
children: [rootNode],
38-
uri: uri,
39-
fragmentKind: "json-pointer",
40-
embedded: embedded
41-
};
54+
if (rootNode) {
55+
embeddedDocument.children.push(rootNode);
56+
}
57+
58+
return embeddedDocument;
4259
};
4360
hyperjump.addMediaTypePlugin({
4461
mediaType: testMediaType,

src/hyperjump/hyperjump.d.ts

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { JsonNode } from "../json/jsonast.d.ts";
2-
import type { JrefNode, JrefJrefNode } from "../jref/jref-ast.d.ts";
2+
import type { JrefJrefNode } 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";
55
import type { jsonObjectHas, jsonObjectKeys, jsonValue } from "../json/jsonast-util.js";
@@ -11,8 +11,7 @@ export type GetOptions = {
1111
referencedFrom?: string;
1212
};
1313

14-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
15-
export class Hyperjump<T extends JrefNode<any> = JrefJrefNode> {
14+
export class Hyperjump<T extends JrefNode<{}> = JrefJrefNode> {
1615
constructor(config?: HyperjumpConfig);
1716

1817
/**
@@ -30,7 +29,7 @@ export class Hyperjump<T extends JrefNode<any> = JrefJrefNode> {
3029
* @throws {@link RetrievalError}
3130
* @throws {@link json.JsonPointerError}
3231
*/
33-
get: (uri: string, options?: GetOptions) => Promise<T & JsonNode<T>>;
32+
get: (uri: string, options?: GetOptions) => Promise<JsonNode<T>>;
3433

3534
/**
3635
* Add support for a
@@ -72,7 +71,7 @@ export class Hyperjump<T extends JrefNode<any> = JrefJrefNode> {
7271
* {@link hyperjump.JsonMediaTypePlugin | `JSON`} media types are enabled by
7372
* default.
7473
*/
75-
addMediaTypePlugin: <T extends DocumentNode>(plugin: MediaTypePlugin<T>) => void;
74+
addMediaTypePlugin: <A extends DocumentNode<T>>(plugin: MediaTypePlugin<A>) => void;
7675

7776
/**
7877
* This is mostly useful for disabling a scheme that's enabled by default.
@@ -94,27 +93,27 @@ export class Hyperjump<T extends JrefNode<any> = JrefJrefNode> {
9493
* This is like indexing into an object or array. It will follow any
9594
* references it encounters so it always returns a JSON compatible value.
9695
*/
97-
step: (key: string, node: JsonNode<T>) => Promise<T & JsonNode<T>>;
96+
step: (key: string, node: JsonNode<T>) => Promise<JsonNode<T>>;
9897

9998
/**
10099
* Iterate over an array node. It will follow any references it encounters so
101100
* it always yields JSON compatible values.
102101
*/
103-
iter: (node: JsonNode<T>) => AsyncGenerator<T & JsonNode<T>, void, unknown>;
102+
iter: (node: JsonNode<T>) => AsyncGenerator<JsonNode<T>, void, unknown>;
104103

105104
keys: typeof jsonObjectKeys;
106105

107106
/**
108107
* Iterate over the values of an object. It will follow any references it
109108
* encounters so it always yields JSON compatible values.
110109
*/
111-
values: (node: JsonNode<T>) => AsyncGenerator<T & JsonNode<T>, void, unknown>;
110+
values: (node: JsonNode<T>) => AsyncGenerator<JsonNode<T>, void, unknown>;
112111

113112
/**
114113
* Iterate over key/value pairs of an object. It will follow any references it
115114
* encounters so it always yields JSON compatible values.
116115
*/
117-
entries: (node: JsonNode<T>) => AsyncGenerator<[string, T & JsonNode<T>], void, unknown>;
116+
entries: (node: JsonNode<T>) => AsyncGenerator<[string, JsonNode<T>], void, unknown>;
118117
}
119118

120119
export class RetrievalError extends Error {

src/hyperjump/hyperjump.js

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,20 +21,20 @@ import { mimeMatch } from "./utilities.js";
2121
// TODO: Support filters
2222

2323
/**
24-
* @template {JrefNode<any>} [T=JrefJrefNode]
24+
* @template {JrefNode<unknown>} [T=JrefJrefNode]
2525
* @implements API.Hyperjump<T>
2626
*/
2727
export class Hyperjump {
2828
// TODO: Add config to enable schemes and media types
2929
#config;
3030

31-
/** @type Record<string, DocumentNode> */
31+
/** @type Record<string, DocumentNode<T>> */
3232
#cache;
3333

3434
/** @type Record<string, UriSchemePlugin> */
3535
#uriSchemePlugins;
3636

37-
/** @type Record<string, MediaTypePlugin<DocumentNode>> */
37+
/** @type Record<string, MediaTypePlugin<DocumentNode<T>>> */
3838
#mediaTypePlugins;
3939

4040
/** @type API.GetOptions */
@@ -91,14 +91,13 @@ export class Hyperjump {
9191
}
9292
const cursor = document.fragmentKind === "json-pointer" ? fragment : "";
9393

94-
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
95-
const node = /** @type T */ (pointerGet(cursor ?? "", document.children[0], document.uri));
94+
const node = pointerGet(cursor ?? "", document.children[0], document.uri);
9695
return await this.#followReferences(node);
9796
}
9897

99-
/** @type (node: T) => Promise<JsonNode<T>> */
98+
/** @type (node: JrefNode<T>) => Promise<JsonNode<T>> */
10099
async #followReferences(node) {
101-
if ("jrefType" in node) {
100+
if (node.jrefType === "reference") {
102101
return this.get(node.href, { referencedFrom: toAbsoluteIri(node.location) });
103102
} else {
104103
return /** @type JsonNode<T> */ (node);
@@ -182,7 +181,7 @@ export class Hyperjump {
182181
this.#mediaTypePlugins[contentType].quality = quality;
183182
}
184183

185-
/** @type (response: Response) => Promise<DocumentNode> */
184+
/** @type (response: Response) => Promise<DocumentNode<T>> */
186185
#parseResponse(response) {
187186
const contentTypeText = response.headers.get("content-type");
188187
if (contentTypeText === null) {
@@ -204,7 +203,7 @@ export class Hyperjump {
204203

205204
/** @type API.Hyperjump<T>["step"] */
206205
async step(key, node) {
207-
return await this.#followReferences(/** @type T */ (pointerStep(key, node)));
206+
return await this.#followReferences(pointerStep(key, node));
208207
}
209208

210209
/** @type API.Hyperjump<T>["iter"] */

src/hyperjump/media-types/media-type-plugin.d.ts

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,14 @@
1-
import type { JrefNode } from "../../jref/jrefast.d.ts";
2-
3-
4-
export type DocumentNode = {
1+
export type DocumentNode<A> = {
52
type: string;
6-
children: JrefNode[];
3+
children: A[];
74
uri?: string;
8-
embedded?: Record<string, DocumentNode>;
5+
embedded?: Record<string, DocumentNode<A>>;
96
anchors?: Record<string, string>;
107
fragmentKind?: string;
118
};
129

1310
// eslint-disable-next-line @typescript-eslint/consistent-type-definitions
14-
export interface MediaTypePlugin<T extends DocumentNode> {
11+
export interface MediaTypePlugin<T extends DocumentNode<unknown>> {
1512
mediaType: string;
1613
/**
1714
* Extensions start with `.` (Example: `.jref`).

src/jref/jref-ast.d.ts

Lines changed: 11 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,74 +1,20 @@
11
import type { Data } from "unist";
2-
import {
3-
JsonArrayNode,
4-
JsonBooleanNode,
5-
JsonNullNode,
6-
JsonNumberNode,
7-
JsonObjectNode,
8-
JsonStringNode
9-
} from "../json/jsonast.d.ts";
2+
import type { JsonNode } from "../json/jsonast.d.ts";
103

4+
export type JrefNode<A> = JsonNode<A & (
5+
{
6+
jrefType: "json";
7+
} | {
8+
jrefType: "reference";
9+
href: string;
10+
}
11+
)>;
1112

12-
// eslint-disable-next-line @typescript-eslint/consistent-type-definitions
13-
export interface JrefReferenceNode {
14-
jrefType: "jref-reference";
15-
href: string;
16-
};
17-
18-
// eslint-disable-next-line @typescript-eslint/consistent-type-definitions
19-
export interface JrefJsonNullNode extends JsonNullNode {
20-
type: "jref";
21-
};
22-
23-
// eslint-disable-next-line @typescript-eslint/consistent-type-definitions
24-
export interface JrefJsonBooleanNode extends JsonBooleanNode {
25-
type: "jref";
26-
};
27-
28-
// eslint-disable-next-line @typescript-eslint/consistent-type-definitions
29-
export interface JrefJsonNumberNode extends JsonNumberNode {
30-
type: "jref";
31-
};
32-
33-
// eslint-disable-next-line @typescript-eslint/consistent-type-definitions
34-
export interface JrefJsonStringNode extends JsonStringNode {
35-
type: "jref";
36-
};
37-
38-
// eslint-disable-next-line @typescript-eslint/consistent-type-definitions
39-
export interface JrefJsonArrayNode extends JsonArrayNode<JrefJrefNode> {
40-
type: "jref";
41-
};
42-
43-
// eslint-disable-next-line @typescript-eslint/consistent-type-definitions
44-
export interface JrefJsonObjectNode extends JsonObjectNode<JrefJrefNode> {
45-
type: "jref";
46-
};
47-
48-
// eslint-disable-next-line @typescript-eslint/consistent-type-definitions
49-
export interface JrefJrefReferenceNode extends JrefReferenceNode, JsonObjectNode<JrefJrefNode> {
50-
type: "jref";
51-
};
52-
53-
export type JrefNode<A> = JsonObjectNode<A>
54-
| JsonArrayNode<A>
55-
| JsonStringNode
56-
| JsonNumberNode
57-
| JsonBooleanNode
58-
| JsonNullNode
59-
| (JrefReferenceNode & JsonObjectNode<A>);
60-
61-
export type JrefJrefNode = JrefJsonObjectNode
62-
| JrefJsonArrayNode
63-
| JrefJsonStringNode
64-
| JrefJsonNumberNode
65-
| JrefJsonBooleanNode
66-
| JrefJsonNullNode
67-
| JrefJrefReferenceNode;
13+
export type JrefJrefNode = JrefNode<{ type: "jref" }>;
6814

6915
export type JrefDocumentNode = {
7016
type: "jref-document";
71-
children: JrefJrefNode[];
17+
children: JrefNode<{}>[];
7218
uri: string;
7319
fragmentKind: "json-pointer";
7420
data?: Data;

src/jref/jref-parse.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { Reviver } from "./jref-util.js";
44

55

66
export type JrefParseOptions = {
7-
reviver?: Reviver<JrefJrefNode>;
7+
reviver?: Reviver<JrefJrefNode, JrefJrefNode>;
88
};
99

1010
/**

src/jref/jref-util.d.ts

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,35 @@
1-
import { JrefJrefNode, JrefNode } from "./jref-ast.d.ts";
1+
import type {
2+
JsonArrayNode,
3+
JsonBooleanNode,
4+
JsonNullNode,
5+
JsonNumberNode,
6+
JsonObjectNode,
7+
JsonStringNode
8+
} from "../json/jsonast.js";
9+
import type { JrefNode } from "./jref-ast.d.ts";
210

11+
export type ParsedJrefNode<A> = {
12+
type: "jref";
13+
} & (
14+
{
15+
jrefType: "json";
16+
} | {
17+
jrefType: "reference";
18+
href: string;
19+
}
20+
) & (
21+
JsonObjectNode<JrefNode<A>>
22+
| JsonArrayNode<JrefNode<A>>
23+
| JsonStringNode
24+
| JsonNumberNode
25+
| JsonBooleanNode
26+
| JsonNullNode
27+
);
328

4-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
5-
export type Reviver<T = JrefNode<any> | undefined> = <A>(node: JrefNode<JrefNode<A>>, key?: string) => T;
29+
export type Reviver<A, R extends JrefNode<A> | undefined> = (node: ParsedJrefNode<A>, key?: string) => R;
630

731
/**
832
* Parse a JRef string into a JRef AST. Includes a reviver option similar to
933
* {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse | JSON.parse}.
1034
*/
11-
export const fromJref: {
12-
(json: string, uri: string): JrefJrefNode;
13-
<R extends Reviver | undefined>(jref: string, uri: string, reviver: R): R extends undefined ? JrefJrefNode : ReturnType<R>;
14-
};
35+
export const fromJref: <A = { type: "jref" }, R = JrefNode<A>>(json: string, uri: string, reviver?: Reviver<A, R>) => R;

0 commit comments

Comments
 (0)