@hey-api/json-schema-ref-parser 1.0.8 → 1.2.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.
@@ -1,4 +1,5 @@
1
1
  import $Ref from "./ref.js";
2
+ import cloneDeep from "lodash/cloneDeep";
2
3
  import Pointer from "./pointer.js";
3
4
  import { ono } from "@jsdevtools/ono";
4
5
  import * as url from "./util/url.js";
@@ -17,10 +18,7 @@ export default dereference;
17
18
  * @param parser
18
19
  * @param options
19
20
  */
20
- function dereference(
21
- parser: $RefParser,
22
- options: ParserOptions,
23
- ) {
21
+ function dereference(parser: $RefParser, options: ParserOptions) {
24
22
  const start = Date.now();
25
23
  // console.log('Dereferencing $ref pointers in %s', parser.$refs._root$Ref.path);
26
24
  const dereferenced = crawl<JSONSchema>(
@@ -200,11 +198,12 @@ function dereference$Ref<S extends object = JSONSchema>(
200
198
  }
201
199
  return {
202
200
  circular: cache.circular,
203
- value: Object.assign({}, cache.value, extraKeys),
201
+ value: Object.assign({}, cloneDeep(cache.value), extraKeys),
204
202
  };
205
203
  }
206
204
 
207
- return cache;
205
+ // Return a deep-cloned value so each occurrence is an independent copy
206
+ return { circular: cache.circular, value: cloneDeep(cache.value) };
208
207
  }
209
208
 
210
209
  const pointer = $refs._resolve($refPath, path, options);
package/lib/index.ts CHANGED
@@ -14,7 +14,7 @@ import { fileResolver } from "./resolvers/file.js";
14
14
  interface ResolvedInput {
15
15
  path: string;
16
16
  schema: string | JSONSchema | Buffer | Awaited<JSONSchema> | undefined;
17
- type: 'file' | 'json' | 'url';
17
+ type: "file" | "json" | "url";
18
18
  }
19
19
 
20
20
  export const getResolvedInput = ({
@@ -27,10 +27,10 @@ export const getResolvedInput = ({
27
27
  }
28
28
 
29
29
  const resolvedInput: ResolvedInput = {
30
- path: typeof pathOrUrlOrSchema === 'string' ? pathOrUrlOrSchema : '',
30
+ path: typeof pathOrUrlOrSchema === "string" ? pathOrUrlOrSchema : "",
31
31
  schema: undefined,
32
- type: 'url',
33
- }
32
+ type: "url",
33
+ };
34
34
 
35
35
  // If the path is a filesystem path, then convert it to a URL.
36
36
  // NOTE: According to the JSON Reference spec, these should already be URLs,
@@ -40,27 +40,36 @@ export const getResolvedInput = ({
40
40
  // If it doesn't work for your use-case, then use a URL instead.
41
41
  if (resolvedInput.path && url.isFileSystemPath(resolvedInput.path)) {
42
42
  resolvedInput.path = url.fromFileSystemPath(resolvedInput.path);
43
- resolvedInput.type = 'file';
44
- } else if (!resolvedInput.path && pathOrUrlOrSchema && typeof pathOrUrlOrSchema === 'object') {
43
+ resolvedInput.type = "file";
44
+ } else if (!resolvedInput.path && pathOrUrlOrSchema && typeof pathOrUrlOrSchema === "object") {
45
45
  if ("$id" in pathOrUrlOrSchema && pathOrUrlOrSchema.$id) {
46
46
  // when schema id has defined an URL should use that hostname to request the references,
47
47
  // instead of using the current page URL
48
48
  const { hostname, protocol } = new URL(pathOrUrlOrSchema.$id as string);
49
49
  resolvedInput.path = `${protocol}//${hostname}:${protocol === "https:" ? 443 : 80}`;
50
- resolvedInput.type = 'url';
50
+ resolvedInput.type = "url";
51
51
  } else {
52
52
  resolvedInput.schema = pathOrUrlOrSchema;
53
- resolvedInput.type = 'json';
53
+ resolvedInput.type = "json";
54
54
  }
55
55
  }
56
56
 
57
- if (resolvedInput.type !== 'json') {
57
+ if (resolvedInput.type !== "json") {
58
58
  // resolve the absolute path of the schema
59
59
  resolvedInput.path = url.resolve(url.cwd(), resolvedInput.path);
60
60
  }
61
61
 
62
62
  return resolvedInput;
63
- }
63
+ };
64
+
65
+ const _ensureResolvedInputPath = (input: ResolvedInput, fallbackPath: string): ResolvedInput => {
66
+ if (input.type === "json" && (!input.path || input.path.length === 0)) {
67
+ return { ...input, path: fallbackPath };
68
+ }
69
+ return input;
70
+ };
71
+
72
+ // NOTE: previously used helper removed as unused
64
73
 
65
74
  /**
66
75
  * This class parses a JSON schema, builds a map of its JSON references and their resolved values,
@@ -74,7 +83,7 @@ export class $RefParser {
74
83
  * @readonly
75
84
  */
76
85
  $refs = new $Refs<JSONSchema>();
77
- public options = getJsonSchemaRefParserDefaultOptions()
86
+ public options = getJsonSchemaRefParserDefaultOptions();
78
87
  /**
79
88
  * The parsed (and possibly dereferenced) JSON schema object
80
89
  *
@@ -82,6 +91,9 @@ export class $RefParser {
82
91
  * @readonly
83
92
  */
84
93
  public schema: JSONSchema | null = null;
94
+ public schemaMany: JSONSchema[] = [];
95
+ public schemaManySources: string[] = [];
96
+ public sourcePathToPrefix: Map<string, string> = new Map();
85
97
 
86
98
  /**
87
99
  * Bundles all referenced files/URLs into a single schema that only has internal `$ref` pointers. This lets you split-up your schema however you want while you're building it, but easily combine all those files together when it's time to package or distribute the schema to other people. The resulting schema size will be small, since it will still contain internal JSON references rather than being fully-dereferenced.
@@ -109,6 +121,7 @@ export class $RefParser {
109
121
  pathOrUrlOrSchema,
110
122
  resolvedInput,
111
123
  });
124
+
112
125
  await resolveExternal(this, this.options);
113
126
  const errors = JSONParserErrorGroup.getParserErrors(this);
114
127
  if (errors.length > 0) {
@@ -122,6 +135,39 @@ export class $RefParser {
122
135
  return this.schema!;
123
136
  }
124
137
 
138
+ /**
139
+ * Bundles multiple roots (files/URLs/objects) into a single schema by creating a synthetic root
140
+ * that references each input, resolving all externals, and then hoisting via the existing bundler.
141
+ */
142
+ public async bundleMany({
143
+ arrayBuffer,
144
+ fetch,
145
+ pathOrUrlOrSchemas,
146
+ resolvedInputs,
147
+ }: {
148
+ arrayBuffer?: ArrayBuffer[];
149
+ fetch?: RequestInit;
150
+ pathOrUrlOrSchemas: Array<JSONSchema | string | unknown>;
151
+ resolvedInputs?: ResolvedInput[];
152
+ }): Promise<JSONSchema> {
153
+ await this.parseMany({ arrayBuffer, fetch, pathOrUrlOrSchemas, resolvedInputs });
154
+ this.mergeMany();
155
+
156
+ await resolveExternal(this, this.options);
157
+ const errors = JSONParserErrorGroup.getParserErrors(this);
158
+ if (errors.length > 0) {
159
+ throw new JSONParserErrorGroup(this);
160
+ }
161
+ _bundle(this, this.options);
162
+ // Merged root is ready for bundling
163
+
164
+ const errors2 = JSONParserErrorGroup.getParserErrors(this);
165
+ if (errors2.length > 0) {
166
+ throw new JSONParserErrorGroup(this);
167
+ }
168
+ return this.schema!;
169
+ }
170
+
125
171
  /**
126
172
  * Dereferences all `$ref` pointers in the JSON Schema, replacing each reference with its resolved value. This results in a schema object that does not contain any `$ref` pointers. Instead, it's a normal JavaScript object tree that can easily be crawled and used just like any other JavaScript object. This is great for programmatic usage, especially when using tools that don't understand JSON references.
127
173
  *
@@ -185,17 +231,17 @@ export class $RefParser {
185
231
  if (schema) {
186
232
  // immediately add a new $Ref with the schema object as value
187
233
  const $ref = this.$refs._add(path);
188
- $ref.pathType = url.isFileSystemPath(path) ? 'file' : 'http';
234
+ $ref.pathType = url.isFileSystemPath(path) ? "file" : "http";
189
235
  $ref.value = schema;
190
- } else if (type !== 'json') {
191
- const file = newFile(path)
236
+ } else if (type !== "json") {
237
+ const file = newFile(path);
192
238
 
193
239
  // Add a new $Ref for this file, even though we don't have the value yet.
194
240
  // This ensures that we don't simultaneously read & parse the same file multiple times
195
241
  const $refAdded = this.$refs._add(file.url);
196
242
  $refAdded.pathType = type;
197
243
  try {
198
- const resolver = type === 'file' ? fileResolver : urlResolver;
244
+ const resolver = type === "file" ? fileResolver : urlResolver;
199
245
  await resolver.handler({
200
246
  arrayBuffer,
201
247
  fetch,
@@ -208,12 +254,12 @@ export class $RefParser {
208
254
  if (isHandledError(err)) {
209
255
  $refAdded.value = err;
210
256
  }
211
-
257
+
212
258
  throw err;
213
259
  }
214
260
  }
215
261
 
216
- if (schema === null || typeof schema !== 'object' || Buffer.isBuffer(schema)) {
262
+ if (schema === null || typeof schema !== "object" || Buffer.isBuffer(schema)) {
217
263
  throw ono.syntax(`"${this.$refs._root$Ref.path || schema}" is not a valid JSON Schema`);
218
264
  }
219
265
 
@@ -223,7 +269,317 @@ export class $RefParser {
223
269
  schema,
224
270
  };
225
271
  }
272
+
273
+ private async parseMany({
274
+ arrayBuffer,
275
+ fetch,
276
+ pathOrUrlOrSchemas,
277
+ resolvedInputs: _resolvedInputs,
278
+ }: {
279
+ arrayBuffer?: ArrayBuffer[];
280
+ fetch?: RequestInit;
281
+ pathOrUrlOrSchemas: Array<JSONSchema | string | unknown>;
282
+ resolvedInputs?: ResolvedInput[];
283
+ }): Promise<{ schemaMany: JSONSchema[] }> {
284
+ const resolvedInputs = [...(_resolvedInputs || [])];
285
+ resolvedInputs.push(...(pathOrUrlOrSchemas.map((schema) => getResolvedInput({ pathOrUrlOrSchema: schema })) || []));
286
+
287
+ this.schemaMany = [];
288
+ this.schemaManySources = [];
289
+ this.sourcePathToPrefix = new Map();
290
+
291
+ for (let i = 0; i < resolvedInputs.length; i++) {
292
+ const resolvedInput = resolvedInputs[i];
293
+ const { path, type } = resolvedInput;
294
+ let { schema } = resolvedInput;
295
+
296
+ if (schema) {
297
+ // keep schema as-is
298
+ } else if (type !== "json") {
299
+ const file = newFile(path);
300
+
301
+ // Add a new $Ref for this file, even though we don't have the value yet.
302
+ // This ensures that we don't simultaneously read & parse the same file multiple times
303
+ const $refAdded = this.$refs._add(file.url);
304
+ $refAdded.pathType = type;
305
+ try {
306
+ const resolver = type === "file" ? fileResolver : urlResolver;
307
+ await resolver.handler({
308
+ arrayBuffer: arrayBuffer?.[i],
309
+ fetch,
310
+ file,
311
+ });
312
+ const parseResult = await parseFile(file, this.options);
313
+ $refAdded.value = parseResult.result;
314
+ schema = parseResult.result;
315
+ } catch (err) {
316
+ if (isHandledError(err)) {
317
+ $refAdded.value = err;
318
+ }
319
+
320
+ throw err;
321
+ }
322
+ }
323
+
324
+ if (schema === null || typeof schema !== "object" || Buffer.isBuffer(schema)) {
325
+ throw ono.syntax(`"${this.$refs._root$Ref.path || schema}" is not a valid JSON Schema`);
326
+ }
327
+
328
+ this.schemaMany.push(schema);
329
+ this.schemaManySources.push(path && path.length ? path : url.cwd());
330
+ }
331
+
332
+ return {
333
+ schemaMany: this.schemaMany,
334
+ };
335
+ }
336
+
337
+ public mergeMany(): JSONSchema {
338
+ const schemas = this.schemaMany || [];
339
+ if (schemas.length === 0) {
340
+ throw ono("mergeMany called with no schemas. Did you run parseMany?");
341
+ }
342
+
343
+ const merged: any = {};
344
+
345
+ // Determine spec version: prefer first occurrence of openapi, else swagger
346
+ let chosenOpenapi: string | undefined;
347
+ let chosenSwagger: string | undefined;
348
+ for (const s of schemas) {
349
+ if (!chosenOpenapi && s && typeof (s as any).openapi === "string") {
350
+ chosenOpenapi = (s as any).openapi;
351
+ }
352
+ if (!chosenSwagger && s && typeof (s as any).swagger === "string") {
353
+ chosenSwagger = (s as any).swagger;
354
+ }
355
+ if (chosenOpenapi && chosenSwagger) {
356
+ break;
357
+ }
358
+ }
359
+ if (typeof chosenOpenapi === "string") {
360
+ merged.openapi = chosenOpenapi;
361
+ } else if (typeof chosenSwagger === "string") {
362
+ merged.swagger = chosenSwagger;
363
+ }
364
+
365
+ // Merge info: take first non-empty per-field across inputs
366
+ const infoAccumulator: any = {};
367
+ for (const s of schemas) {
368
+ const info = (s as any)?.info;
369
+ if (info && typeof info === "object") {
370
+ for (const [k, v] of Object.entries(info)) {
371
+ if (infoAccumulator[k] === undefined && v !== undefined) {
372
+ infoAccumulator[k] = JSON.parse(JSON.stringify(v));
373
+ }
374
+ }
375
+ }
376
+ }
377
+ if (Object.keys(infoAccumulator).length > 0) {
378
+ merged.info = infoAccumulator;
379
+ }
380
+
381
+ // Merge servers: union by url+description
382
+ const servers: any[] = [];
383
+ const seenServers = new Set<string>();
384
+ for (const s of schemas) {
385
+ const arr = (s as any)?.servers;
386
+ if (Array.isArray(arr)) {
387
+ for (const srv of arr) {
388
+ if (srv && typeof srv === "object") {
389
+ const key = `${srv.url || ""}|${srv.description || ""}`;
390
+ if (!seenServers.has(key)) {
391
+ seenServers.add(key);
392
+ servers.push(JSON.parse(JSON.stringify(srv)));
393
+ }
394
+ }
395
+ }
396
+ }
397
+ }
398
+ if (servers.length > 0) {
399
+ merged.servers = servers;
400
+ }
401
+
402
+ merged.paths = {};
403
+ merged.components = {};
404
+
405
+ const componentSections = [
406
+ "schemas",
407
+ "parameters",
408
+ "requestBodies",
409
+ "responses",
410
+ "headers",
411
+ "securitySchemes",
412
+ "examples",
413
+ "links",
414
+ "callbacks",
415
+ ];
416
+ for (const sec of componentSections) {
417
+ merged.components[sec] = {};
418
+ }
419
+
420
+ const tagNameSet = new Set<string>();
421
+ const tags: any[] = [];
422
+ const usedOpIds = new Set<string>();
423
+
424
+ const baseName = (p: string) => {
425
+ try {
426
+ const withoutHash = p.split("#")[0];
427
+ const parts = withoutHash.split("/");
428
+ const filename = parts[parts.length - 1] || "schema";
429
+ const dot = filename.lastIndexOf(".");
430
+ const raw = dot > 0 ? filename.substring(0, dot) : filename;
431
+ return raw.replace(/[^A-Za-z0-9_-]/g, "_");
432
+ } catch {
433
+ return "schema";
434
+ }
435
+ };
436
+ const unique = (set: Set<string>, proposed: string) => {
437
+ let name = proposed;
438
+ let i = 2;
439
+ while (set.has(name)) {
440
+ name = `${proposed}_${i++}`;
441
+ }
442
+ set.add(name);
443
+ return name;
444
+ };
445
+
446
+ const rewriteRef = (ref: string, refMap: Map<string, string>): string => {
447
+ // OAS3: #/components/{section}/{name}...
448
+ let m = ref.match(/^#\/components\/([^/]+)\/([^/]+)(.*)$/);
449
+ if (m) {
450
+ const base = `#/components/${m[1]}/${m[2]}`;
451
+ const mapped = refMap.get(base);
452
+ if (mapped) {
453
+ return mapped + (m[3] || "");
454
+ }
455
+ }
456
+ // OAS2: #/definitions/{name}...
457
+ m = ref.match(/^#\/definitions\/([^/]+)(.*)$/);
458
+ if (m) {
459
+ const base = `#/components/schemas/${m[1]}`;
460
+ const mapped = refMap.get(base);
461
+ if (mapped) {
462
+ // map definitions -> components/schemas
463
+ return mapped + (m[2] || "");
464
+ }
465
+ }
466
+ return ref;
467
+ };
468
+
469
+ const cloneAndRewrite = (
470
+ obj: any,
471
+ refMap: Map<string, string>,
472
+ tagMap: Map<string, string>,
473
+ opIdPrefix: string,
474
+ basePath: string,
475
+ ): any => {
476
+ if (obj === null || obj === undefined) {
477
+ return obj;
478
+ }
479
+ if (Array.isArray(obj)) {
480
+ return obj.map((v) => cloneAndRewrite(v, refMap, tagMap, opIdPrefix, basePath));
481
+ }
482
+ if (typeof obj !== "object") {
483
+ return obj;
484
+ }
485
+
486
+ const out: any = {};
487
+ for (const [k, v] of Object.entries(obj)) {
488
+ if (k === "$ref" && typeof v === "string") {
489
+ const s = v as string;
490
+ if (s.startsWith("#")) {
491
+ out[k] = rewriteRef(s, refMap);
492
+ } else {
493
+ const proto = url.getProtocol(s);
494
+ if (proto === undefined) {
495
+ // relative external ref -> absolutize against source base path
496
+ out[k] = url.resolve(basePath + "#", s);
497
+ } else {
498
+ out[k] = s;
499
+ }
500
+ }
501
+ } else if (k === "tags" && Array.isArray(v) && v.every((x) => typeof x === "string")) {
502
+ out[k] = v.map((t) => tagMap.get(t) || t);
503
+ } else if (k === "operationId" && typeof v === "string") {
504
+ out[k] = unique(usedOpIds, `${opIdPrefix}_${v}`);
505
+ } else {
506
+ out[k] = cloneAndRewrite(v as any, refMap, tagMap, opIdPrefix, basePath);
507
+ }
508
+ }
509
+ return out;
510
+ };
511
+
512
+ for (let i = 0; i < schemas.length; i++) {
513
+ const schema: any = schemas[i] || {};
514
+ const sourcePath = this.schemaManySources[i] || `multi://input/${i + 1}`;
515
+ const prefix = baseName(sourcePath);
516
+
517
+ // Track prefix for this source path (strip hash). Only map real file/http paths
518
+ const withoutHash = url.stripHash(sourcePath);
519
+ const protocol = url.getProtocol(withoutHash);
520
+ if (protocol === undefined || protocol === "file" || protocol === "http" || protocol === "https") {
521
+ this.sourcePathToPrefix.set(withoutHash, prefix);
522
+ }
523
+
524
+ const refMap = new Map<string, string>();
525
+ const tagMap = new Map<string, string>();
526
+
527
+ const srcComponents = (schema.components || {}) as any;
528
+ for (const sec of componentSections) {
529
+ const group = srcComponents[sec] || {};
530
+ for (const [name] of Object.entries(group)) {
531
+ const newName = `${prefix}_${name}`;
532
+ refMap.set(`#/components/${sec}/${name}`, `#/components/${sec}/${newName}`);
533
+ }
534
+ }
535
+
536
+ const srcTags: any[] = Array.isArray(schema.tags) ? schema.tags : [];
537
+ for (const t of srcTags) {
538
+ if (!t || typeof t !== "object" || typeof t.name !== "string") {
539
+ continue;
540
+ }
541
+ const desired = t.name;
542
+ const finalName = tagNameSet.has(desired) ? `${prefix}_${desired}` : desired;
543
+ tagNameSet.add(finalName);
544
+ tagMap.set(desired, finalName);
545
+ if (!tags.find((x) => x && x.name === finalName)) {
546
+ tags.push({ ...t, name: finalName });
547
+ }
548
+ }
549
+
550
+ for (const sec of componentSections) {
551
+ const group = (schema.components && schema.components[sec]) || {};
552
+ for (const [name, val] of Object.entries(group)) {
553
+ const newName = `${prefix}_${name}`;
554
+ merged.components[sec][newName] = cloneAndRewrite(val, refMap, tagMap, prefix, url.stripHash(sourcePath));
555
+ }
556
+ }
557
+
558
+ const srcPaths = (schema.paths || {}) as Record<string, any>;
559
+ for (const [p, item] of Object.entries(srcPaths)) {
560
+ let targetPath = p;
561
+ if (merged.paths[p]) {
562
+ const trimmed = p.startsWith("/") ? p.substring(1) : p;
563
+ targetPath = `/${prefix}/${trimmed}`;
564
+ }
565
+ merged.paths[targetPath] = cloneAndRewrite(item, refMap, tagMap, prefix, url.stripHash(sourcePath));
566
+ }
567
+ }
568
+
569
+ if (tags.length > 0) {
570
+ merged.tags = tags;
571
+ }
572
+
573
+ // Rebuild $refs root using the first input's path to preserve external resolution semantics
574
+ const rootPath = this.schemaManySources[0] || url.cwd();
575
+ this.$refs = new $Refs();
576
+ const rootRef = this.$refs._add(rootPath);
577
+ rootRef.pathType = url.isFileSystemPath(rootPath) ? "file" : "http";
578
+ rootRef.value = merged;
579
+ this.schema = merged;
580
+ return merged as JSONSchema;
581
+ }
226
582
  }
227
583
 
228
- export { sendRequest } from './resolvers/url.js'
584
+ export { sendRequest } from "./resolvers/url.js";
229
585
  export type { JSONSchema } from "./types/index.js";
@@ -21,10 +21,7 @@ import { urlResolver } from "./resolvers/url.js";
21
21
  * The promise resolves once all JSON references in the schema have been resolved,
22
22
  * including nested references that are contained in externally-referenced files.
23
23
  */
24
- export function resolveExternal(
25
- parser: $RefParser,
26
- options: $RefParserOptions,
27
- ) {
24
+ export function resolveExternal(parser: $RefParser, options: $RefParserOptions) {
28
25
  try {
29
26
  // console.log('Resolving $ref pointers in %s', parser.$refs._root$Ref.path);
30
27
  const promises = crawl(parser.schema, parser.$refs._root$Ref.path + "#", parser.$refs, options);
@@ -101,29 +98,33 @@ async function resolve$Ref<S extends object = JSONSchema>(
101
98
 
102
99
  // $ref.$ref = url.relative($refs._root$Ref.path, resolvedPath);
103
100
 
101
+ // If this ref points back to an input source we've already merged, avoid re-importing
102
+ // by checking if the path (without hash) matches a known source in parser and we can serve it internally later.
103
+ // We keep normal flow but ensure cache hit if already added.
104
104
  // Do we already have this $ref?
105
105
  const ref = $refs._$refs[withoutHash];
106
106
  if (ref) {
107
- // We've already parsed this $ref, so use the existing value
108
- return Promise.resolve(ref.value);
107
+ // We've already parsed this $ref, so crawl it to resolve its own externals
108
+ const promises = crawl(ref.value as S, `${withoutHash}#`, $refs, options, new Set(), true);
109
+ return Promise.all(promises);
109
110
  }
110
111
 
111
112
  // Parse the $referenced file/url
112
- const file = newFile(resolvedPath)
113
+ const file = newFile(resolvedPath);
113
114
 
114
115
  // Add a new $Ref for this file, even though we don't have the value yet.
115
116
  // This ensures that we don't simultaneously read & parse the same file multiple times
116
117
  const $refAdded = $refs._add(file.url);
117
118
 
118
119
  try {
119
- const resolvedInput = getResolvedInput({ pathOrUrlOrSchema: resolvedPath })
120
+ const resolvedInput = getResolvedInput({ pathOrUrlOrSchema: resolvedPath });
120
121
 
121
122
  $refAdded.pathType = resolvedInput.type;
122
123
 
123
124
  let promises: any = [];
124
125
 
125
- if (resolvedInput.type !== 'json') {
126
- const resolver = resolvedInput.type === 'file' ? fileResolver : urlResolver;
126
+ if (resolvedInput.type !== "json") {
127
+ const resolver = resolvedInput.type === "file" ? fileResolver : urlResolver;
127
128
  await resolver.handler({ file });
128
129
  const parseResult = await parseFile(file, options);
129
130
  $refAdded.value = parseResult.result;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hey-api/json-schema-ref-parser",
3
- "version": "1.0.8",
3
+ "version": "1.2.0",
4
4
  "description": "Parse, Resolve, and Dereference JSON Schema $ref pointers",
5
5
  "homepage": "https://heyapi.dev/",
6
6
  "repository": {