Skip to content

Commit 565068b

Browse files
committed
feat(generics): introduce generics for the input schema and the options
1 parent bdb426b commit 565068b

23 files changed

+393
-292
lines changed

lib/bundle.ts

+23-19
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import $Ref from "./ref.js";
22
import Pointer from "./pointer.js";
33
import * as url from "./util/url.js";
4-
import type $RefParserOptions from "./options.js";
54
import type $Refs from "./refs.js";
6-
7-
export default bundle;
5+
import type $RefParser from "./index";
6+
import type { ParserOptions } from "./index";
7+
import type { JSONSchema } from "./index";
88

99
/**
1010
* Bundles all external JSON references into the main JSON schema, thus resulting in a schema that
@@ -14,12 +14,15 @@ export default bundle;
1414
* @param parser
1515
* @param options
1616
*/
17-
function bundle(parser: any, options: any) {
17+
function bundle<S extends JSONSchema = JSONSchema, O extends ParserOptions = ParserOptions>(
18+
parser: $RefParser<S, O>,
19+
options: O,
20+
) {
1821
// console.log('Bundling $ref pointers in %s', parser.$refs._root$Ref.path);
1922

2023
// Build an inventory of all $ref pointers in the JSON Schema
2124
const inventory: any = [];
22-
crawl(parser, "schema", parser.$refs._root$Ref.path + "#", "#", 0, inventory, parser.$refs, options);
25+
crawl<S, O>(parser, "schema", parser.$refs._root$Ref.path + "#", "#", 0, inventory, parser.$refs, options);
2326

2427
// Remap all $ref pointers
2528
remap(inventory);
@@ -32,19 +35,20 @@ function bundle(parser: any, options: any) {
3235
* @param key - The property key of `parent` to be crawled
3336
* @param path - The full path of the property being crawled, possibly with a JSON Pointer in the hash
3437
* @param pathFromRoot - The path of the property being crawled, from the schema root
38+
* @param indirections
3539
* @param inventory - An array of already-inventoried $ref pointers
3640
* @param $refs
3741
* @param options
3842
*/
39-
function crawl(
43+
function crawl<S, O>(
4044
parent: any,
41-
key: any,
42-
path: any,
43-
pathFromRoot: any,
44-
indirections: any,
45-
inventory: any,
46-
$refs: any,
47-
options: any,
45+
key: string | null,
46+
path: string,
47+
pathFromRoot: string,
48+
indirections: number,
49+
inventory: unknown[],
50+
$refs: $Refs<S>,
51+
options: O,
4852
) {
4953
const obj = key === null ? parent : parent[key];
5054

@@ -98,15 +102,15 @@ function crawl(
98102
* @param $refs
99103
* @param options
100104
*/
101-
function inventory$Ref(
105+
function inventory$Ref<S, O>(
102106
$refParent: any,
103107
$refKey: any,
104108
path: string,
105109
pathFromRoot: any,
106110
indirections: any,
107111
inventory: any,
108-
$refs: $Refs,
109-
options: $RefParserOptions,
112+
$refs: $Refs<S>,
113+
options: O,
110114
) {
111115
const $ref = $refKey === null ? $refParent : $refParent[$refKey];
112116
const $refPath = url.resolve(path, $ref.$ref);
@@ -248,9 +252,8 @@ function remap(inventory: any) {
248252
* TODO
249253
*/
250254
function findInInventory(inventory: any, $refParent: any, $refKey: any) {
251-
for (let i = 0; i < inventory.length; i++) {
252-
const existingEntry = inventory[i];
253-
if (existingEntry.parent === $refParent && existingEntry.key === $refKey) {
255+
for (const existingEntry of inventory) {
256+
if (existingEntry && existingEntry.parent === $refParent && existingEntry.key === $refKey) {
254257
return existingEntry;
255258
}
256259
}
@@ -260,3 +263,4 @@ function removeFromInventory(inventory: any, entry: any) {
260263
const index = inventory.indexOf(entry);
261264
inventory.splice(index, 1);
262265
}
266+
export default bundle;

lib/dereference.ts

+21-17
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ import Pointer from "./pointer.js";
33
import { ono } from "@jsdevtools/ono";
44
import * as url from "./util/url.js";
55
import type $Refs from "./refs.js";
6-
import type $RefParserOptions from "./options.js";
6+
import type { DereferenceOptions, ParserOptions } from "./options.js";
7+
import type { JSONSchema } from "./types";
8+
import type $RefParser from "./index";
79

810
export default dereference;
911

@@ -14,11 +16,14 @@ export default dereference;
1416
* @param parser
1517
* @param options
1618
*/
17-
function dereference(parser: any, options: any) {
19+
function dereference<S extends JSONSchema = JSONSchema, O extends ParserOptions = ParserOptions>(
20+
parser: $RefParser<S, O>,
21+
options: O,
22+
) {
1823
// console.log('Dereferencing $ref pointers in %s', parser.$refs._root$Ref.path);
19-
const dereferenced = crawl(
24+
const dereferenced = crawl<S, O>(
2025
parser.schema,
21-
parser.$refs._root$Ref.path,
26+
parser.$refs._root$Ref.path!,
2227
"#",
2328
new Set(),
2429
new Set(),
@@ -43,25 +48,26 @@ function dereference(parser: any, options: any) {
4348
* @param options
4449
* @returns
4550
*/
46-
function crawl(
51+
function crawl<S extends JSONSchema = JSONSchema, O extends ParserOptions = ParserOptions>(
4752
obj: any,
4853
path: string,
4954
pathFromRoot: string,
5055
parents: Set<any>,
5156
processedObjects: Set<any>,
5257
dereferencedCache: any,
53-
$refs: $Refs,
54-
options: $RefParserOptions,
58+
$refs: $Refs<S>,
59+
options: O,
5560
) {
5661
let dereferenced;
5762
const result = {
5863
value: obj,
5964
circular: false,
6065
};
6166

62-
const isExcludedPath = options.dereference.excludedPathMatcher || (() => false);
67+
const derefOptions = (options.dereference || {}) as DereferenceOptions;
68+
const isExcludedPath = derefOptions.excludedPathMatcher || (() => false);
6369

64-
if (options.dereference.circular === "ignore" || !processedObjects.has(obj)) {
70+
if (derefOptions?.circular === "ignore" || !processedObjects.has(obj)) {
6571
if (obj && typeof obj === "object" && !ArrayBuffer.isView(obj) && !isExcludedPath(pathFromRoot)) {
6672
parents.add(obj);
6773
processedObjects.add(obj);
@@ -106,9 +112,7 @@ function crawl(
106112
// Avoid pointless mutations; breaks frozen objects to no profit
107113
if (obj[key] !== dereferenced.value) {
108114
obj[key] = dereferenced.value;
109-
if (options.dereference.onDereference) {
110-
options.dereference.onDereference(value.$ref, obj[key], obj, key);
111-
}
115+
derefOptions?.onDereference?.(value.$ref, obj[key], obj, key);
112116
}
113117
} else {
114118
if (!parents.has(value)) {
@@ -157,18 +161,18 @@ function crawl(
157161
* @param options
158162
* @returns
159163
*/
160-
function dereference$Ref(
164+
function dereference$Ref<S extends JSONSchema = JSONSchema, O extends ParserOptions = ParserOptions>(
161165
$ref: any,
162166
path: string,
163167
pathFromRoot: string,
164168
parents: Set<any>,
165169
processedObjects: any,
166170
dereferencedCache: any,
167-
$refs: $Refs,
168-
options: $RefParserOptions,
171+
$refs: $Refs<S>,
172+
options: O,
169173
) {
170174
const isExternalRef = $Ref.isExternal$Ref($ref);
171-
const shouldResolveOnCwd = isExternalRef && options?.dereference.externalReferenceResolution === "root";
175+
const shouldResolveOnCwd = isExternalRef && options?.dereference?.externalReferenceResolution === "root";
172176
const $refPath = url.resolve(shouldResolveOnCwd ? url.cwd() : path, $ref.$ref);
173177

174178
const cache = dereferencedCache.get($refPath);
@@ -225,7 +229,7 @@ function dereference$Ref(
225229
dereferencedValue = dereferenced.value;
226230
}
227231

228-
if (circular && !directCircular && options.dereference.circular === "ignore") {
232+
if (circular && !directCircular && options.dereference?.circular === "ignore") {
229233
// The user has chosen to "ignore" circular references, so don't change the value
230234
dereferencedValue = $ref;
231235
}

0 commit comments

Comments
 (0)