@apidevtools/json-schema-ref-parser 11.4.2 → 11.5.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/lib/index.ts CHANGED
@@ -19,7 +19,15 @@ import {
19
19
  import { ono } from "@jsdevtools/ono";
20
20
  import maybe from "./util/maybe.js";
21
21
  import type { ParserOptions } from "./options.js";
22
- import type { $RefsCallback, JSONSchema, SchemaCallback } from "./types/index.js";
22
+ import type {
23
+ $RefsCallback,
24
+ JSONSchema,
25
+ SchemaCallback,
26
+ FileInfo,
27
+ Plugin,
28
+ ResolverOptions,
29
+ HTTPResolverOptions,
30
+ } from "./types/index.js";
23
31
 
24
32
  export type RefParserSchema = string | JSONSchema;
25
33
 
@@ -29,14 +37,14 @@ export type RefParserSchema = string | JSONSchema;
29
37
  *
30
38
  * @class
31
39
  */
32
- export class $RefParser {
40
+ export class $RefParser<S extends JSONSchema = JSONSchema, O extends ParserOptions = ParserOptions> {
33
41
  /**
34
42
  * The parsed (and possibly dereferenced) JSON schema object
35
43
  *
36
44
  * @type {object}
37
45
  * @readonly
38
46
  */
39
- public schema: JSONSchema | null = null;
47
+ public schema: S | null = null;
40
48
 
41
49
  /**
42
50
  * The resolved JSON references
@@ -44,7 +52,7 @@ export class $RefParser {
44
52
  * @type {$Refs}
45
53
  * @readonly
46
54
  */
47
- $refs = new $Refs();
55
+ $refs = new $Refs<S>();
48
56
 
49
57
  /**
50
58
  * Parses the given JSON schema.
@@ -57,19 +65,14 @@ export class $RefParser {
57
65
  * @param [callback] - An error-first callback. The second parameter is the parsed JSON schema object.
58
66
  * @returns - The returned promise resolves with the parsed JSON schema object.
59
67
  */
60
- public parse(schema: RefParserSchema): Promise<JSONSchema>;
61
- public parse(schema: RefParserSchema, callback: SchemaCallback): Promise<void>;
62
- public parse(schema: RefParserSchema, options: ParserOptions): Promise<JSONSchema>;
63
- public parse(schema: RefParserSchema, options: ParserOptions, callback: SchemaCallback): Promise<void>;
64
- public parse(baseUrl: string, schema: RefParserSchema, options: ParserOptions): Promise<JSONSchema>;
65
- public parse(
66
- baseUrl: string,
67
- schema: RefParserSchema,
68
- options: ParserOptions,
69
- callback: SchemaCallback,
70
- ): Promise<void>;
68
+ public parse(schema: S | string): Promise<S>;
69
+ public parse(schema: S | string, callback: SchemaCallback<S>): Promise<void>;
70
+ public parse(schema: S | string, options: O): Promise<S>;
71
+ public parse(schema: S | string, options: O, callback: SchemaCallback<S>): Promise<void>;
72
+ public parse(baseUrl: string, schema: S | string, options: O): Promise<S>;
73
+ public parse(baseUrl: string, schema: S | string, options: O, callback: SchemaCallback<S>): Promise<void>;
71
74
  async parse() {
72
- const args = normalizeArgs(arguments as any);
75
+ const args = normalizeArgs<S, O>(arguments as any);
73
76
  let promise;
74
77
 
75
78
  if (!args.path && !args.schema) {
@@ -112,7 +115,7 @@ export class $RefParser {
112
115
  promise = Promise.resolve(args.schema);
113
116
  } else {
114
117
  // Parse the schema file/url
115
- promise = _parse(args.path, this.$refs, args.options);
118
+ promise = _parse<S, typeof args.options>(args.path, this.$refs, args.options);
116
119
  }
117
120
 
118
121
  try {
@@ -140,19 +143,35 @@ export class $RefParser {
140
143
  }
141
144
  }
142
145
 
143
- public static parse(schema: RefParserSchema): Promise<JSONSchema>;
144
- public static parse(schema: RefParserSchema, callback: SchemaCallback): Promise<void>;
145
- public static parse(schema: RefParserSchema, options: ParserOptions): Promise<JSONSchema>;
146
- public static parse(schema: RefParserSchema, options: ParserOptions, callback: SchemaCallback): Promise<void>;
147
- public static parse(baseUrl: string, schema: RefParserSchema, options: ParserOptions): Promise<JSONSchema>;
148
- public static parse(
146
+ public static parse<S extends JSONSchema = JSONSchema>(schema: S | string): Promise<S>;
147
+ public static parse<S extends JSONSchema = JSONSchema>(
148
+ schema: S | string,
149
+ callback: SchemaCallback<S>,
150
+ ): Promise<void>;
151
+ public static parse<S extends JSONSchema = JSONSchema, O extends ParserOptions = ParserOptions>(
152
+ schema: S | string,
153
+ options: O,
154
+ ): Promise<S>;
155
+ public static parse<S extends JSONSchema = JSONSchema, O extends ParserOptions = ParserOptions>(
156
+ schema: S | string,
157
+ options: O,
158
+ callback: SchemaCallback<S>,
159
+ ): Promise<void>;
160
+ public static parse<S extends JSONSchema = JSONSchema, O extends ParserOptions = ParserOptions>(
161
+ baseUrl: string,
162
+ schema: S | string,
163
+ options: O,
164
+ ): Promise<S>;
165
+ public static parse<S extends JSONSchema = JSONSchema, O extends ParserOptions = ParserOptions>(
149
166
  baseUrl: string,
150
- schema: RefParserSchema,
151
- options: ParserOptions,
152
- callback: SchemaCallback,
167
+ schema: S | string,
168
+ options: O,
169
+ callback: SchemaCallback<S>,
153
170
  ): Promise<void>;
154
- public static parse(): Promise<JSONSchema> | Promise<void> {
155
- const parser = new $RefParser();
171
+ public static parse<S extends JSONSchema = JSONSchema, O extends ParserOptions = ParserOptions>():
172
+ | Promise<S>
173
+ | Promise<void> {
174
+ const parser = new $RefParser<S, O>();
156
175
  return parser.parse.apply(parser, arguments as any);
157
176
  }
158
177
 
@@ -167,19 +186,14 @@ export class $RefParser {
167
186
  * @param options (optional)
168
187
  * @param callback (optional) A callback that will receive a `$Refs` object
169
188
  */
170
- public resolve(schema: RefParserSchema): Promise<$Refs>;
171
- public resolve(schema: RefParserSchema, callback: $RefsCallback): Promise<void>;
172
- public resolve(schema: RefParserSchema, options: ParserOptions): Promise<$Refs>;
173
- public resolve(schema: RefParserSchema, options: ParserOptions, callback: $RefsCallback): Promise<void>;
174
- public resolve(baseUrl: string, schema: RefParserSchema, options: ParserOptions): Promise<$Refs>;
175
- public resolve(
176
- baseUrl: string,
177
- schema: RefParserSchema,
178
- options: ParserOptions,
179
- callback: $RefsCallback,
180
- ): Promise<void>;
189
+ public resolve(schema: S | string): Promise<$Refs<S>>;
190
+ public resolve(schema: S | string, callback: $RefsCallback<S>): Promise<void>;
191
+ public resolve(schema: S | string, options: O): Promise<$Refs<S>>;
192
+ public resolve(schema: S | string, options: O, callback: $RefsCallback<S>): Promise<void>;
193
+ public resolve(baseUrl: string, schema: S | string, options: O): Promise<$Refs<S>>;
194
+ public resolve(baseUrl: string, schema: S | string, options: O, callback: $RefsCallback<S>): Promise<void>;
181
195
  async resolve() {
182
- const args = normalizeArgs(arguments);
196
+ const args = normalizeArgs<S, O>(arguments);
183
197
 
184
198
  try {
185
199
  await this.parse(args.path, args.schema, args.options);
@@ -202,19 +216,35 @@ export class $RefParser {
202
216
  * @param options (optional)
203
217
  * @param callback (optional) A callback that will receive a `$Refs` object
204
218
  */
205
- public static resolve(schema: RefParserSchema): Promise<$Refs>;
206
- public static resolve(schema: RefParserSchema, callback: $RefsCallback): Promise<void>;
207
- public static resolve(schema: RefParserSchema, options: ParserOptions): Promise<$Refs>;
208
- public static resolve(schema: RefParserSchema, options: ParserOptions, callback: $RefsCallback): Promise<void>;
209
- public static resolve(baseUrl: string, schema: RefParserSchema, options: ParserOptions): Promise<$Refs>;
210
- public static resolve(
219
+ public static resolve<S extends JSONSchema = JSONSchema>(schema: S | string): Promise<$Refs<S>>;
220
+ public static resolve<S extends JSONSchema = JSONSchema>(
221
+ schema: S | string,
222
+ callback: $RefsCallback<S>,
223
+ ): Promise<void>;
224
+ public static resolve<S extends JSONSchema = JSONSchema, O extends ParserOptions = ParserOptions>(
225
+ schema: S | string,
226
+ options: O,
227
+ ): Promise<$Refs<S>>;
228
+ public static resolve<S extends JSONSchema = JSONSchema, O extends ParserOptions = ParserOptions>(
229
+ schema: S | string,
230
+ options: O,
231
+ callback: $RefsCallback<S>,
232
+ ): Promise<void>;
233
+ public static resolve<S extends JSONSchema = JSONSchema, O extends ParserOptions = ParserOptions>(
211
234
  baseUrl: string,
212
- schema: RefParserSchema,
213
- options: ParserOptions,
214
- callback: $RefsCallback,
235
+ schema: S | string,
236
+ options: O,
237
+ ): Promise<$Refs<S>>;
238
+ public static resolve<S extends JSONSchema = JSONSchema, O extends ParserOptions = ParserOptions>(
239
+ baseUrl: string,
240
+ schema: S | string,
241
+ options: O,
242
+ callback: $RefsCallback<S>,
215
243
  ): Promise<void>;
216
- static resolve(): Promise<JSONSchema> | Promise<void> {
217
- const instance = new $RefParser();
244
+ static resolve<S extends JSONSchema = JSONSchema, O extends ParserOptions = ParserOptions>():
245
+ | Promise<S>
246
+ | Promise<void> {
247
+ const instance = new $RefParser<S, O>();
218
248
  return instance.resolve.apply(instance, arguments as any);
219
249
  }
220
250
 
@@ -229,19 +259,37 @@ export class $RefParser {
229
259
  * @param options (optional)
230
260
  * @param callback (optional) A callback that will receive the bundled schema object
231
261
  */
232
- public static bundle(schema: RefParserSchema): Promise<JSONSchema>;
233
- public static bundle(schema: RefParserSchema, callback: SchemaCallback): Promise<void>;
234
- public static bundle(schema: RefParserSchema, options: ParserOptions): Promise<JSONSchema>;
235
- public static bundle(schema: RefParserSchema, options: ParserOptions, callback: SchemaCallback): Promise<void>;
236
- public static bundle(baseUrl: string, schema: RefParserSchema, options: ParserOptions): Promise<JSONSchema>;
237
- public static bundle(
262
+ public static bundle<S extends JSONSchema = JSONSchema, O extends ParserOptions = ParserOptions>(
263
+ schema: S | string,
264
+ ): Promise<S>;
265
+ public static bundle<S extends JSONSchema = JSONSchema, O extends ParserOptions = ParserOptions>(
266
+ schema: S | string,
267
+ callback: SchemaCallback<S>,
268
+ ): Promise<void>;
269
+ public static bundle<S extends JSONSchema = JSONSchema, O extends ParserOptions = ParserOptions>(
270
+ schema: S | string,
271
+ options: O,
272
+ ): Promise<S>;
273
+ public static bundle<S extends JSONSchema = JSONSchema, O extends ParserOptions = ParserOptions>(
274
+ schema: S | string,
275
+ options: O,
276
+ callback: SchemaCallback<S>,
277
+ ): Promise<void>;
278
+ public static bundle<S extends JSONSchema = JSONSchema, O extends ParserOptions = ParserOptions>(
238
279
  baseUrl: string,
239
- schema: RefParserSchema,
240
- options: ParserOptions,
241
- callback: SchemaCallback,
242
- ): Promise<JSONSchema>;
243
- static bundle(): Promise<JSONSchema> | Promise<void> {
244
- const instance = new $RefParser();
280
+ schema: S | string,
281
+ options: O,
282
+ ): Promise<S>;
283
+ public static bundle<S extends JSONSchema = JSONSchema, O extends ParserOptions = ParserOptions>(
284
+ baseUrl: string,
285
+ schema: S | string,
286
+ options: O,
287
+ callback: SchemaCallback<S>,
288
+ ): Promise<S>;
289
+ static bundle<S extends JSONSchema = JSONSchema, O extends ParserOptions = ParserOptions>():
290
+ | Promise<S>
291
+ | Promise<void> {
292
+ const instance = new $RefParser<S, O>();
245
293
  return instance.bundle.apply(instance, arguments as any);
246
294
  }
247
295
 
@@ -256,22 +304,17 @@ export class $RefParser {
256
304
  * @param options (optional)
257
305
  * @param callback (optional) A callback that will receive the bundled schema object
258
306
  */
259
- public bundle(schema: RefParserSchema): Promise<JSONSchema>;
260
- public bundle(schema: RefParserSchema, callback: SchemaCallback): Promise<void>;
261
- public bundle(schema: RefParserSchema, options: ParserOptions): Promise<JSONSchema>;
262
- public bundle(schema: RefParserSchema, options: ParserOptions, callback: SchemaCallback): Promise<void>;
263
- public bundle(baseUrl: string, schema: RefParserSchema, options: ParserOptions): Promise<JSONSchema>;
264
- public bundle(
265
- baseUrl: string,
266
- schema: RefParserSchema,
267
- options: ParserOptions,
268
- callback: SchemaCallback,
269
- ): Promise<void>;
307
+ public bundle(schema: S | string): Promise<S>;
308
+ public bundle(schema: S | string, callback: SchemaCallback<S>): Promise<void>;
309
+ public bundle(schema: S | string, options: O): Promise<S>;
310
+ public bundle(schema: S | string, options: O, callback: SchemaCallback<S>): Promise<void>;
311
+ public bundle(baseUrl: string, schema: S | string, options: O): Promise<S>;
312
+ public bundle(baseUrl: string, schema: S | string, options: O, callback: SchemaCallback<S>): Promise<void>;
270
313
  async bundle() {
271
- const args = normalizeArgs(arguments);
314
+ const args = normalizeArgs<S, O>(arguments);
272
315
  try {
273
316
  await this.resolve(args.path, args.schema, args.options);
274
- _bundle(this, args.options);
317
+ _bundle<S, O>(this, args.options);
275
318
  finalize(this);
276
319
  return maybe(args.callback, Promise.resolve(this.schema!));
277
320
  } catch (err) {
@@ -290,19 +333,37 @@ export class $RefParser {
290
333
  * @param options (optional)
291
334
  * @param callback (optional) A callback that will receive the dereferenced schema object
292
335
  */
293
- public static dereference(schema: RefParserSchema): Promise<JSONSchema>;
294
- public static dereference(schema: RefParserSchema, callback: SchemaCallback): Promise<void>;
295
- public static dereference(schema: RefParserSchema, options: ParserOptions): Promise<JSONSchema>;
296
- public static dereference(schema: RefParserSchema, options: ParserOptions, callback: SchemaCallback): Promise<void>;
297
- public static dereference(baseUrl: string, schema: RefParserSchema, options: ParserOptions): Promise<JSONSchema>;
298
- public static dereference(
336
+ public static dereference<S extends JSONSchema = JSONSchema, O extends ParserOptions = ParserOptions>(
337
+ schema: S | string,
338
+ ): Promise<S>;
339
+ public static dereference<S extends JSONSchema = JSONSchema, O extends ParserOptions = ParserOptions>(
340
+ schema: S | string,
341
+ callback: SchemaCallback<S>,
342
+ ): Promise<void>;
343
+ public static dereference<S extends JSONSchema = JSONSchema, O extends ParserOptions = ParserOptions>(
344
+ schema: S | string,
345
+ options: O,
346
+ ): Promise<S>;
347
+ public static dereference<S extends JSONSchema = JSONSchema, O extends ParserOptions = ParserOptions>(
348
+ schema: S | string,
349
+ options: O,
350
+ callback: SchemaCallback<S>,
351
+ ): Promise<void>;
352
+ public static dereference<S extends JSONSchema = JSONSchema, O extends ParserOptions = ParserOptions>(
353
+ baseUrl: string,
354
+ schema: S | string,
355
+ options: O,
356
+ ): Promise<S>;
357
+ public static dereference<S extends JSONSchema = JSONSchema, O extends ParserOptions = ParserOptions>(
299
358
  baseUrl: string,
300
- schema: RefParserSchema,
301
- options: ParserOptions,
302
- callback: SchemaCallback,
359
+ schema: S | string,
360
+ options: O,
361
+ callback: SchemaCallback<S>,
303
362
  ): Promise<void>;
304
- static dereference(): Promise<JSONSchema> | Promise<void> {
305
- const instance = new $RefParser();
363
+ static dereference<S extends JSONSchema = JSONSchema, O extends ParserOptions = ParserOptions>():
364
+ | Promise<S>
365
+ | Promise<void> {
366
+ const instance = new $RefParser<S, O>();
306
367
  return instance.dereference.apply(instance, arguments as any);
307
368
  }
308
369
 
@@ -313,37 +374,35 @@ export class $RefParser {
313
374
  *
314
375
  * See https://apitools.dev/json-schema-ref-parser/docs/ref-parser.html#dereferenceschema-options-callback
315
376
  *
377
+ * @param baseUrl
316
378
  * @param schema A JSON Schema object, or the file path or URL of a JSON Schema file. See the `parse` method for more info.
317
379
  * @param options (optional)
318
380
  * @param callback (optional) A callback that will receive the dereferenced schema object
319
381
  */
320
- public dereference(
321
- baseUrl: string,
322
- schema: RefParserSchema,
323
- options: ParserOptions,
324
- callback: SchemaCallback,
325
- ): Promise<void>;
326
- public dereference(schema: RefParserSchema, options: ParserOptions, callback: SchemaCallback): Promise<void>;
327
- public dereference(schema: RefParserSchema, callback: SchemaCallback): Promise<void>;
328
- public dereference(baseUrl: string, schema: RefParserSchema, options: ParserOptions): Promise<JSONSchema>;
329
- public dereference(schema: RefParserSchema, options: ParserOptions): Promise<JSONSchema>;
330
- public dereference(schema: RefParserSchema): Promise<JSONSchema>;
382
+ public dereference(baseUrl: string, schema: S | string, options: O, callback: SchemaCallback<S>): Promise<void>;
383
+ public dereference(schema: S | string, options: O, callback: SchemaCallback<S>): Promise<void>;
384
+ public dereference(schema: S | string, callback: SchemaCallback<S>): Promise<void>;
385
+ public dereference(baseUrl: string, schema: S | string, options: O): Promise<S>;
386
+ public dereference(schema: S | string, options: O): Promise<S>;
387
+ public dereference(schema: S | string): Promise<S>;
331
388
  async dereference() {
332
- const args = normalizeArgs(arguments);
389
+ const args = normalizeArgs<S, O>(arguments);
333
390
 
334
391
  try {
335
392
  await this.resolve(args.path, args.schema, args.options);
336
393
  _dereference(this, args.options);
337
394
  finalize(this);
338
- return maybe(args.callback, Promise.resolve(this.schema));
395
+ return maybe<S>(args.callback, Promise.resolve(this.schema!) as Promise<S>);
339
396
  } catch (err) {
340
- return maybe(args.callback, Promise.reject(err));
397
+ return maybe<S>(args.callback, Promise.reject(err));
341
398
  }
342
399
  }
343
400
  }
344
401
  export default $RefParser;
345
402
 
346
- function finalize(parser: any) {
403
+ function finalize<S extends JSONSchema = JSONSchema, O extends ParserOptions = ParserOptions>(
404
+ parser: $RefParser<S, O>,
405
+ ) {
347
406
  const errors = JSONParserErrorGroup.getParserErrors(parser);
348
407
  if (errors.length > 0) {
349
408
  throw new JSONParserErrorGroup(parser);
@@ -369,4 +428,8 @@ export {
369
428
  isHandledError,
370
429
  JSONParserErrorGroup,
371
430
  SchemaCallback,
431
+ FileInfo,
432
+ Plugin,
433
+ ResolverOptions,
434
+ HTTPResolverOptions,
372
435
  };
@@ -1,20 +1,25 @@
1
+ import type { Options, ParserOptions } from "./options.js";
1
2
  import { getNewOptions } from "./options.js";
2
3
  import type { JSONSchema, SchemaCallback } from "./types";
3
- import type $RefParserOptions from "./options";
4
4
 
5
5
  // I really dislike this function and the way it's written. It's not clear what it's doing, and it's way too flexible
6
6
  // In the future, I'd like to deprecate the api and accept only named parameters in index.ts
7
- export interface NormalizedArguments<T = $RefParserOptions> {
7
+ export interface NormalizedArguments<S, O> {
8
8
  path: string;
9
- schema: JSONSchema;
10
- options: T;
11
- callback: SchemaCallback;
9
+ schema: S;
10
+ options: O & Options;
11
+ callback: SchemaCallback<S>;
12
12
  }
13
13
  /**
14
14
  * Normalizes the given arguments, accounting for optional args.
15
15
  */
16
- export function normalizeArgs<T = $RefParserOptions>(_args: Partial<IArguments>): NormalizedArguments<T> {
17
- let path, schema, options, callback;
16
+ export function normalizeArgs<S extends JSONSchema = JSONSchema, O extends ParserOptions = ParserOptions>(
17
+ _args: Partial<IArguments>,
18
+ ): NormalizedArguments<S, O> {
19
+ let path;
20
+ let schema;
21
+ let options: Options & O;
22
+ let callback;
18
23
  const args = Array.prototype.slice.call(_args) as any[];
19
24
 
20
25
  if (typeof args[args.length - 1] === "function") {
@@ -42,7 +47,7 @@ export function normalizeArgs<T = $RefParserOptions>(_args: Partial<IArguments>)
42
47
  }
43
48
 
44
49
  try {
45
- options = getNewOptions(options);
50
+ options = getNewOptions<S, O>(options);
46
51
  } catch (e) {
47
52
  console.error(`JSON Schema Ref Parser: Error normalizing options: ${e}`);
48
53
  }
package/lib/options.ts CHANGED
@@ -5,20 +5,55 @@ import binaryParser from "./parsers/binary.js";
5
5
  import fileResolver from "./resolvers/file.js";
6
6
  import httpResolver from "./resolvers/http.js";
7
7
 
8
- import type { HTTPResolverOptions, JSONSchemaObject, Plugin, ResolverOptions } from "./types/index.js";
8
+ import type { HTTPResolverOptions, JSONSchema, JSONSchemaObject, Plugin, ResolverOptions } from "./types/index.js";
9
9
 
10
10
  export type DeepPartial<T> = T extends object
11
11
  ? {
12
12
  [P in keyof T]?: DeepPartial<T[P]>;
13
13
  }
14
14
  : T;
15
+ export interface DereferenceOptions {
16
+ /**
17
+ * Determines whether circular `$ref` pointers are handled.
18
+ *
19
+ * If set to `false`, then a `ReferenceError` will be thrown if the schema contains any circular references.
20
+ *
21
+ * If set to `"ignore"`, then circular references will simply be ignored. No error will be thrown, but the `$Refs.circular` property will still be set to `true`.
22
+ */
23
+ circular?: boolean | "ignore";
24
+
25
+ /**
26
+ * A function, called for each path, which can return true to stop this path and all
27
+ * subpaths from being dereferenced further. This is useful in schemas where some
28
+ * subpaths contain literal $ref keys that should not be dereferenced.
29
+ */
30
+ excludedPathMatcher?(path: string): boolean;
31
+
32
+ /**
33
+ * Callback invoked during dereferencing.
34
+ *
35
+ * @argument {string} path - The path being dereferenced (ie. the `$ref` string)
36
+ * @argument {JSONSchemaObject} value - The JSON-Schema that the `$ref` resolved to
37
+ * @argument {JSONSchemaObject} parent - The parent of the dereferenced object
38
+ * @argument {string} parentPropName - The prop name of the parent object whose value was dereferenced
39
+ */
40
+ onDereference?(path: string, value: JSONSchemaObject, parent?: JSONSchemaObject, parentPropName?: string): void;
41
+
42
+ /**
43
+ * Whether a reference should resolve relative to its directory/path, or from the cwd
44
+ *
45
+ * Default: `relative`
46
+ */
47
+ externalReferenceResolution?: "relative" | "root";
48
+ }
49
+
15
50
  /**
16
51
  * Options that determine how JSON schemas are parsed, resolved, and dereferenced.
17
52
  *
18
53
  * @param [options] - Overridden options
19
54
  * @class
20
55
  */
21
- export interface $RefParserOptions {
56
+ export interface $RefParserOptions<S> {
22
57
  /**
23
58
  * The `parse` options determine how different types of files will be parsed.
24
59
  *
@@ -42,10 +77,10 @@ export interface $RefParserOptions {
42
77
  * Determines whether external $ref pointers will be resolved. If this option is disabled, then external `$ref` pointers will simply be ignored.
43
78
  */
44
79
  external?: boolean;
45
- file?: Partial<ResolverOptions> | boolean;
46
- http?: HTTPResolverOptions | boolean;
80
+ file?: Partial<ResolverOptions<S>> | boolean;
81
+ http?: HTTPResolverOptions<S> | boolean;
47
82
  } & {
48
- [key: string]: Partial<ResolverOptions> | HTTPResolverOptions | boolean | undefined;
83
+ [key: string]: Partial<ResolverOptions<S>> | HTTPResolverOptions<S> | boolean | undefined;
49
84
  };
50
85
 
51
86
  /**
@@ -58,47 +93,14 @@ export interface $RefParserOptions {
58
93
  /**
59
94
  * The `dereference` options control how JSON Schema `$Ref` Parser will dereference `$ref` pointers within the JSON schema.
60
95
  */
61
- dereference: {
62
- /**
63
- * Determines whether circular `$ref` pointers are handled.
64
- *
65
- * If set to `false`, then a `ReferenceError` will be thrown if the schema contains any circular references.
66
- *
67
- * If set to `"ignore"`, then circular references will simply be ignored. No error will be thrown, but the `$Refs.circular` property will still be set to `true`.
68
- */
69
- circular?: boolean | "ignore";
70
-
71
- /**
72
- * A function, called for each path, which can return true to stop this path and all
73
- * subpaths from being dereferenced further. This is useful in schemas where some
74
- * subpaths contain literal $ref keys that should not be dereferenced.
75
- */
76
- excludedPathMatcher?(path: string): boolean;
77
-
78
- /**
79
- * Callback invoked during dereferencing.
80
- *
81
- * @argument {string} path - The path being dereferenced (ie. the `$ref` string)
82
- * @argument {JSONSchemaObject} value - The JSON-Schema that the `$ref` resolved to
83
- * @argument {JSONSchemaObject} parent - The parent of the dereferenced object
84
- * @argument {string} parentPropName - The prop name of the parent object whose value was dereferenced
85
- */
86
- onDereference?(path: string, value: JSONSchemaObject, parent?: JSONSchemaObject, parentPropName?: string): void;
96
+ dereference: DereferenceOptions;
87
97
 
88
- /**
89
- * Whether a reference should resolve relative to its directory/path, or from the cwd
90
- *
91
- * Default: `relative`
92
- */
93
- externalReferenceResolution?: "relative" | "root";
94
-
95
- /**
96
- * Whether to clone the schema before dereferencing it.
97
- * This is useful when you want to dereference the same schema multiple times, but you don't want to modify the original schema.
98
- * Default: `true` due to mutating the input being the default behavior historically
99
- */
100
- mutateInputSchema?: boolean;
101
- };
98
+ /**
99
+ * Whether to clone the schema before dereferencing it.
100
+ * This is useful when you want to dereference the same schema multiple times, but you don't want to modify the original schema.
101
+ * Default: `true` due to mutating the input being the default behavior historically
102
+ */
103
+ mutateInputSchema?: boolean;
102
104
  }
103
105
 
104
106
  export const getJsonSchemaRefParserDefaultOptions = () => {
@@ -168,19 +170,19 @@ export const getJsonSchemaRefParserDefaultOptions = () => {
168
170
  },
169
171
 
170
172
  mutateInputSchema: true,
171
- } as $RefParserOptions;
173
+ } as $RefParserOptions<JSONSchema>;
172
174
  return defaults;
173
175
  };
174
176
 
175
- export const getNewOptions = (options: DeepPartial<$RefParserOptions> | undefined): $RefParserOptions => {
177
+ export const getNewOptions = <S, O>(options: O | undefined): O & $RefParserOptions<S> => {
176
178
  const newOptions = getJsonSchemaRefParserDefaultOptions();
177
179
  if (options) {
178
180
  merge(newOptions, options);
179
181
  }
180
- return newOptions;
182
+ return newOptions as O & $RefParserOptions<S>;
181
183
  };
182
- export type Options = $RefParserOptions;
183
- export type ParserOptions = DeepPartial<$RefParserOptions>;
184
+ export type Options = $RefParserOptions<JSONSchema>;
185
+ export type ParserOptions = DeepPartial<$RefParserOptions<JSONSchema>>;
184
186
  /**
185
187
  * Merges the properties of the source object into the target object.
186
188
  *
package/lib/parse.ts CHANGED
@@ -10,14 +10,16 @@ import {
10
10
  } from "./util/errors.js";
11
11
  import type $Refs from "./refs.js";
12
12
  import type { Options } from "./options.js";
13
- import type { FileInfo } from "./types/index.js";
14
-
15
- export default parse;
13
+ import type { FileInfo, JSONSchema } from "./types/index.js";
16
14
 
17
15
  /**
18
16
  * Reads and parses the specified file path or URL.
19
17
  */
20
- async function parse(path: string, $refs: $Refs, options: Options) {
18
+ async function parse<S extends JSONSchema = JSONSchema, O extends Options = Options>(
19
+ path: string,
20
+ $refs: $Refs<S>,
21
+ options: O,
22
+ ) {
21
23
  // Remove the URL fragment, if any
22
24
  const hashIndex = path.indexOf("#");
23
25
  let hash = "";
@@ -40,11 +42,11 @@ async function parse(path: string, $refs: $Refs, options: Options) {
40
42
 
41
43
  // Read the file and then parse the data
42
44
  try {
43
- const resolver = await readFile(file, options, $refs);
45
+ const resolver = await readFile<S, O>(file, options, $refs);
44
46
  $ref.pathType = resolver.plugin.name;
45
47
  file.data = resolver.result;
46
48
 
47
- const parser = await parseFile(file, options, $refs);
49
+ const parser = await parseFile<S, O>(file, options, $refs);
48
50
  $ref.value = parser.result;
49
51
 
50
52
  return parser.result;
@@ -64,11 +66,15 @@ async function parse(path: string, $refs: $Refs, options: Options) {
64
66
  * @param file.url - The full URL of the referenced file
65
67
  * @param file.extension - The lowercased file extension (e.g. ".txt", ".html", etc.)
66
68
  * @param options
67
- *
69
+ * @param $refs
68
70
  * @returns
69
71
  * The promise resolves with the raw file contents and the resolver that was used.
70
72
  */
71
- async function readFile(file: FileInfo, options: Options, $refs: $Refs): Promise<any> {
73
+ async function readFile<S extends JSONSchema = JSONSchema, O extends Options = Options>(
74
+ file: FileInfo,
75
+ options: O,
76
+ $refs: $Refs<S>,
77
+ ): Promise<any> {
72
78
  // console.log('Reading %s', file.url);
73
79
 
74
80
  // Find the resolvers that can read this file
@@ -105,11 +111,16 @@ async function readFile(file: FileInfo, options: Options, $refs: $Refs): Promise
105
111
  * @param file.extension - The lowercased file extension (e.g. ".txt", ".html", etc.)
106
112
  * @param file.data - The file contents. This will be whatever data type was returned by the resolver
107
113
  * @param options
114
+ * @param $refs
108
115
  *
109
116
  * @returns
110
117
  * The promise resolves with the parsed file contents and the parser that was used.
111
118
  */
112
- async function parseFile(file: FileInfo, options: Options, $refs: $Refs) {
119
+ async function parseFile<S extends JSONSchema = JSONSchema, O extends Options = Options>(
120
+ file: FileInfo,
121
+ options: O,
122
+ $refs: $Refs<S>,
123
+ ) {
113
124
  // Find the parsers that can read this file type.
114
125
  // If none of the parsers are an exact match for this file, then we'll try ALL of them.
115
126
  // This handles situations where the file IS a supported type, just with an unknown extension.
@@ -120,7 +131,7 @@ async function parseFile(file: FileInfo, options: Options, $refs: $Refs) {
120
131
  // Run the parsers, in order, until one of them succeeds
121
132
  plugins.sort(parsers);
122
133
  try {
123
- const parser = await plugins.run(parsers, "parse", file, $refs);
134
+ const parser = await plugins.run<S>(parsers, "parse", file, $refs);
124
135
  if (!parser.plugin.allowEmpty && isEmpty(parser.result)) {
125
136
  throw ono.syntax(`Error parsing "${file.url}" as ${parser.plugin.name}. \nParsed value is empty`);
126
137
  } else {
@@ -156,3 +167,4 @@ function isEmpty(value: any) {
156
167
  (Buffer.isBuffer(value) && value.length === 0)
157
168
  );
158
169
  }
170
+ export default parse;