@apidevtools/json-schema-ref-parser 12.0.1 → 13.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/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://apitools.dev/json-schema-ref-parser/docs/plugins/resolvers.html) such as databases
61
- - Can [bundle](https://apitools.dev/json-schema-ref-parser/docs/ref-parser.html#bundlepath-options-callback) multiple
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://apitools.dev/json-schema-ref-parser/docs/ref-parser.html#dereferencepath-options-callback)
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://apitools.dev/json-schema-ref-parser/docs/#circular-refs), nested references,
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://apitools.dev/json-schema-ref-parser/docs/)
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://apitools.dev/json-schema-ref-parser/docs/)
133
+ Full API documentation is available [right here](https://apidevtools.com/json-schema-ref-parser/docs/)
134
134
 
135
135
  ## Contributing
136
136
 
@@ -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;
@@ -38,7 +38,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
38
38
  Object.defineProperty(exports, "__esModule", { value: true });
39
39
  const ref_js_1 = __importDefault(require("./ref.js"));
40
40
  const pointer_js_1 = __importDefault(require("./pointer.js"));
41
- const ono_1 = require("@jsdevtools/ono");
42
41
  const url = __importStar(require("./util/url.js"));
43
42
  const errors_1 = require("./util/errors");
44
43
  exports.default = dereference;
@@ -203,7 +202,7 @@ function dereference$Ref($ref, path, pathFromRoot, parents, processedObjects, de
203
202
  //
204
203
  // This check is not perfect and the design of the dereference caching mechanism needs a total
205
204
  // overhaul.
206
- if (typeof cache.value === 'object' && '$ref' in cache.value && '$ref' in $ref) {
205
+ if (typeof cache.value === "object" && "$ref" in cache.value && "$ref" in $ref) {
207
206
  if (cache.value.$ref === $ref.$ref) {
208
207
  return cache;
209
208
  }
@@ -283,7 +282,8 @@ function foundCircularReference(keyPath, $refs, options) {
283
282
  $refs.circular = true;
284
283
  options?.dereference?.onCircular?.(keyPath);
285
284
  if (!options.dereference.circular) {
286
- throw ono_1.ono.reference(`Circular $ref pointer found at ${keyPath}`);
285
+ const error = new ReferenceError(`Circular $ref pointer found at ${keyPath}`);
286
+ throw error;
287
287
  }
288
288
  return true;
289
289
  }
package/dist/lib/index.js CHANGED
@@ -56,7 +56,6 @@ Object.defineProperty(exports, "UnmatchedParserError", { enumerable: true, get:
56
56
  Object.defineProperty(exports, "UnmatchedResolverError", { enumerable: true, get: function () { return errors_js_1.UnmatchedResolverError; } });
57
57
  Object.defineProperty(exports, "isHandledError", { enumerable: true, get: function () { return errors_js_1.isHandledError; } });
58
58
  Object.defineProperty(exports, "JSONParserErrorGroup", { enumerable: true, get: function () { return errors_js_1.JSONParserErrorGroup; } });
59
- const ono_1 = require("@jsdevtools/ono");
60
59
  const maybe_js_1 = __importDefault(require("./util/maybe.js"));
61
60
  const options_js_1 = require("./options.js");
62
61
  Object.defineProperty(exports, "getJsonSchemaRefParserDefaultOptions", { enumerable: true, get: function () { return options_js_1.getJsonSchemaRefParserDefaultOptions; } });
@@ -87,7 +86,7 @@ class $RefParser {
87
86
  const args = (0, normalize_args_js_1.default)(arguments);
88
87
  let promise;
89
88
  if (!args.path && !args.schema) {
90
- const err = (0, ono_1.ono)(`Expected a file path, URL, or object. Got ${args.path || args.schema}`);
89
+ const err = new Error(`Expected a file path, URL, or object. Got ${args.path || args.schema}`);
91
90
  return (0, maybe_js_1.default)(args.callback, Promise.reject(err));
92
91
  }
93
92
  // Reset everything
@@ -136,7 +135,7 @@ class $RefParser {
136
135
  return (0, maybe_js_1.default)(args.callback, Promise.resolve(this.schema));
137
136
  }
138
137
  else {
139
- throw ono_1.ono.syntax(`"${this.$refs._root$Ref.path || result}" is not a valid JSON Schema`);
138
+ throw new SyntaxError(`"${this.$refs._root$Ref.path || result}" is not a valid JSON Schema`);
140
139
  }
141
140
  }
142
141
  catch (err) {
@@ -105,300 +105,7 @@ export interface $RefParserOptions<S extends object = JSONSchema> {
105
105
  timeoutMs?: number;
106
106
  }
107
107
  export declare const getJsonSchemaRefParserDefaultOptions: () => $RefParserOptions<JSONSchema>;
108
- export declare const getNewOptions: <S extends object = JSONSchema, O extends ParserOptions<S> = {
109
- parse?: {
110
- [x: string]: boolean | {
111
- name?: string | undefined;
112
- order?: number | undefined;
113
- allowEmpty?: boolean | undefined;
114
- allowBOM?: boolean | undefined;
115
- encoding?: BufferEncoding | undefined;
116
- canParse?: string | boolean | {
117
- exec?: {} | undefined;
118
- test?: {} | undefined;
119
- readonly source?: string | undefined;
120
- readonly global?: boolean | undefined;
121
- readonly ignoreCase?: boolean | undefined;
122
- readonly multiline?: boolean | undefined;
123
- lastIndex?: number | undefined;
124
- compile?: {} | undefined;
125
- readonly flags?: string | undefined;
126
- readonly sticky?: boolean | undefined;
127
- readonly unicode?: boolean | undefined;
128
- readonly dotAll?: boolean | undefined;
129
- readonly hasIndices?: boolean | undefined;
130
- readonly unicodeSets?: boolean | undefined;
131
- [Symbol.match]?: {} | undefined;
132
- [Symbol.replace]?: {} | undefined;
133
- [Symbol.search]?: {} | undefined;
134
- [Symbol.split]?: {} | undefined;
135
- [Symbol.matchAll]?: {} | undefined;
136
- } | (string | undefined)[] | {} | undefined;
137
- parse?: string | number | {} | undefined;
138
- } | undefined;
139
- json?: boolean | {
140
- name?: string | undefined;
141
- order?: number | undefined;
142
- allowEmpty?: boolean | undefined;
143
- allowBOM?: boolean | undefined;
144
- encoding?: BufferEncoding | undefined;
145
- canParse?: string | boolean | {
146
- exec?: {} | undefined;
147
- test?: {} | undefined;
148
- readonly source?: string | undefined;
149
- readonly global?: boolean | undefined;
150
- readonly ignoreCase?: boolean | undefined;
151
- readonly multiline?: boolean | undefined;
152
- lastIndex?: number | undefined;
153
- compile?: {} | undefined;
154
- readonly flags?: string | undefined;
155
- readonly sticky?: boolean | undefined;
156
- readonly unicode?: boolean | undefined;
157
- readonly dotAll?: boolean | undefined;
158
- readonly hasIndices?: boolean | undefined;
159
- readonly unicodeSets?: boolean | undefined;
160
- [Symbol.match]?: {} | undefined;
161
- [Symbol.replace]?: {} | undefined;
162
- [Symbol.search]?: {} | undefined;
163
- [Symbol.split]?: {} | undefined;
164
- [Symbol.matchAll]?: {} | undefined;
165
- } | (string | undefined)[] | {} | undefined;
166
- parse?: string | number | {} | undefined;
167
- } | undefined;
168
- yaml?: boolean | {
169
- name?: string | undefined;
170
- order?: number | undefined;
171
- allowEmpty?: boolean | undefined;
172
- allowBOM?: boolean | undefined;
173
- encoding?: BufferEncoding | undefined;
174
- canParse?: string | boolean | {
175
- exec?: {} | undefined;
176
- test?: {} | undefined;
177
- readonly source?: string | undefined;
178
- readonly global?: boolean | undefined;
179
- readonly ignoreCase?: boolean | undefined;
180
- readonly multiline?: boolean | undefined;
181
- lastIndex?: number | undefined;
182
- compile?: {} | undefined;
183
- readonly flags?: string | undefined;
184
- readonly sticky?: boolean | undefined;
185
- readonly unicode?: boolean | undefined;
186
- readonly dotAll?: boolean | undefined;
187
- readonly hasIndices?: boolean | undefined;
188
- readonly unicodeSets?: boolean | undefined;
189
- [Symbol.match]?: {} | undefined;
190
- [Symbol.replace]?: {} | undefined;
191
- [Symbol.search]?: {} | undefined;
192
- [Symbol.split]?: {} | undefined;
193
- [Symbol.matchAll]?: {} | undefined;
194
- } | (string | undefined)[] | {} | undefined;
195
- parse?: string | number | {} | undefined;
196
- } | undefined;
197
- binary?: boolean | {
198
- name?: string | undefined;
199
- order?: number | undefined;
200
- allowEmpty?: boolean | undefined;
201
- allowBOM?: boolean | undefined;
202
- encoding?: BufferEncoding | undefined;
203
- canParse?: string | boolean | {
204
- exec?: {} | undefined;
205
- test?: {} | undefined;
206
- readonly source?: string | undefined;
207
- readonly global?: boolean | undefined;
208
- readonly ignoreCase?: boolean | undefined;
209
- readonly multiline?: boolean | undefined;
210
- lastIndex?: number | undefined;
211
- compile?: {} | undefined;
212
- readonly flags?: string | undefined;
213
- readonly sticky?: boolean | undefined;
214
- readonly unicode?: boolean | undefined;
215
- readonly dotAll?: boolean | undefined;
216
- readonly hasIndices?: boolean | undefined;
217
- readonly unicodeSets?: boolean | undefined;
218
- [Symbol.match]?: {} | undefined;
219
- [Symbol.replace]?: {} | undefined;
220
- [Symbol.search]?: {} | undefined;
221
- [Symbol.split]?: {} | undefined;
222
- [Symbol.matchAll]?: {} | undefined;
223
- } | (string | undefined)[] | {} | undefined;
224
- parse?: string | number | {} | undefined;
225
- } | undefined;
226
- text?: boolean | {
227
- name?: string | undefined;
228
- order?: number | undefined;
229
- allowEmpty?: boolean | undefined;
230
- allowBOM?: boolean | undefined;
231
- encoding?: BufferEncoding | undefined;
232
- canParse?: string | boolean | {
233
- exec?: {} | undefined;
234
- test?: {} | undefined;
235
- readonly source?: string | undefined;
236
- readonly global?: boolean | undefined;
237
- readonly ignoreCase?: boolean | undefined;
238
- readonly multiline?: boolean | undefined;
239
- lastIndex?: number | undefined;
240
- compile?: {} | undefined;
241
- readonly flags?: string | undefined;
242
- readonly sticky?: boolean | undefined;
243
- readonly unicode?: boolean | undefined;
244
- readonly dotAll?: boolean | undefined;
245
- readonly hasIndices?: boolean | undefined;
246
- readonly unicodeSets?: boolean | undefined;
247
- [Symbol.match]?: {} | undefined;
248
- [Symbol.replace]?: {} | undefined;
249
- [Symbol.search]?: {} | undefined;
250
- [Symbol.split]?: {} | undefined;
251
- [Symbol.matchAll]?: {} | undefined;
252
- } | (string | undefined)[] | {} | undefined;
253
- parse?: string | number | {} | undefined;
254
- } | undefined;
255
- } | undefined;
256
- resolve?: {
257
- [x: string]: boolean | {
258
- name?: string | undefined;
259
- order?: number | undefined;
260
- canRead?: string | boolean | {
261
- exec?: {} | undefined;
262
- test?: {} | undefined;
263
- readonly source?: string | undefined;
264
- readonly global?: boolean | undefined;
265
- readonly ignoreCase?: boolean | undefined;
266
- readonly multiline?: boolean | undefined;
267
- lastIndex?: number | undefined;
268
- compile?: {} | undefined;
269
- readonly flags?: string | undefined;
270
- readonly sticky?: boolean | undefined;
271
- readonly unicode?: boolean | undefined;
272
- readonly dotAll?: boolean | undefined;
273
- readonly hasIndices?: boolean | undefined;
274
- readonly unicodeSets?: boolean | undefined;
275
- [Symbol.match]?: {} | undefined;
276
- [Symbol.replace]?: {} | undefined;
277
- [Symbol.search]?: {} | undefined;
278
- [Symbol.split]?: {} | undefined;
279
- [Symbol.matchAll]?: {} | undefined;
280
- } | (string | undefined)[] | {} | undefined;
281
- read?: string | object | {} | undefined;
282
- } | {
283
- headers?: ([(string | undefined)?, (string | undefined)?] | undefined)[] | {
284
- [x: string]: string | undefined;
285
- } | {
286
- append?: {} | undefined;
287
- delete?: {} | undefined;
288
- get?: {} | undefined;
289
- getSetCookie?: {} | undefined;
290
- has?: {} | undefined;
291
- set?: {} | undefined;
292
- forEach?: {} | undefined;
293
- } | null | undefined;
294
- timeout?: number | undefined;
295
- redirects?: number | undefined;
296
- withCredentials?: boolean | undefined;
297
- name?: string | undefined;
298
- order?: number | undefined;
299
- canRead?: string | boolean | {
300
- exec?: {} | undefined;
301
- test?: {} | undefined;
302
- readonly source?: string | undefined;
303
- readonly global?: boolean | undefined;
304
- readonly ignoreCase?: boolean | undefined;
305
- readonly multiline?: boolean | undefined;
306
- lastIndex?: number | undefined;
307
- compile?: {} | undefined;
308
- readonly flags?: string | undefined;
309
- readonly sticky?: boolean | undefined;
310
- readonly unicode?: boolean | undefined;
311
- readonly dotAll?: boolean | undefined;
312
- readonly hasIndices?: boolean | undefined;
313
- readonly unicodeSets?: boolean | undefined;
314
- [Symbol.match]?: {} | undefined;
315
- [Symbol.replace]?: {} | undefined;
316
- [Symbol.search]?: {} | undefined;
317
- [Symbol.split]?: {} | undefined;
318
- [Symbol.matchAll]?: {} | undefined;
319
- } | (string | undefined)[] | {} | undefined;
320
- read?: string | object | {} | undefined;
321
- } | undefined;
322
- external?: boolean | undefined;
323
- file?: boolean | {
324
- name?: string | undefined;
325
- order?: number | undefined;
326
- canRead?: string | boolean | {
327
- exec?: {} | undefined;
328
- test?: {} | undefined;
329
- readonly source?: string | undefined;
330
- readonly global?: boolean | undefined;
331
- readonly ignoreCase?: boolean | undefined;
332
- readonly multiline?: boolean | undefined;
333
- lastIndex?: number | undefined;
334
- compile?: {} | undefined;
335
- readonly flags?: string | undefined;
336
- readonly sticky?: boolean | undefined;
337
- readonly unicode?: boolean | undefined;
338
- readonly dotAll?: boolean | undefined;
339
- readonly hasIndices?: boolean | undefined;
340
- readonly unicodeSets?: boolean | undefined;
341
- [Symbol.match]?: {} | undefined;
342
- [Symbol.replace]?: {} | undefined;
343
- [Symbol.search]?: {} | undefined;
344
- [Symbol.split]?: {} | undefined;
345
- [Symbol.matchAll]?: {} | undefined;
346
- } | (string | undefined)[] | {} | undefined;
347
- read?: string | object | {} | undefined;
348
- } | undefined;
349
- http?: boolean | {
350
- headers?: ([(string | undefined)?, (string | undefined)?] | undefined)[] | {
351
- [x: string]: string | undefined;
352
- } | {
353
- append?: {} | undefined;
354
- delete?: {} | undefined;
355
- get?: {} | undefined;
356
- getSetCookie?: {} | undefined;
357
- has?: {} | undefined;
358
- set?: {} | undefined;
359
- forEach?: {} | undefined;
360
- } | null | undefined;
361
- timeout?: number | undefined;
362
- redirects?: number | undefined;
363
- withCredentials?: boolean | undefined;
364
- name?: string | undefined;
365
- order?: number | undefined;
366
- canRead?: string | boolean | {
367
- exec?: {} | undefined;
368
- test?: {} | undefined;
369
- readonly source?: string | undefined;
370
- readonly global?: boolean | undefined;
371
- readonly ignoreCase?: boolean | undefined;
372
- readonly multiline?: boolean | undefined;
373
- lastIndex?: number | undefined;
374
- compile?: {} | undefined;
375
- readonly flags?: string | undefined;
376
- readonly sticky?: boolean | undefined;
377
- readonly unicode?: boolean | undefined;
378
- readonly dotAll?: boolean | undefined;
379
- readonly hasIndices?: boolean | undefined;
380
- readonly unicodeSets?: boolean | undefined;
381
- [Symbol.match]?: {} | undefined;
382
- [Symbol.replace]?: {} | undefined;
383
- [Symbol.search]?: {} | undefined;
384
- [Symbol.split]?: {} | undefined;
385
- [Symbol.matchAll]?: {} | undefined;
386
- } | (string | undefined)[] | {} | undefined;
387
- read?: string | object | {} | undefined;
388
- } | undefined;
389
- } | undefined;
390
- continueOnError?: boolean | undefined;
391
- dereference?: {
392
- circular?: boolean | "ignore" | undefined;
393
- excludedPathMatcher?: {} | undefined;
394
- onCircular?: {} | undefined;
395
- onDereference?: {} | undefined;
396
- preservedProperties?: (string | undefined)[] | undefined;
397
- externalReferenceResolution?: "relative" | "root" | undefined;
398
- } | undefined;
399
- mutateInputSchema?: boolean | undefined;
400
- timeoutMs?: number | undefined;
401
- }>(options: O | undefined) => O & $RefParserOptions<S>;
108
+ export declare const getNewOptions: <S extends object = JSONSchema, O extends ParserOptions<S> = ParserOptions<S>>(options: O | undefined) => O & $RefParserOptions<S>;
402
109
  export type Options<S extends object = JSONSchema> = $RefParserOptions<S>;
403
110
  export type ParserOptions<S extends object = JSONSchema> = DeepPartial<$RefParserOptions<S>>;
404
111
  export default $RefParserOptions;
package/dist/lib/parse.js CHANGED
@@ -33,7 +33,6 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
- const ono_1 = require("@jsdevtools/ono");
37
36
  const url = __importStar(require("./util/url.js"));
38
37
  const plugins = __importStar(require("./util/plugins.js"));
39
38
  const errors_js_1 = require("./util/errors.js");
@@ -103,7 +102,7 @@ async function readFile(file, options, $refs) {
103
102
  }
104
103
  else if (!err || !("error" in err)) {
105
104
  // Throw a generic, friendly error.
106
- throw ono_1.ono.syntax(`Unable to resolve $ref pointer "${file.url}"`);
105
+ throw new SyntaxError(`Unable to resolve $ref pointer "${file.url}"`);
107
106
  }
108
107
  // Throw the original error, if it's one of our own (user-friendly) errors.
109
108
  else if (err.error instanceof errors_js_1.ResolverError) {
@@ -139,7 +138,7 @@ async function parseFile(file, options, $refs) {
139
138
  try {
140
139
  const parser = await plugins.run(parsers, "parse", file, $refs);
141
140
  if (!parser.plugin.allowEmpty && isEmpty(parser.result)) {
142
- throw ono_1.ono.syntax(`Error parsing "${file.url}" as ${parser.plugin.name}. \nParsed value is empty`);
141
+ throw new SyntaxError(`Error parsing "${file.url}" as ${parser.plugin.name}. \nParsed value is empty`);
143
142
  }
144
143
  else {
145
144
  return parser;
@@ -154,7 +153,7 @@ async function parseFile(file, options, $refs) {
154
153
  throw err;
155
154
  }
156
155
  else if (!err || !("error" in err)) {
157
- throw ono_1.ono.syntax(`Unable to parse ${file.url}`);
156
+ throw new SyntaxError(`Unable to parse ${file.url}`);
158
157
  }
159
158
  else if (err.error instanceof errors_js_1.ParserError) {
160
159
  throw err.error;
@@ -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('null');
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/lib/refs.js CHANGED
@@ -36,7 +36,6 @@ 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
- const ono_1 = require("@jsdevtools/ono");
40
39
  const ref_js_1 = __importDefault(require("./ref.js"));
41
40
  const url = __importStar(require("./util/url.js"));
42
41
  const convert_path_to_posix_1 = __importDefault(require("./util/convert-path-to-posix"));
@@ -120,7 +119,7 @@ class $Refs {
120
119
  const withoutHash = url.stripHash(absPath);
121
120
  const $ref = this._$refs[withoutHash];
122
121
  if (!$ref) {
123
- throw (0, ono_1.ono)(`Error resolving $ref pointer "${path}". \n"${withoutHash}" not found.`);
122
+ throw new Error(`Error resolving $ref pointer "${path}". \n"${withoutHash}" not found.`);
124
123
  }
125
124
  $ref.set(absPath, value);
126
125
  }
@@ -163,7 +162,7 @@ class $Refs {
163
162
  const withoutHash = url.stripHash(absPath);
164
163
  const $ref = this._$refs[withoutHash];
165
164
  if (!$ref) {
166
- throw (0, ono_1.ono)(`Error resolving $ref pointer "${path}". \n"${withoutHash}" not found.`);
165
+ throw new Error(`Error resolving $ref pointer "${path}". \n"${withoutHash}" not found.`);
167
166
  }
168
167
  return $ref.resolve(absPath, options, path, pathFromRoot);
169
168
  }
@@ -37,7 +37,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
37
37
  };
38
38
  Object.defineProperty(exports, "__esModule", { value: true });
39
39
  const fs_1 = __importDefault(require("fs"));
40
- const ono_1 = require("@jsdevtools/ono");
41
40
  const url = __importStar(require("../util/url.js"));
42
41
  const errors_js_1 = require("../util/errors.js");
43
42
  exports.default = {
@@ -62,13 +61,17 @@ exports.default = {
62
61
  path = url.toFileSystemPath(file.url);
63
62
  }
64
63
  catch (err) {
65
- throw new errors_js_1.ResolverError(ono_1.ono.uri(err, `Malformed URI: ${file.url}`), file.url);
64
+ const e = err;
65
+ e.message = `Malformed URI: ${file.url}: ${e.message}`;
66
+ throw new errors_js_1.ResolverError(e, file.url);
66
67
  }
67
68
  try {
68
69
  return await fs_1.default.promises.readFile(path);
69
70
  }
70
71
  catch (err) {
71
- throw new errors_js_1.ResolverError((0, ono_1.ono)(err, `Error opening file "${path}"`), path);
72
+ const e = err;
73
+ e.message = `Error opening file ${path}: ${e.message}`;
74
+ throw new errors_js_1.ResolverError(e, path);
72
75
  }
73
76
  },
74
77
  };
@@ -33,7 +33,6 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
- const ono_1 = require("@jsdevtools/ono");
37
36
  const url = __importStar(require("../util/url.js"));
38
37
  const errors_js_1 = require("../util/errors.js");
39
38
  exports.default = {
@@ -97,14 +96,20 @@ async function download(u, httpOptions, _redirects) {
97
96
  try {
98
97
  const res = await get(u, httpOptions);
99
98
  if (res.status >= 400) {
100
- throw (0, ono_1.ono)({ status: res.status }, `HTTP ERROR ${res.status}`);
99
+ const error = new Error(`HTTP ERROR ${res.status}`);
100
+ error.status = res.status;
101
+ throw error;
101
102
  }
102
103
  else if (res.status >= 300) {
103
104
  if (!Number.isNaN(httpOptions.redirects) && redirects.length > httpOptions.redirects) {
104
- throw new errors_js_1.ResolverError((0, ono_1.ono)({ status: res.status }, `Error downloading ${redirects[0]}. \nToo many redirects: \n ${redirects.join(" \n ")}`));
105
+ const error = new Error(`Error downloading ${redirects[0]}. \nToo many redirects: \n ${redirects.join(" \n ")}`);
106
+ error.status = res.status;
107
+ throw new errors_js_1.ResolverError(error);
105
108
  }
106
109
  else if (!("location" in res.headers) || !res.headers.location) {
107
- throw (0, ono_1.ono)({ status: res.status }, `HTTP ${res.status} redirect with no location header`);
110
+ const error = new Error(`HTTP ${res.status} redirect with no location header`);
111
+ error.status = res.status;
112
+ throw error;
108
113
  }
109
114
  else {
110
115
  const redirectTo = url.resolve(u.href, res.headers.location);
@@ -120,7 +125,9 @@ async function download(u, httpOptions, _redirects) {
120
125
  }
121
126
  }
122
127
  catch (err) {
123
- throw new errors_js_1.ResolverError((0, ono_1.ono)(err, `Error downloading ${u.href}`), u.href);
128
+ const e = err;
129
+ e.message = `Error downloading ${u.href}: ${e.message}`;
130
+ throw new errors_js_1.ResolverError(e, u.href);
124
131
  }
125
132
  }
126
133
  /**
@@ -2,6 +2,16 @@ import type $RefParser from "../index.js";
2
2
  import type { ParserOptions } from "../index.js";
3
3
  import type { JSONSchema } from "../index.js";
4
4
  export type JSONParserErrorType = "EUNKNOWN" | "EPARSER" | "EUNMATCHEDPARSER" | "ETIMEOUT" | "ERESOLVER" | "EUNMATCHEDRESOLVER" | "EMISSINGPOINTER" | "EINVALIDPOINTER";
5
+ /**
6
+ * Custom JSON serializer for Error objects.
7
+ * Returns all built-in error properties, as well as extended properties.
8
+ */
9
+ export declare function toJSON<T extends Error>(this: T): Error & T;
10
+ /**
11
+ * Returns own, inherited, enumerable, non-enumerable, string, and symbol keys of `obj`.
12
+ * Does NOT return members of the base Object prototype, or the specified omitted keys.
13
+ */
14
+ export declare function getDeepKeys(obj: object, omit?: Array<string | symbol>): Set<string | symbol>;
5
15
  export declare class JSONParserError extends Error {
6
16
  readonly name: string;
7
17
  readonly message: string;
@@ -9,11 +19,13 @@ export declare class JSONParserError extends Error {
9
19
  path: Array<string | number> | null;
10
20
  readonly code: JSONParserErrorType;
11
21
  constructor(message: string, source?: string);
22
+ toJSON: () => Error;
12
23
  get footprint(): string;
13
24
  }
14
25
  export declare class JSONParserErrorGroup<S extends object = JSONSchema, O extends ParserOptions<S> = ParserOptions<S>> extends Error {
15
26
  files: $RefParser<S, O>;
16
27
  constructor(parser: $RefParser<S, O>);
28
+ toJSON: () => Error;
17
29
  static getParserErrors<S extends object = JSONSchema, O extends ParserOptions<S> = ParserOptions<S>>(parser: $RefParser<S, O>): JSONParserError[];
18
30
  get errors(): Array<JSONParserError | InvalidPointerError | ResolverError | ParserError | MissingPointerError | UnmatchedParserError | UnmatchedResolverError>;
19
31
  }
@@ -1,19 +1,62 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.InvalidPointerError = exports.TimeoutError = exports.MissingPointerError = exports.UnmatchedResolverError = exports.ResolverError = exports.UnmatchedParserError = exports.ParserError = exports.JSONParserErrorGroup = exports.JSONParserError = void 0;
4
+ exports.toJSON = toJSON;
5
+ exports.getDeepKeys = getDeepKeys;
4
6
  exports.isHandledError = isHandledError;
5
7
  exports.normalizeError = normalizeError;
6
- const ono_1 = require("@jsdevtools/ono");
7
8
  const url_js_1 = require("./url.js");
9
+ const nonJsonTypes = ["function", "symbol", "undefined"];
10
+ const protectedProps = ["constructor", "prototype", "__proto__"];
11
+ const objectPrototype = Object.getPrototypeOf({});
12
+ /**
13
+ * Custom JSON serializer for Error objects.
14
+ * Returns all built-in error properties, as well as extended properties.
15
+ */
16
+ function toJSON() {
17
+ // HACK: We have to cast the objects to `any` so we can use symbol indexers.
18
+ // see https://github.com/Microsoft/TypeScript/issues/1863
19
+ const pojo = {};
20
+ const error = this;
21
+ for (const key of getDeepKeys(error)) {
22
+ if (typeof key === "string") {
23
+ const value = error[key];
24
+ const type = typeof value;
25
+ if (!nonJsonTypes.includes(type)) {
26
+ pojo[key] = value;
27
+ }
28
+ }
29
+ }
30
+ return pojo;
31
+ }
32
+ /**
33
+ * Returns own, inherited, enumerable, non-enumerable, string, and symbol keys of `obj`.
34
+ * Does NOT return members of the base Object prototype, or the specified omitted keys.
35
+ */
36
+ function getDeepKeys(obj, omit = []) {
37
+ let keys = [];
38
+ // Crawl the prototype chain, finding all the string and symbol keys
39
+ while (obj && obj !== objectPrototype) {
40
+ keys = keys.concat(Object.getOwnPropertyNames(obj), Object.getOwnPropertySymbols(obj));
41
+ obj = Object.getPrototypeOf(obj);
42
+ }
43
+ // De-duplicate the list of keys
44
+ const uniqueKeys = new Set(keys);
45
+ // Remove any omitted keys
46
+ for (const key of omit.concat(protectedProps)) {
47
+ uniqueKeys.delete(key);
48
+ }
49
+ return uniqueKeys;
50
+ }
8
51
  class JSONParserError extends Error {
9
52
  constructor(message, source) {
10
53
  super();
54
+ this.toJSON = toJSON.bind(this);
11
55
  this.code = "EUNKNOWN";
12
56
  this.name = "JSONParserError";
13
57
  this.message = message;
14
58
  this.source = source;
15
59
  this.path = null;
16
- ono_1.Ono.extend(this);
17
60
  }
18
61
  get footprint() {
19
62
  return `${this.path}+${this.source}+${this.code}+${this.message}`;
@@ -23,10 +66,10 @@ exports.JSONParserError = JSONParserError;
23
66
  class JSONParserErrorGroup extends Error {
24
67
  constructor(parser) {
25
68
  super();
69
+ this.toJSON = toJSON.bind(this);
26
70
  this.files = parser;
27
71
  this.name = "JSONParserErrorGroup";
28
72
  this.message = `${this.errors.length} error${this.errors.length > 1 ? "s" : ""} occurred while reading '${(0, url_js_1.toFileSystemPath)(parser.$refs._root$Ref.path)}'`;
29
- ono_1.Ono.extend(this);
30
73
  }
31
74
  static getParserErrors(parser) {
32
75
  const errors = [];
@@ -14,5 +14,6 @@ exports.default = (0, config_1.defineConfig)({
14
14
  passWithNoTests: true,
15
15
  reporters: ["verbose"],
16
16
  coverage: { reporter: ["lcov", "html", "text"] },
17
+ snapshotSerializers: ["./test/utils/serializeJson.ts"],
17
18
  },
18
19
  });
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 = a.pathFromRoot.lastIndexOf("/definitions");
220
- const bDefinitionsIndex = b.pathFromRoot.lastIndexOf("/definitions");
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
@@ -1,6 +1,5 @@
1
1
  import $Ref from "./ref.js";
2
2
  import Pointer from "./pointer.js";
3
- import { ono } from "@jsdevtools/ono";
4
3
  import * as url from "./util/url.js";
5
4
  import type $Refs from "./refs.js";
6
5
  import type { DereferenceOptions, ParserOptions } from "./options.js";
@@ -251,7 +250,7 @@ function dereference$Ref<S extends object = JSONSchema, O extends ParserOptions<
251
250
  //
252
251
  // This check is not perfect and the design of the dereference caching mechanism needs a total
253
252
  // overhaul.
254
- if (typeof cache.value === 'object' && '$ref' in cache.value && '$ref' in $ref) {
253
+ if (typeof cache.value === "object" && "$ref" in cache.value && "$ref" in $ref) {
255
254
  if (cache.value.$ref === $ref.$ref) {
256
255
  return cache;
257
256
  } else {
@@ -355,7 +354,8 @@ function foundCircularReference(keyPath: any, $refs: any, options: any) {
355
354
  options?.dereference?.onCircular?.(keyPath);
356
355
 
357
356
  if (!options.dereference.circular) {
358
- throw ono.reference(`Circular $ref pointer found at ${keyPath}`);
357
+ const error = new ReferenceError(`Circular $ref pointer found at ${keyPath}`);
358
+ throw error;
359
359
  }
360
360
  return true;
361
361
  }
package/lib/index.ts CHANGED
@@ -16,7 +16,6 @@ import {
16
16
  isHandledError,
17
17
  JSONParserErrorGroup,
18
18
  } from "./util/errors.js";
19
- import { ono } from "@jsdevtools/ono";
20
19
  import maybe from "./util/maybe.js";
21
20
  import type { ParserOptions } from "./options.js";
22
21
  import { getJsonSchemaRefParserDefaultOptions } from "./options.js";
@@ -77,7 +76,7 @@ export class $RefParser<S extends object = JSONSchema, O extends ParserOptions<S
77
76
  let promise;
78
77
 
79
78
  if (!args.path && !args.schema) {
80
- const err = ono(`Expected a file path, URL, or object. Got ${args.path || args.schema}`);
79
+ const err = new Error(`Expected a file path, URL, or object. Got ${args.path || args.schema}`);
81
80
  return maybe(args.callback, Promise.reject(err));
82
81
  }
83
82
 
@@ -129,7 +128,7 @@ export class $RefParser<S extends object = JSONSchema, O extends ParserOptions<S
129
128
  this.schema = null; // it's already set to null at line 79, but let's set it again for the sake of readability
130
129
  return maybe(args.callback, Promise.resolve(this.schema!));
131
130
  } else {
132
- throw ono.syntax(`"${this.$refs._root$Ref.path || result}" is not a valid JSON Schema`);
131
+ throw new SyntaxError(`"${this.$refs._root$Ref.path || result}" is not a valid JSON Schema`);
133
132
  }
134
133
  } catch (err) {
135
134
  if (!args.options.continueOnError || !isHandledError(err)) {
@@ -192,12 +191,7 @@ export class $RefParser<S extends object = JSONSchema, O extends ParserOptions<S
192
191
  public resolve(schema: S | string | unknown, options: O): Promise<$Refs<S, O>>;
193
192
  public resolve(schema: S | string | unknown, options: O, callback: $RefsCallback<S, O>): Promise<void>;
194
193
  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>;
194
+ public resolve(path: string, schema: S | string | unknown, options: O, callback: $RefsCallback<S, O>): Promise<void>;
201
195
  async resolve() {
202
196
  const args = normalizeArgs<S, O>(arguments);
203
197
 
package/lib/parse.ts CHANGED
@@ -1,4 +1,3 @@
1
- import { ono } from "@jsdevtools/ono";
2
1
  import * as url from "./util/url.js";
3
2
  import * as plugins from "./util/plugins.js";
4
3
  import {
@@ -92,7 +91,7 @@ async function readFile<S extends object = JSONSchema, O extends ParserOptions<S
92
91
  throw new UnmatchedResolverError(file.url);
93
92
  } else if (!err || !("error" in err)) {
94
93
  // Throw a generic, friendly error.
95
- throw ono.syntax(`Unable to resolve $ref pointer "${file.url}"`);
94
+ throw new SyntaxError(`Unable to resolve $ref pointer "${file.url}"`);
96
95
  }
97
96
  // Throw the original error, if it's one of our own (user-friendly) errors.
98
97
  else if (err.error instanceof ResolverError) {
@@ -133,7 +132,7 @@ async function parseFile<S extends object = JSONSchema, O extends ParserOptions<
133
132
  try {
134
133
  const parser = await plugins.run<S, O>(parsers, "parse", file, $refs);
135
134
  if (!parser.plugin.allowEmpty && isEmpty(parser.result)) {
136
- throw ono.syntax(`Error parsing "${file.url}" as ${parser.plugin.name}. \nParsed value is empty`);
135
+ throw new SyntaxError(`Error parsing "${file.url}" as ${parser.plugin.name}. \nParsed value is empty`);
137
136
  } else {
138
137
  return parser;
139
138
  }
@@ -144,7 +143,7 @@ async function parseFile<S extends object = JSONSchema, O extends ParserOptions<
144
143
  } else if (err && err.message && err.message.startsWith("Error parsing")) {
145
144
  throw err;
146
145
  } else if (!err || !("error" in err)) {
147
- throw ono.syntax(`Unable to parse ${file.url}`);
146
+ throw new SyntaxError(`Unable to parse ${file.url}`);
148
147
  } else if (err.error instanceof ParserError) {
149
148
  throw err.error;
150
149
  } else {
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('null');
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)) {
package/lib/refs.ts CHANGED
@@ -1,4 +1,3 @@
1
- import { ono } from "@jsdevtools/ono";
2
1
  import $Ref from "./ref.js";
3
2
  import * as url from "./util/url.js";
4
3
  import type { JSONSchema4Type, JSONSchema6Type, JSONSchema7Type } from "json-schema";
@@ -100,7 +99,7 @@ export default class $Refs<S extends object = JSONSchema, O extends ParserOption
100
99
  const $ref = this._$refs[withoutHash];
101
100
 
102
101
  if (!$ref) {
103
- throw ono(`Error resolving $ref pointer "${path}". \n"${withoutHash}" not found.`);
102
+ throw new Error(`Error resolving $ref pointer "${path}". \n"${withoutHash}" not found.`);
104
103
  }
105
104
 
106
105
  $ref.set(absPath, value);
@@ -150,7 +149,7 @@ export default class $Refs<S extends object = JSONSchema, O extends ParserOption
150
149
  const $ref = this._$refs[withoutHash];
151
150
 
152
151
  if (!$ref) {
153
- throw ono(`Error resolving $ref pointer "${path}". \n"${withoutHash}" not found.`);
152
+ throw new Error(`Error resolving $ref pointer "${path}". \n"${withoutHash}" not found.`);
154
153
  }
155
154
 
156
155
  return $ref.resolve(absPath, options, path, pathFromRoot);
@@ -1,5 +1,4 @@
1
1
  import fs from "fs";
2
- import { ono } from "@jsdevtools/ono";
3
2
  import * as url from "../util/url.js";
4
3
  import { ResolverError } from "../util/errors.js";
5
4
  import type { JSONSchema, ResolverOptions } from "../types/index.js";
@@ -28,12 +27,16 @@ export default {
28
27
  try {
29
28
  path = url.toFileSystemPath(file.url);
30
29
  } catch (err: any) {
31
- throw new ResolverError(ono.uri(err, `Malformed URI: ${file.url}`), file.url);
30
+ const e = err as Error;
31
+ e.message = `Malformed URI: ${file.url}: ${e.message}`;
32
+ throw new ResolverError(e, file.url);
32
33
  }
33
34
  try {
34
35
  return await fs.promises.readFile(path);
35
36
  } catch (err: any) {
36
- throw new ResolverError(ono(err, `Error opening file "${path}"`), path);
37
+ const e = err as Error;
38
+ e.message = `Error opening file ${path}: ${e.message}`;
39
+ throw new ResolverError(e, path);
37
40
  }
38
41
  },
39
42
  } as ResolverOptions<JSONSchema>;
@@ -1,4 +1,3 @@
1
- import { ono } from "@jsdevtools/ono";
2
1
  import * as url from "../util/url.js";
3
2
  import { ResolverError } from "../util/errors.js";
4
3
  import type { FileInfo, HTTPResolverOptions, JSONSchema } from "../types/index.js";
@@ -78,17 +77,20 @@ async function download<S extends object = JSONSchema>(
78
77
  try {
79
78
  const res = await get(u, httpOptions);
80
79
  if (res.status >= 400) {
81
- throw ono({ status: res.status }, `HTTP ERROR ${res.status}`);
80
+ const error = new Error(`HTTP ERROR ${res.status}`) as Error & { status?: number };
81
+ error.status = res.status;
82
+ throw error;
82
83
  } else if (res.status >= 300) {
83
84
  if (!Number.isNaN(httpOptions.redirects) && redirects.length > httpOptions.redirects!) {
84
- throw new ResolverError(
85
- ono(
86
- { status: res.status },
87
- `Error downloading ${redirects[0]}. \nToo many redirects: \n ${redirects.join(" \n ")}`,
88
- ),
89
- );
85
+ const error = new Error(
86
+ `Error downloading ${redirects[0]}. \nToo many redirects: \n ${redirects.join(" \n ")}`,
87
+ ) as Error & { status?: number };
88
+ error.status = res.status;
89
+ throw new ResolverError(error);
90
90
  } else if (!("location" in res.headers) || !res.headers.location) {
91
- throw ono({ status: res.status }, `HTTP ${res.status} redirect with no location header`);
91
+ const error = new Error(`HTTP ${res.status} redirect with no location header`) as Error & { status?: number };
92
+ error.status = res.status;
93
+ throw error;
92
94
  } else {
93
95
  const redirectTo = url.resolve(u.href, res.headers.location as string);
94
96
  return download(redirectTo, httpOptions, redirects);
@@ -101,7 +103,9 @@ async function download<S extends object = JSONSchema>(
101
103
  return Buffer.alloc(0);
102
104
  }
103
105
  } catch (err: any) {
104
- throw new ResolverError(ono(err, `Error downloading ${u.href}`), u.href);
106
+ const e = err as Error;
107
+ e.message = `Error downloading ${u.href}: ${e.message}`;
108
+ throw new ResolverError(e, u.href);
105
109
  }
106
110
  }
107
111
 
@@ -1,4 +1,3 @@
1
- import { Ono } from "@jsdevtools/ono";
2
1
  import { getHash, stripHash, toFileSystemPath } from "./url.js";
3
2
  import type $RefParser from "../index.js";
4
3
  import type { ParserOptions } from "../index.js";
@@ -14,7 +13,57 @@ export type JSONParserErrorType =
14
13
  | "EUNMATCHEDRESOLVER"
15
14
  | "EMISSINGPOINTER"
16
15
  | "EINVALIDPOINTER";
16
+ const nonJsonTypes = ["function", "symbol", "undefined"];
17
+ const protectedProps = ["constructor", "prototype", "__proto__"];
18
+ const objectPrototype = Object.getPrototypeOf({});
19
+
20
+ /**
21
+ * Custom JSON serializer for Error objects.
22
+ * Returns all built-in error properties, as well as extended properties.
23
+ */
24
+ export function toJSON<T extends Error>(this: T): Error & T {
25
+ // HACK: We have to cast the objects to `any` so we can use symbol indexers.
26
+ // see https://github.com/Microsoft/TypeScript/issues/1863
27
+ const pojo: any = {};
28
+ const error = this as any;
29
+
30
+ for (const key of getDeepKeys(error)) {
31
+ if (typeof key === "string") {
32
+ const value = error[key];
33
+ const type = typeof value;
34
+
35
+ if (!nonJsonTypes.includes(type)) {
36
+ pojo[key] = value;
37
+ }
38
+ }
39
+ }
40
+
41
+ return pojo as Error & T;
42
+ }
43
+
44
+ /**
45
+ * Returns own, inherited, enumerable, non-enumerable, string, and symbol keys of `obj`.
46
+ * Does NOT return members of the base Object prototype, or the specified omitted keys.
47
+ */
48
+ export function getDeepKeys(obj: object, omit: Array<string | symbol> = []): Set<string | symbol> {
49
+ let keys: Array<string | symbol> = [];
50
+
51
+ // Crawl the prototype chain, finding all the string and symbol keys
52
+ while (obj && obj !== objectPrototype) {
53
+ keys = keys.concat(Object.getOwnPropertyNames(obj), Object.getOwnPropertySymbols(obj));
54
+ obj = Object.getPrototypeOf(obj) as object;
55
+ }
17
56
 
57
+ // De-duplicate the list of keys
58
+ const uniqueKeys = new Set(keys);
59
+
60
+ // Remove any omitted keys
61
+ for (const key of omit.concat(protectedProps)) {
62
+ uniqueKeys.delete(key);
63
+ }
64
+
65
+ return uniqueKeys;
66
+ }
18
67
  export class JSONParserError extends Error {
19
68
  public readonly name: string;
20
69
  public readonly message: string;
@@ -29,10 +78,10 @@ export class JSONParserError extends Error {
29
78
  this.message = message;
30
79
  this.source = source;
31
80
  this.path = null;
32
-
33
- Ono.extend(this);
34
81
  }
35
82
 
83
+ toJSON = toJSON.bind(this);
84
+
36
85
  get footprint() {
37
86
  return `${this.path}+${this.source}+${this.code}+${this.message}`;
38
87
  }
@@ -52,9 +101,8 @@ export class JSONParserErrorGroup<
52
101
  this.message = `${this.errors.length} error${
53
102
  this.errors.length > 1 ? "s" : ""
54
103
  } occurred while reading '${toFileSystemPath(parser.$refs._root$Ref!.path)}'`;
55
-
56
- Ono.extend(this);
57
104
  }
105
+ toJSON = toJSON.bind(this);
58
106
 
59
107
  static getParserErrors<S extends object = JSONSchema, O extends ParserOptions<S> = ParserOptions<S>>(
60
108
  parser: $RefParser<S, O>,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@apidevtools/json-schema-ref-parser",
3
- "version": "12.0.1",
3
+ "version": "13.0.0",
4
4
  "description": "Parse, Resolve, and Dereference JSON Schema $ref pointers",
5
5
  "scripts": {
6
6
  "prepublishOnly": "yarn build",
@@ -67,32 +67,31 @@
67
67
  "cjs"
68
68
  ],
69
69
  "devDependencies": {
70
- "@eslint/compat": "^1.2.5",
71
- "@eslint/js": "^9.18.0",
70
+ "@eslint/compat": "^1.2.9",
71
+ "@eslint/js": "^9.28.0",
72
72
  "@types/eslint": "^9.6.1",
73
73
  "@types/js-yaml": "^4.0.9",
74
74
  "@types/node": "^22",
75
- "@typescript-eslint/eslint-plugin": "^8.21.0",
76
- "@typescript-eslint/parser": "^8.21.0",
77
- "@vitest/coverage-v8": "^3.0.4",
75
+ "@typescript-eslint/eslint-plugin": "^8.33.1",
76
+ "@typescript-eslint/parser": "^8.33.1",
77
+ "@vitest/coverage-v8": "^3.2.1",
78
78
  "cross-env": "^7.0.3",
79
- "eslint": "^9.18.0",
80
- "eslint-config-prettier": "^10.0.1",
79
+ "eslint": "^9.28.0",
80
+ "eslint-config-prettier": "^10.1.5",
81
81
  "eslint-config-standard": "^17.1.0",
82
82
  "eslint-plugin-import": "^2.31.0",
83
- "eslint-plugin-prettier": "^5.2.3",
83
+ "eslint-plugin-prettier": "^5.4.1",
84
84
  "eslint-plugin-promise": "^7.2.1",
85
85
  "eslint-plugin-unused-imports": "^4.1.4",
86
- "globals": "^15.14.0",
87
- "jsdom": "^26.0.0",
88
- "prettier": "^3.4.2",
86
+ "globals": "^16.2.0",
87
+ "jsdom": "^26.1.0",
88
+ "prettier": "^3.5.3",
89
89
  "rimraf": "^6.0.1",
90
- "typescript": "^5.7.3",
91
- "typescript-eslint": "^8.21.0",
92
- "vitest": "^3.0.4"
90
+ "typescript": "^5.8.3",
91
+ "typescript-eslint": "^8.33.1",
92
+ "vitest": "^3.2.1"
93
93
  },
94
94
  "dependencies": {
95
- "@jsdevtools/ono": "^7.1.3",
96
95
  "@types/json-schema": "^7.0.15",
97
96
  "js-yaml": "^4.1.0"
98
97
  },
@@ -107,5 +106,5 @@
107
106
  "@semantic-release/github"
108
107
  ]
109
108
  },
110
- "packageManager": "yarn@4.2.2"
109
+ "packageManager": "yarn@4.9.1"
111
110
  }