@apidevtools/json-schema-ref-parser 12.0.0 → 12.0.2
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/README.md +6 -6
- package/dist/lib/bundle.js +4 -4
- package/dist/lib/dereference.js +36 -14
- package/dist/lib/pointer.js +1 -4
- package/dist/vite.config.js +1 -0
- package/lib/bundle.ts +10 -4
- package/lib/dereference.ts +35 -15
- package/lib/index.ts +1 -6
- package/lib/pointer.ts +1 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -57,12 +57,12 @@ JavaScript objects.
|
|
|
57
57
|
|
|
58
58
|
- Use **JSON** or **YAML** schemas — or even a mix of both!
|
|
59
59
|
- Supports `$ref` pointers to external files and URLs, as well
|
|
60
|
-
as [custom sources](https://
|
|
61
|
-
- Can [bundle](https://
|
|
60
|
+
as [custom sources](https://apidevtools.com/json-schema-ref-parser/docs/plugins/resolvers.html) such as databases
|
|
61
|
+
- Can [bundle](https://apidevtools.com/json-schema-ref-parser/docs/ref-parser.html#bundlepath-options-callback) multiple
|
|
62
62
|
files into a single schema that only has _internal_ `$ref` pointers
|
|
63
|
-
- Can [dereference](https://
|
|
63
|
+
- Can [dereference](https://apidevtools.com/json-schema-ref-parser/docs/ref-parser.html#dereferencepath-options-callback)
|
|
64
64
|
your schema, producing a plain-old JavaScript object that's easy to work with
|
|
65
|
-
- Supports [circular references](https://
|
|
65
|
+
- Supports [circular references](https://apidevtools.com/json-schema-ref-parser/docs/#circular-refs), nested references,
|
|
66
66
|
back-references, and cross-references between files
|
|
67
67
|
- Maintains object reference equality — `$ref` pointers to the same value always resolve to the same object
|
|
68
68
|
instance
|
|
@@ -86,7 +86,7 @@ try {
|
|
|
86
86
|
}
|
|
87
87
|
```
|
|
88
88
|
|
|
89
|
-
For more detailed examples, please see the [API Documentation](https://
|
|
89
|
+
For more detailed examples, please see the [API Documentation](https://apidevtools.com/json-schema-ref-parser/docs/)
|
|
90
90
|
|
|
91
91
|
## Polyfills
|
|
92
92
|
|
|
@@ -130,7 +130,7 @@ config.plugins.push(
|
|
|
130
130
|
|
|
131
131
|
## API Documentation
|
|
132
132
|
|
|
133
|
-
Full API documentation is available [right here](https://
|
|
133
|
+
Full API documentation is available [right here](https://apidevtools.com/json-schema-ref-parser/docs/)
|
|
134
134
|
|
|
135
135
|
## Contributing
|
|
136
136
|
|
package/dist/lib/bundle.js
CHANGED
|
@@ -80,10 +80,10 @@ function crawl(parent, key, path, pathFromRoot, indirections, inventory, $refs,
|
|
|
80
80
|
const keys = Object.keys(obj).sort((a, b) => {
|
|
81
81
|
// Most people will expect references to be bundled into the the "definitions" property,
|
|
82
82
|
// so we always crawl that property first, if it exists.
|
|
83
|
-
if (a === "definitions") {
|
|
83
|
+
if (a === "definitions" || a === "$defs") {
|
|
84
84
|
return -1;
|
|
85
85
|
}
|
|
86
|
-
else if (b === "definitions") {
|
|
86
|
+
else if (b === "definitions" || b === "$defs") {
|
|
87
87
|
return 1;
|
|
88
88
|
}
|
|
89
89
|
else {
|
|
@@ -214,8 +214,8 @@ function remap(inventory) {
|
|
|
214
214
|
else {
|
|
215
215
|
// Determine how far each $ref is from the "definitions" property.
|
|
216
216
|
// Most people will expect references to be bundled into the the "definitions" property if possible.
|
|
217
|
-
const aDefinitionsIndex = a.pathFromRoot.lastIndexOf("/definitions");
|
|
218
|
-
const bDefinitionsIndex = b.pathFromRoot.lastIndexOf("/definitions");
|
|
217
|
+
const aDefinitionsIndex = Math.max(a.pathFromRoot.lastIndexOf("/definitions"), a.pathFromRoot.lastIndexOf("/$defs"));
|
|
218
|
+
const bDefinitionsIndex = Math.max(b.pathFromRoot.lastIndexOf("/definitions"), b.pathFromRoot.lastIndexOf("/$defs"));
|
|
219
219
|
if (aDefinitionsIndex !== bDefinitionsIndex) {
|
|
220
220
|
// Give higher priority to the $ref that's closer to the "definitions" property
|
|
221
221
|
return bDefinitionsIndex - aDefinitionsIndex;
|
package/dist/lib/dereference.js
CHANGED
|
@@ -174,24 +174,46 @@ function dereference$Ref($ref, path, pathFromRoot, parents, processedObjects, de
|
|
|
174
174
|
//
|
|
175
175
|
// If the cached object however is _not_ circular and there are additional keys alongside our
|
|
176
176
|
// `$ref` pointer here we should merge them back in and return that.
|
|
177
|
-
if (cache.circular) {
|
|
177
|
+
if (!cache.circular) {
|
|
178
|
+
const refKeys = Object.keys($ref);
|
|
179
|
+
if (refKeys.length > 1) {
|
|
180
|
+
const extraKeys = {};
|
|
181
|
+
for (const key of refKeys) {
|
|
182
|
+
if (key !== "$ref" && !(key in cache.value)) {
|
|
183
|
+
// @ts-expect-error TS(7053): Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
|
|
184
|
+
extraKeys[key] = $ref[key];
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
return {
|
|
188
|
+
circular: cache.circular,
|
|
189
|
+
value: Object.assign({}, cache.value, extraKeys),
|
|
190
|
+
};
|
|
191
|
+
}
|
|
178
192
|
return cache;
|
|
179
193
|
}
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
194
|
+
// If both our cached value and our incoming `$ref` are the same then we can return what we
|
|
195
|
+
// got out of the cache, otherwise we should re-process this value. We need to do this because
|
|
196
|
+
// the current dereference caching mechanism doesn't take into account that `$ref` are neither
|
|
197
|
+
// unique or reference the same file.
|
|
198
|
+
//
|
|
199
|
+
// For example if `schema.yaml` references `definitions/child.yaml` and
|
|
200
|
+
// `definitions/parent.yaml` references `child.yaml` then `$ref: 'child.yaml'` may get cached
|
|
201
|
+
// for `definitions/child.yaml`, resulting in `schema.yaml` being having an invalid reference
|
|
202
|
+
// to `child.yaml`.
|
|
203
|
+
//
|
|
204
|
+
// This check is not perfect and the design of the dereference caching mechanism needs a total
|
|
205
|
+
// overhaul.
|
|
206
|
+
if (typeof cache.value === "object" && "$ref" in cache.value && "$ref" in $ref) {
|
|
207
|
+
if (cache.value.$ref === $ref.$ref) {
|
|
208
|
+
return cache;
|
|
209
|
+
}
|
|
210
|
+
else {
|
|
211
|
+
// no-op
|
|
188
212
|
}
|
|
189
|
-
return {
|
|
190
|
-
circular: cache.circular,
|
|
191
|
-
value: Object.assign({}, cache.value, extraKeys),
|
|
192
|
-
};
|
|
193
213
|
}
|
|
194
|
-
|
|
214
|
+
else {
|
|
215
|
+
return cache;
|
|
216
|
+
}
|
|
195
217
|
}
|
|
196
218
|
const pointer = $refs._resolve($refPath, path, options);
|
|
197
219
|
if (pointer === null) {
|
package/dist/lib/pointer.js
CHANGED
|
@@ -40,7 +40,7 @@ exports.nullSymbol = void 0;
|
|
|
40
40
|
const ref_js_1 = __importDefault(require("./ref.js"));
|
|
41
41
|
const url = __importStar(require("./util/url.js"));
|
|
42
42
|
const errors_js_1 = require("./util/errors.js");
|
|
43
|
-
exports.nullSymbol = Symbol(
|
|
43
|
+
exports.nullSymbol = Symbol("null");
|
|
44
44
|
const slashes = /\//g;
|
|
45
45
|
const tildes = /~/g;
|
|
46
46
|
const escapedSlash = /~1/g;
|
|
@@ -93,9 +93,6 @@ class Pointer {
|
|
|
93
93
|
// The $ref path has changed, so append the remaining tokens to the path
|
|
94
94
|
this.path = Pointer.join(this.path, tokens.slice(i));
|
|
95
95
|
}
|
|
96
|
-
if (typeof this.value === "object" && this.value !== null && !isRootPath(pathFromRoot) && "$ref" in this.value) {
|
|
97
|
-
return this;
|
|
98
|
-
}
|
|
99
96
|
const token = tokens[i];
|
|
100
97
|
if (this.value[token] === undefined || (this.value[token] === null && i === tokens.length - 1)) {
|
|
101
98
|
// one final case is if the entry itself includes slashes, and was parsed out as a token - we can join the remaining tokens and try again
|
package/dist/vite.config.js
CHANGED
package/lib/bundle.ts
CHANGED
|
@@ -76,9 +76,9 @@ function crawl<S extends object = JSONSchema, O extends ParserOptions<S> = Parse
|
|
|
76
76
|
const keys = Object.keys(obj).sort((a, b) => {
|
|
77
77
|
// Most people will expect references to be bundled into the the "definitions" property,
|
|
78
78
|
// so we always crawl that property first, if it exists.
|
|
79
|
-
if (a === "definitions") {
|
|
79
|
+
if (a === "definitions" || a === "$defs") {
|
|
80
80
|
return -1;
|
|
81
|
-
} else if (b === "definitions") {
|
|
81
|
+
} else if (b === "definitions" || b === "$defs") {
|
|
82
82
|
return 1;
|
|
83
83
|
} else {
|
|
84
84
|
// Otherwise, crawl the keys based on their length.
|
|
@@ -216,8 +216,14 @@ function remap(inventory: InventoryEntry[]) {
|
|
|
216
216
|
} else {
|
|
217
217
|
// Determine how far each $ref is from the "definitions" property.
|
|
218
218
|
// Most people will expect references to be bundled into the the "definitions" property if possible.
|
|
219
|
-
const aDefinitionsIndex =
|
|
220
|
-
|
|
219
|
+
const aDefinitionsIndex = Math.max(
|
|
220
|
+
a.pathFromRoot.lastIndexOf("/definitions"),
|
|
221
|
+
a.pathFromRoot.lastIndexOf("/$defs"),
|
|
222
|
+
);
|
|
223
|
+
const bDefinitionsIndex = Math.max(
|
|
224
|
+
b.pathFromRoot.lastIndexOf("/definitions"),
|
|
225
|
+
b.pathFromRoot.lastIndexOf("/$defs"),
|
|
226
|
+
);
|
|
221
227
|
|
|
222
228
|
if (aDefinitionsIndex !== bDefinitionsIndex) {
|
|
223
229
|
// Give higher priority to the $ref that's closer to the "definitions" property
|
package/lib/dereference.ts
CHANGED
|
@@ -220,26 +220,46 @@ function dereference$Ref<S extends object = JSONSchema, O extends ParserOptions<
|
|
|
220
220
|
//
|
|
221
221
|
// If the cached object however is _not_ circular and there are additional keys alongside our
|
|
222
222
|
// `$ref` pointer here we should merge them back in and return that.
|
|
223
|
-
if (cache.circular) {
|
|
223
|
+
if (!cache.circular) {
|
|
224
|
+
const refKeys = Object.keys($ref);
|
|
225
|
+
if (refKeys.length > 1) {
|
|
226
|
+
const extraKeys = {};
|
|
227
|
+
for (const key of refKeys) {
|
|
228
|
+
if (key !== "$ref" && !(key in cache.value)) {
|
|
229
|
+
// @ts-expect-error TS(7053): Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
|
|
230
|
+
extraKeys[key] = $ref[key];
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
return {
|
|
234
|
+
circular: cache.circular,
|
|
235
|
+
value: Object.assign({}, cache.value, extraKeys),
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
|
|
224
239
|
return cache;
|
|
225
240
|
}
|
|
226
241
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
242
|
+
// If both our cached value and our incoming `$ref` are the same then we can return what we
|
|
243
|
+
// got out of the cache, otherwise we should re-process this value. We need to do this because
|
|
244
|
+
// the current dereference caching mechanism doesn't take into account that `$ref` are neither
|
|
245
|
+
// unique or reference the same file.
|
|
246
|
+
//
|
|
247
|
+
// For example if `schema.yaml` references `definitions/child.yaml` and
|
|
248
|
+
// `definitions/parent.yaml` references `child.yaml` then `$ref: 'child.yaml'` may get cached
|
|
249
|
+
// for `definitions/child.yaml`, resulting in `schema.yaml` being having an invalid reference
|
|
250
|
+
// to `child.yaml`.
|
|
251
|
+
//
|
|
252
|
+
// This check is not perfect and the design of the dereference caching mechanism needs a total
|
|
253
|
+
// overhaul.
|
|
254
|
+
if (typeof cache.value === "object" && "$ref" in cache.value && "$ref" in $ref) {
|
|
255
|
+
if (cache.value.$ref === $ref.$ref) {
|
|
256
|
+
return cache;
|
|
257
|
+
} else {
|
|
258
|
+
// no-op
|
|
235
259
|
}
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
value: Object.assign({}, cache.value, extraKeys),
|
|
239
|
-
};
|
|
260
|
+
} else {
|
|
261
|
+
return cache;
|
|
240
262
|
}
|
|
241
|
-
|
|
242
|
-
return cache;
|
|
243
263
|
}
|
|
244
264
|
|
|
245
265
|
const pointer = $refs._resolve($refPath, path, options);
|
package/lib/index.ts
CHANGED
|
@@ -192,12 +192,7 @@ export class $RefParser<S extends object = JSONSchema, O extends ParserOptions<S
|
|
|
192
192
|
public resolve(schema: S | string | unknown, options: O): Promise<$Refs<S, O>>;
|
|
193
193
|
public resolve(schema: S | string | unknown, options: O, callback: $RefsCallback<S, O>): Promise<void>;
|
|
194
194
|
public resolve(path: string, schema: S | string | unknown, options: O): Promise<$Refs<S, O>>;
|
|
195
|
-
public resolve(
|
|
196
|
-
path: string,
|
|
197
|
-
schema: S | string | unknown,
|
|
198
|
-
options: O,
|
|
199
|
-
callback: $RefsCallback<S, O>,
|
|
200
|
-
): Promise<void>;
|
|
195
|
+
public resolve(path: string, schema: S | string | unknown, options: O, callback: $RefsCallback<S, O>): Promise<void>;
|
|
201
196
|
async resolve() {
|
|
202
197
|
const args = normalizeArgs<S, O>(arguments);
|
|
203
198
|
|
package/lib/pointer.ts
CHANGED
|
@@ -5,7 +5,7 @@ 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(
|
|
8
|
+
export const nullSymbol = Symbol("null");
|
|
9
9
|
|
|
10
10
|
const slashes = /\//g;
|
|
11
11
|
const tildes = /~/g;
|
|
@@ -101,10 +101,6 @@ class Pointer<S extends object = JSONSchema, O extends ParserOptions<S> = Parser
|
|
|
101
101
|
this.path = Pointer.join(this.path, tokens.slice(i));
|
|
102
102
|
}
|
|
103
103
|
|
|
104
|
-
if (typeof this.value === "object" && this.value !== null && !isRootPath(pathFromRoot) && "$ref" in this.value) {
|
|
105
|
-
return this;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
104
|
const token = tokens[i];
|
|
109
105
|
|
|
110
106
|
if (this.value[token] === undefined || (this.value[token] === null && i === tokens.length - 1)) {
|