@apidevtools/json-schema-ref-parser 11.9.2 → 12.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/dereference.js +24 -6
- package/dist/lib/pointer.d.ts +1 -0
- package/dist/lib/pointer.js +11 -0
- package/dist/lib/ref.js +42 -5
- package/lib/dereference.ts +32 -6
- package/lib/pointer.ts +12 -0
- package/lib/ref.ts +10 -2
- package/package.json +1 -1
package/dist/lib/dereference.js
CHANGED
|
@@ -76,11 +76,7 @@ function crawl(obj, path, pathFromRoot, parents, processedObjects, dereferencedC
|
|
|
76
76
|
value: obj,
|
|
77
77
|
circular: false,
|
|
78
78
|
};
|
|
79
|
-
|
|
80
|
-
if (Date.now() - startTime > options.timeoutMs) {
|
|
81
|
-
throw new errors_1.TimeoutError(options.timeoutMs);
|
|
82
|
-
}
|
|
83
|
-
}
|
|
79
|
+
checkDereferenceTimeout(startTime, options);
|
|
84
80
|
const derefOptions = (options.dereference || {});
|
|
85
81
|
const isExcludedPath = derefOptions.excludedPathMatcher || (() => false);
|
|
86
82
|
if (derefOptions?.circular === "ignore" || !processedObjects.has(obj)) {
|
|
@@ -94,6 +90,7 @@ function crawl(obj, path, pathFromRoot, parents, processedObjects, dereferencedC
|
|
|
94
90
|
}
|
|
95
91
|
else {
|
|
96
92
|
for (const key of Object.keys(obj)) {
|
|
93
|
+
checkDereferenceTimeout(startTime, options);
|
|
97
94
|
const keyPath = pointer_js_1.default.join(path, key);
|
|
98
95
|
const keyPathFromRoot = pointer_js_1.default.join(pathFromRoot, key);
|
|
99
96
|
if (isExcludedPath(keyPathFromRoot)) {
|
|
@@ -171,7 +168,15 @@ function dereference$Ref($ref, path, pathFromRoot, parents, processedObjects, de
|
|
|
171
168
|
const shouldResolveOnCwd = isExternalRef && options?.dereference?.externalReferenceResolution === "root";
|
|
172
169
|
const $refPath = url.resolve(shouldResolveOnCwd ? url.cwd() : path, $ref.$ref);
|
|
173
170
|
const cache = dereferencedCache.get($refPath);
|
|
174
|
-
if (cache
|
|
171
|
+
if (cache) {
|
|
172
|
+
// If the object we found is circular we can immediately return it because it would have been
|
|
173
|
+
// cached with everything we need already and we don't need to re-process anything inside it.
|
|
174
|
+
//
|
|
175
|
+
// If the cached object however is _not_ circular and there are additional keys alongside our
|
|
176
|
+
// `$ref` pointer here we should merge them back in and return that.
|
|
177
|
+
if (cache.circular) {
|
|
178
|
+
return cache;
|
|
179
|
+
}
|
|
175
180
|
const refKeys = Object.keys($ref);
|
|
176
181
|
if (refKeys.length > 1) {
|
|
177
182
|
const extraKeys = {};
|
|
@@ -229,6 +234,19 @@ function dereference$Ref($ref, path, pathFromRoot, parents, processedObjects, de
|
|
|
229
234
|
}
|
|
230
235
|
return dereferencedObject;
|
|
231
236
|
}
|
|
237
|
+
/**
|
|
238
|
+
* Check if we've run past our allowed timeout and throw an error if we have.
|
|
239
|
+
*
|
|
240
|
+
* @param startTime - The time when the dereferencing started.
|
|
241
|
+
* @param options
|
|
242
|
+
*/
|
|
243
|
+
function checkDereferenceTimeout(startTime, options) {
|
|
244
|
+
if (options && options.timeoutMs) {
|
|
245
|
+
if (Date.now() - startTime > options.timeoutMs) {
|
|
246
|
+
throw new errors_1.TimeoutError(options.timeoutMs);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
}
|
|
232
250
|
/**
|
|
233
251
|
* Called when a circular reference is found.
|
|
234
252
|
* It sets the {@link $Refs#circular} flag, executes the options.dereference.onCircular callback,
|
package/dist/lib/pointer.d.ts
CHANGED
package/dist/lib/pointer.js
CHANGED
|
@@ -36,9 +36,11 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
36
36
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
37
|
};
|
|
38
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.nullSymbol = void 0;
|
|
39
40
|
const ref_js_1 = __importDefault(require("./ref.js"));
|
|
40
41
|
const url = __importStar(require("./util/url.js"));
|
|
41
42
|
const errors_js_1 = require("./util/errors.js");
|
|
43
|
+
exports.nullSymbol = Symbol('null');
|
|
42
44
|
const slashes = /\//g;
|
|
43
45
|
const tildes = /~/g;
|
|
44
46
|
const escapedSlash = /~1/g;
|
|
@@ -110,6 +112,15 @@ class Pointer {
|
|
|
110
112
|
if (didFindSubstringSlashMatch) {
|
|
111
113
|
continue;
|
|
112
114
|
}
|
|
115
|
+
// If the token we're looking for ended up not containing any slashes but is
|
|
116
|
+
// actually instead pointing to an existing `null` value then we should use that
|
|
117
|
+
// `null` value.
|
|
118
|
+
if (token in this.value && this.value[token] === null) {
|
|
119
|
+
// We use a `null` symbol for internal tracking to differntiate between a general `null`
|
|
120
|
+
// value and our expected `null` value.
|
|
121
|
+
this.value = exports.nullSymbol;
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
113
124
|
this.value = null;
|
|
114
125
|
const path = this.$ref.path || "";
|
|
115
126
|
const targetRef = this.path.replace(path, "");
|
package/dist/lib/ref.js
CHANGED
|
@@ -1,9 +1,39 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
5
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
const pointer_js_1 =
|
|
36
|
+
const pointer_js_1 = __importStar(require("./pointer.js"));
|
|
7
37
|
const errors_js_1 = require("./util/errors.js");
|
|
8
38
|
const url_js_1 = require("./util/url.js");
|
|
9
39
|
/**
|
|
@@ -78,7 +108,11 @@ class $Ref {
|
|
|
78
108
|
resolve(path, options, friendlyPath, pathFromRoot) {
|
|
79
109
|
const pointer = new pointer_js_1.default(this, path, friendlyPath);
|
|
80
110
|
try {
|
|
81
|
-
|
|
111
|
+
const resolved = pointer.resolve(this.value, options, pathFromRoot);
|
|
112
|
+
if (resolved.value === pointer_js_1.nullSymbol) {
|
|
113
|
+
resolved.value = null;
|
|
114
|
+
}
|
|
115
|
+
return resolved;
|
|
82
116
|
}
|
|
83
117
|
catch (err) {
|
|
84
118
|
if (!options || !options.continueOnError || !(0, errors_js_1.isHandledError)(err)) {
|
|
@@ -104,6 +138,9 @@ class $Ref {
|
|
|
104
138
|
set(path, value) {
|
|
105
139
|
const pointer = new pointer_js_1.default(this, path);
|
|
106
140
|
this.value = pointer.set(this.value, value);
|
|
141
|
+
if (this.value === pointer_js_1.nullSymbol) {
|
|
142
|
+
this.value = null;
|
|
143
|
+
}
|
|
107
144
|
}
|
|
108
145
|
/**
|
|
109
146
|
* Determines whether the given value is a JSON reference.
|
package/lib/dereference.ts
CHANGED
|
@@ -69,11 +69,8 @@ function crawl<S extends object = JSONSchema, O extends ParserOptions<S> = Parse
|
|
|
69
69
|
circular: false,
|
|
70
70
|
};
|
|
71
71
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
throw new TimeoutError(options.timeoutMs);
|
|
75
|
-
}
|
|
76
|
-
}
|
|
72
|
+
checkDereferenceTimeout<S, O>(startTime, options);
|
|
73
|
+
|
|
77
74
|
const derefOptions = (options.dereference || {}) as DereferenceOptions;
|
|
78
75
|
const isExcludedPath = derefOptions.excludedPathMatcher || (() => false);
|
|
79
76
|
|
|
@@ -98,6 +95,8 @@ function crawl<S extends object = JSONSchema, O extends ParserOptions<S> = Parse
|
|
|
98
95
|
result.value = dereferenced.value;
|
|
99
96
|
} else {
|
|
100
97
|
for (const key of Object.keys(obj)) {
|
|
98
|
+
checkDereferenceTimeout<S, O>(startTime, options);
|
|
99
|
+
|
|
101
100
|
const keyPath = Pointer.join(path, key);
|
|
102
101
|
const keyPathFromRoot = Pointer.join(pathFromRoot, key);
|
|
103
102
|
|
|
@@ -214,7 +213,17 @@ function dereference$Ref<S extends object = JSONSchema, O extends ParserOptions<
|
|
|
214
213
|
const $refPath = url.resolve(shouldResolveOnCwd ? url.cwd() : path, $ref.$ref);
|
|
215
214
|
|
|
216
215
|
const cache = dereferencedCache.get($refPath);
|
|
217
|
-
|
|
216
|
+
|
|
217
|
+
if (cache) {
|
|
218
|
+
// If the object we found is circular we can immediately return it because it would have been
|
|
219
|
+
// cached with everything we need already and we don't need to re-process anything inside it.
|
|
220
|
+
//
|
|
221
|
+
// If the cached object however is _not_ circular and there are additional keys alongside our
|
|
222
|
+
// `$ref` pointer here we should merge them back in and return that.
|
|
223
|
+
if (cache.circular) {
|
|
224
|
+
return cache;
|
|
225
|
+
}
|
|
226
|
+
|
|
218
227
|
const refKeys = Object.keys($ref);
|
|
219
228
|
if (refKeys.length > 1) {
|
|
220
229
|
const extraKeys = {};
|
|
@@ -294,6 +303,23 @@ function dereference$Ref<S extends object = JSONSchema, O extends ParserOptions<
|
|
|
294
303
|
return dereferencedObject;
|
|
295
304
|
}
|
|
296
305
|
|
|
306
|
+
/**
|
|
307
|
+
* Check if we've run past our allowed timeout and throw an error if we have.
|
|
308
|
+
*
|
|
309
|
+
* @param startTime - The time when the dereferencing started.
|
|
310
|
+
* @param options
|
|
311
|
+
*/
|
|
312
|
+
function checkDereferenceTimeout<S extends object = JSONSchema, O extends ParserOptions<S> = ParserOptions<S>>(
|
|
313
|
+
startTime: number,
|
|
314
|
+
options: O,
|
|
315
|
+
): void {
|
|
316
|
+
if (options && options.timeoutMs) {
|
|
317
|
+
if (Date.now() - startTime > options.timeoutMs) {
|
|
318
|
+
throw new TimeoutError(options.timeoutMs);
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
297
323
|
/**
|
|
298
324
|
* Called when a circular reference is found.
|
|
299
325
|
* It sets the {@link $Refs#circular} flag, executes the options.dereference.onCircular callback,
|
package/lib/pointer.ts
CHANGED
|
@@ -5,6 +5,8 @@ import * as url from "./util/url.js";
|
|
|
5
5
|
import { JSONParserError, InvalidPointerError, MissingPointerError, isHandledError } from "./util/errors.js";
|
|
6
6
|
import type { JSONSchema } from "./types";
|
|
7
7
|
|
|
8
|
+
export const nullSymbol = Symbol('null');
|
|
9
|
+
|
|
8
10
|
const slashes = /\//g;
|
|
9
11
|
const tildes = /~/g;
|
|
10
12
|
const escapedSlash = /~1/g;
|
|
@@ -121,6 +123,16 @@ class Pointer<S extends object = JSONSchema, O extends ParserOptions<S> = Parser
|
|
|
121
123
|
continue;
|
|
122
124
|
}
|
|
123
125
|
|
|
126
|
+
// If the token we're looking for ended up not containing any slashes but is
|
|
127
|
+
// actually instead pointing to an existing `null` value then we should use that
|
|
128
|
+
// `null` value.
|
|
129
|
+
if (token in this.value && this.value[token] === null) {
|
|
130
|
+
// We use a `null` symbol for internal tracking to differntiate between a general `null`
|
|
131
|
+
// value and our expected `null` value.
|
|
132
|
+
this.value = nullSymbol;
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
135
|
+
|
|
124
136
|
this.value = null;
|
|
125
137
|
|
|
126
138
|
const path = this.$ref.path || "";
|
package/lib/ref.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import Pointer from "./pointer.js";
|
|
1
|
+
import Pointer, { nullSymbol } from "./pointer.js";
|
|
2
2
|
import type { JSONParserError, MissingPointerError, ParserError, ResolverError } from "./util/errors.js";
|
|
3
3
|
import { InvalidPointerError, isHandledError, normalizeError } from "./util/errors.js";
|
|
4
4
|
import { safePointerToPath, stripHash, getHash } from "./util/url.js";
|
|
@@ -119,7 +119,12 @@ class $Ref<S extends object = JSONSchema, O extends ParserOptions<S> = ParserOpt
|
|
|
119
119
|
resolve(path: string, options?: O, friendlyPath?: string, pathFromRoot?: string) {
|
|
120
120
|
const pointer = new Pointer<S, O>(this, path, friendlyPath);
|
|
121
121
|
try {
|
|
122
|
-
|
|
122
|
+
const resolved = pointer.resolve(this.value, options, pathFromRoot);
|
|
123
|
+
if (resolved.value === nullSymbol) {
|
|
124
|
+
resolved.value = null;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
return resolved;
|
|
123
128
|
} catch (err: any) {
|
|
124
129
|
if (!options || !options.continueOnError || !isHandledError(err)) {
|
|
125
130
|
throw err;
|
|
@@ -148,6 +153,9 @@ class $Ref<S extends object = JSONSchema, O extends ParserOptions<S> = ParserOpt
|
|
|
148
153
|
set(path: string, value: any) {
|
|
149
154
|
const pointer = new Pointer(this, path);
|
|
150
155
|
this.value = pointer.set(this.value, value);
|
|
156
|
+
if (this.value === nullSymbol) {
|
|
157
|
+
this.value = null;
|
|
158
|
+
}
|
|
151
159
|
}
|
|
152
160
|
|
|
153
161
|
/**
|