@hey-api/json-schema-ref-parser 1.2.4 → 1.3.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.
Files changed (92) hide show
  1. package/README.md +9 -84
  2. package/dist/index.d.mts +629 -0
  3. package/dist/index.d.mts.map +1 -0
  4. package/dist/index.mjs +1887 -0
  5. package/dist/index.mjs.map +1 -0
  6. package/package.json +42 -78
  7. package/src/__tests__/bundle.test.ts +59 -0
  8. package/src/__tests__/index.test.ts +43 -0
  9. package/src/__tests__/pointer.test.ts +34 -0
  10. package/src/__tests__/utils.ts +3 -0
  11. package/{lib → src}/bundle.ts +143 -229
  12. package/{lib → src}/dereference.ts +20 -43
  13. package/{lib → src}/index.ts +103 -125
  14. package/{lib → src}/options.ts +13 -9
  15. package/{lib → src}/parse.ts +19 -15
  16. package/src/parsers/binary.ts +13 -0
  17. package/{lib → src}/parsers/json.ts +5 -6
  18. package/src/parsers/text.ts +21 -0
  19. package/{lib → src}/parsers/yaml.ts +9 -9
  20. package/{lib → src}/pointer.ts +42 -23
  21. package/{lib → src}/ref.ts +25 -21
  22. package/{lib → src}/refs.ts +23 -26
  23. package/{lib → src}/resolve-external.ts +91 -60
  24. package/{lib → src}/resolvers/file.ts +7 -10
  25. package/{lib → src}/resolvers/url.ts +12 -8
  26. package/{lib → src}/types/index.ts +9 -2
  27. package/src/util/convert-path-to-posix.ts +8 -0
  28. package/{lib → src}/util/errors.ts +38 -36
  29. package/{lib → src}/util/is-windows.ts +1 -1
  30. package/{lib → src}/util/plugins.ts +7 -8
  31. package/{lib → src}/util/url.ts +41 -42
  32. package/dist/lib/__tests__/bundle.test.d.ts +0 -1
  33. package/dist/lib/__tests__/bundle.test.js +0 -50
  34. package/dist/lib/__tests__/index.test.d.ts +0 -1
  35. package/dist/lib/__tests__/index.test.js +0 -43
  36. package/dist/lib/__tests__/pointer.test.d.ts +0 -1
  37. package/dist/lib/__tests__/pointer.test.js +0 -27
  38. package/dist/lib/bundle.d.ts +0 -26
  39. package/dist/lib/bundle.js +0 -600
  40. package/dist/lib/dereference.d.ts +0 -11
  41. package/dist/lib/dereference.js +0 -226
  42. package/dist/lib/index.d.ts +0 -92
  43. package/dist/lib/index.js +0 -525
  44. package/dist/lib/options.d.ts +0 -61
  45. package/dist/lib/options.js +0 -45
  46. package/dist/lib/parse.d.ts +0 -13
  47. package/dist/lib/parse.js +0 -87
  48. package/dist/lib/parsers/binary.d.ts +0 -2
  49. package/dist/lib/parsers/binary.js +0 -12
  50. package/dist/lib/parsers/json.d.ts +0 -2
  51. package/dist/lib/parsers/json.js +0 -38
  52. package/dist/lib/parsers/text.d.ts +0 -2
  53. package/dist/lib/parsers/text.js +0 -18
  54. package/dist/lib/parsers/yaml.d.ts +0 -2
  55. package/dist/lib/parsers/yaml.js +0 -28
  56. package/dist/lib/pointer.d.ts +0 -88
  57. package/dist/lib/pointer.js +0 -297
  58. package/dist/lib/ref.d.ts +0 -180
  59. package/dist/lib/ref.js +0 -226
  60. package/dist/lib/refs.d.ts +0 -127
  61. package/dist/lib/refs.js +0 -232
  62. package/dist/lib/resolve-external.d.ts +0 -13
  63. package/dist/lib/resolve-external.js +0 -151
  64. package/dist/lib/resolvers/file.d.ts +0 -6
  65. package/dist/lib/resolvers/file.js +0 -61
  66. package/dist/lib/resolvers/url.d.ts +0 -17
  67. package/dist/lib/resolvers/url.js +0 -62
  68. package/dist/lib/types/index.d.ts +0 -43
  69. package/dist/lib/types/index.js +0 -2
  70. package/dist/lib/util/convert-path-to-posix.d.ts +0 -1
  71. package/dist/lib/util/convert-path-to-posix.js +0 -14
  72. package/dist/lib/util/errors.d.ts +0 -56
  73. package/dist/lib/util/errors.js +0 -112
  74. package/dist/lib/util/is-windows.d.ts +0 -1
  75. package/dist/lib/util/is-windows.js +0 -6
  76. package/dist/lib/util/plugins.d.ts +0 -16
  77. package/dist/lib/util/plugins.js +0 -45
  78. package/dist/lib/util/url.d.ts +0 -79
  79. package/dist/lib/util/url.js +0 -285
  80. package/dist/vite.config.d.ts +0 -2
  81. package/dist/vite.config.js +0 -19
  82. package/lib/__tests__/bundle.test.ts +0 -52
  83. package/lib/__tests__/index.test.ts +0 -45
  84. package/lib/__tests__/pointer.test.ts +0 -26
  85. package/lib/__tests__/spec/circular-ref-with-description.json +0 -11
  86. package/lib/__tests__/spec/multiple-refs.json +0 -34
  87. package/lib/__tests__/spec/openapi-paths-ref.json +0 -46
  88. package/lib/__tests__/spec/path-parameter.json +0 -16
  89. package/lib/parsers/binary.ts +0 -13
  90. package/lib/parsers/text.ts +0 -21
  91. package/lib/util/convert-path-to-posix.ts +0 -11
  92. /package/{LICENSE → LICENSE.md} +0 -0
@@ -1,10 +1,11 @@
1
- import { ono } from "@jsdevtools/ono";
2
- import { getExtension } from "./util/url.js";
3
- import * as plugins from "./util/plugins.js";
4
- import type { PluginResult } from "./util/plugins.js";
5
- import { ParserError } from "./util/errors.js";
6
- import type { $RefParserOptions } from "./options.js";
7
- import type { FileInfo } from "./types/index.js";
1
+ import { ono } from '@jsdevtools/ono';
2
+
3
+ import type { $RefParserOptions } from './options';
4
+ import type { FileInfo } from './types';
5
+ import { ParserError } from './util/errors';
6
+ import type { PluginResult } from './util/plugins';
7
+ import * as plugins from './util/plugins';
8
+ import { getExtension } from './util/url';
8
9
 
9
10
  /**
10
11
  * Prepares the file object so we can populate it with data and other values
@@ -14,8 +15,8 @@ import type { FileInfo } from "./types/index.js";
14
15
  export function newFile(path: string): FileInfo {
15
16
  let url = path;
16
17
  // Remove the URL fragment, if any
17
- const hashIndex = url.indexOf("#");
18
- let hash = "";
18
+ const hashIndex = url.indexOf('#');
19
+ let hash = '';
19
20
  if (hashIndex > -1) {
20
21
  hash = url.substring(hashIndex);
21
22
  url = url.substring(0, hashIndex);
@@ -30,23 +31,26 @@ export function newFile(path: string): FileInfo {
30
31
  /**
31
32
  * Parses the given file's contents, using the configured parser plugins.
32
33
  */
33
- export const parseFile = async (file: FileInfo, options: $RefParserOptions): Promise<PluginResult> => {
34
+ export async function parseFile(
35
+ file: FileInfo,
36
+ options: $RefParserOptions['parse'],
37
+ ): Promise<PluginResult> {
34
38
  try {
35
39
  // If none of the parsers are a match for this file, try all of them. This
36
40
  // handles situations where the file is a supported type, just with an
37
41
  // unknown extension.
38
- const parsers = [options.parse.json, options.parse.yaml, options.parse.text, options.parse.binary];
42
+ const parsers = [options.json, options.yaml, options.text, options.binary];
39
43
  const filtered = parsers.filter((plugin) => plugin.canHandle(file));
40
44
  return await plugins.run(filtered.length ? filtered : parsers, file);
41
45
  } catch (error: any) {
42
- if (error && error.message && error.message.startsWith("Error parsing")) {
46
+ if (error && error.message && error.message.startsWith('Error parsing')) {
43
47
  throw error;
44
48
  }
45
-
46
- if (!error || !("error" in error)) {
49
+
50
+ if (!error || !('error' in error)) {
47
51
  throw ono.syntax(`Unable to parse ${file.url}`);
48
52
  }
49
-
53
+
50
54
  if (error.error instanceof ParserError) {
51
55
  throw error.error;
52
56
  }
@@ -0,0 +1,13 @@
1
+ import type { FileInfo, Plugin } from '../types';
2
+
3
+ const BINARY_REGEXP = /\.(jpeg|jpg|gif|png|bmp|ico)$/i;
4
+
5
+ export const binaryParser: Plugin = {
6
+ canHandle: (file: FileInfo) => Buffer.isBuffer(file.data) && BINARY_REGEXP.test(file.url),
7
+ handler: (file: FileInfo): Buffer =>
8
+ Buffer.isBuffer(file.data)
9
+ ? file.data
10
+ : // This will reject if data is anything other than a string or typed array
11
+ Buffer.from(file.data),
12
+ name: 'binary',
13
+ };
@@ -1,6 +1,5 @@
1
- import { ParserError } from "../util/errors.js";
2
- import type { FileInfo } from "../types/index.js";
3
- import type { Plugin } from "../types/index.js";
1
+ import type { FileInfo, Plugin } from '../types';
2
+ import { ParserError } from '../util/errors';
4
3
 
5
4
  export const jsonParser: Plugin = {
6
5
  canHandle: (file: FileInfo) => file.extension === '.json',
@@ -10,7 +9,7 @@ export const jsonParser: Plugin = {
10
9
  data = data.toString();
11
10
  }
12
11
 
13
- if (typeof data !== "string") {
12
+ if (typeof data !== 'string') {
14
13
  // data is already a JavaScript value (object, array, number, null, NaN, etc.)
15
14
  return data as object;
16
15
  }
@@ -22,11 +21,11 @@ export const jsonParser: Plugin = {
22
21
 
23
22
  try {
24
23
  return JSON.parse(data);
25
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
24
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
26
25
  } catch (error: any) {
27
26
  try {
28
27
  // find the first curly brace
29
- const firstCurlyBrace = data.indexOf("{");
28
+ const firstCurlyBrace = data.indexOf('{');
30
29
  // remove any characters before the first curly brace
31
30
  data = data.slice(firstCurlyBrace);
32
31
  return JSON.parse(data);
@@ -0,0 +1,21 @@
1
+ import type { FileInfo, Plugin } from '../types';
2
+ import { ParserError } from '../util/errors';
3
+
4
+ const TEXT_REGEXP = /\.(txt|htm|html|md|xml|js|min|map|css|scss|less|svg)$/i;
5
+
6
+ export const textParser: Plugin = {
7
+ canHandle: (file: FileInfo) =>
8
+ (typeof file.data === 'string' || Buffer.isBuffer(file.data)) && TEXT_REGEXP.test(file.url),
9
+ handler(file: FileInfo): string {
10
+ if (typeof file.data === 'string') {
11
+ return file.data;
12
+ }
13
+
14
+ if (!Buffer.isBuffer(file.data)) {
15
+ throw new ParserError('data is not text', file.url);
16
+ }
17
+
18
+ return file.data.toString('utf-8');
19
+ },
20
+ name: 'text',
21
+ };
@@ -1,25 +1,25 @@
1
- import { ParserError } from "../util/errors.js";
2
- import yaml from "js-yaml";
3
- import { JSON_SCHEMA } from "js-yaml";
4
- import type { FileInfo, JSONSchema } from "../types/index.js";
5
- import type { Plugin } from "../types/index.js";
1
+ import yaml from 'js-yaml';
2
+ import { JSON_SCHEMA } from 'js-yaml';
3
+
4
+ import type { FileInfo, JSONSchema, Plugin } from '../types';
5
+ import { ParserError } from '../util/errors';
6
6
 
7
7
  export const yamlParser: Plugin = {
8
8
  // JSON is valid YAML
9
- canHandle: (file: FileInfo) => [".yaml", ".yml", ".json"].includes(file.extension),
9
+ canHandle: (file: FileInfo) => ['.yaml', '.yml', '.json'].includes(file.extension),
10
10
  handler: async (file: FileInfo): Promise<JSONSchema> => {
11
11
  const data = Buffer.isBuffer(file.data) ? file.data.toString() : file.data;
12
12
 
13
- if (typeof data !== "string") {
13
+ if (typeof data !== 'string') {
14
14
  // data is already a JavaScript value (object, array, number, null, NaN, etc.)
15
15
  return data;
16
16
  }
17
17
 
18
18
  try {
19
- const yamlSchema = yaml.load(data, { schema: JSON_SCHEMA }) as JSONSchema
19
+ const yamlSchema = yaml.load(data, { schema: JSON_SCHEMA }) as JSONSchema;
20
20
  return yamlSchema;
21
21
  } catch (error: any) {
22
- throw new ParserError(error?.message || "Parser Error", file.url);
22
+ throw new ParserError(error?.message || 'Parser Error', file.url);
23
23
  }
24
24
  },
25
25
  name: 'yaml',
@@ -1,9 +1,13 @@
1
- import type { ParserOptions } from "./options.js";
2
-
3
- import $Ref from "./ref.js";
4
- import * as url from "./util/url.js";
5
- import { JSONParserError, InvalidPointerError, MissingPointerError, isHandledError } from "./util/errors.js";
6
- import type { JSONSchema } from "./types";
1
+ import type { ParserOptions } from './options';
2
+ import $Ref from './ref';
3
+ import type { JSONSchema } from './types';
4
+ import {
5
+ InvalidPointerError,
6
+ isHandledError,
7
+ JSONParserError,
8
+ MissingPointerError,
9
+ } from './util/errors';
10
+ import * as url from './util/url';
7
11
 
8
12
  const slashes = /\//g;
9
13
  const tildes = /~/g;
@@ -100,16 +104,24 @@ class Pointer<S extends object = JSONSchema> {
100
104
  this.path = Pointer.join(this.path, tokens.slice(i));
101
105
  }
102
106
 
103
- if (typeof this.value === "object" && this.value !== null && !isRootPath(pathFromRoot) && "$ref" in this.value) {
107
+ if (
108
+ typeof this.value === 'object' &&
109
+ this.value !== null &&
110
+ !isRootPath(pathFromRoot) &&
111
+ '$ref' in this.value
112
+ ) {
104
113
  return this;
105
114
  }
106
115
 
107
- const token = tokens[i];
108
- if (this.value[token] === undefined || (this.value[token] === null && i === tokens.length - 1)) {
116
+ const token = tokens[i]!;
117
+ if (
118
+ this.value[token] === undefined ||
119
+ (this.value[token] === null && i === tokens.length - 1)
120
+ ) {
109
121
  // 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
110
122
  let didFindSubstringSlashMatch = false;
111
123
  for (let j = tokens.length - 1; j > i; j--) {
112
- const joinedToken = tokens.slice(i, j + 1).join("/");
124
+ const joinedToken = tokens.slice(i, j + 1).join('/');
113
125
  if (this.value[joinedToken] !== undefined) {
114
126
  this.value = this.value[joinedToken];
115
127
  i = j;
@@ -129,11 +141,16 @@ class Pointer<S extends object = JSONSchema> {
129
141
  }
130
142
 
131
143
  if (errors.length > 0) {
132
- throw errors.length === 1 ? errors[0] : new AggregateError(errors, "Multiple missing pointer errors");
144
+ throw errors.length === 1
145
+ ? errors[0]
146
+ : new AggregateError(errors, 'Multiple missing pointer errors');
133
147
  }
134
148
 
135
149
  // Resolve the final value
136
- if (!this.value || (this.value.$ref && url.resolve(this.path, this.value.$ref) !== pathFromRoot)) {
150
+ if (
151
+ !this.value ||
152
+ (this.value.$ref && url.resolve(this.path, this.value.$ref) !== pathFromRoot)
153
+ ) {
137
154
  resolveIf$Ref(this, options, pathFromRoot);
138
155
  }
139
156
 
@@ -166,7 +183,7 @@ class Pointer<S extends object = JSONSchema> {
166
183
  for (let i = 0; i < tokens.length - 1; i++) {
167
184
  resolveIf$Ref(this, options);
168
185
 
169
- token = tokens[i];
186
+ token = tokens[i]!;
170
187
  if (this.value && this.value[token] !== undefined) {
171
188
  // The token exists
172
189
  this.value = this.value[token];
@@ -208,14 +225,16 @@ class Pointer<S extends object = JSONSchema> {
208
225
  }
209
226
 
210
227
  // Split into an array
211
- const split = pointer.split("/");
228
+ const split = pointer.split('/');
212
229
 
213
230
  // Decode each part, according to RFC 6901
214
231
  for (let i = 0; i < split.length; i++) {
215
- split[i] = safeDecodeURIComponent(split[i].replace(escapedSlash, "/").replace(escapedTilde, "~"));
232
+ split[i] = safeDecodeURIComponent(
233
+ split[i]!.replace(escapedSlash, '/').replace(escapedTilde, '~'),
234
+ );
216
235
  }
217
236
 
218
- if (split[0] !== "") {
237
+ if (split[0] !== '') {
219
238
  throw new InvalidPointerError(pointer, originalPath === undefined ? path : originalPath);
220
239
  }
221
240
 
@@ -231,16 +250,16 @@ class Pointer<S extends object = JSONSchema> {
231
250
  */
232
251
  static join(base: string, tokens: string | string[]) {
233
252
  // Ensure that the base path contains a hash
234
- if (base.indexOf("#") === -1) {
235
- base += "#";
253
+ if (base.indexOf('#') === -1) {
254
+ base += '#';
236
255
  }
237
256
 
238
257
  // Append each token to the base path
239
258
  tokens = Array.isArray(tokens) ? tokens : [tokens];
240
259
  for (let i = 0; i < tokens.length; i++) {
241
- const token = tokens[i];
260
+ const token = tokens[i]!;
242
261
  // Encode the token, according to RFC 6901
243
- base += "/" + encodeURIComponent(token.replace(tildes, "~0").replace(slashes, "~1"));
262
+ base += '/' + encodeURIComponent(token.replace(tildes, '~0').replace(slashes, '~1'));
244
263
  }
245
264
 
246
265
  return base;
@@ -306,8 +325,8 @@ export default Pointer;
306
325
  * @returns - Returns the assigned value
307
326
  */
308
327
  function setValue(pointer: any, token: any, value: any) {
309
- if (pointer.value && typeof pointer.value === "object") {
310
- if (token === "-" && Array.isArray(pointer.value)) {
328
+ if (pointer.value && typeof pointer.value === 'object') {
329
+ if (token === '-' && Array.isArray(pointer.value)) {
311
330
  pointer.value.push(value);
312
331
  } else {
313
332
  pointer.value[token] = value;
@@ -329,5 +348,5 @@ function unwrapOrThrow(value: any) {
329
348
  }
330
349
 
331
350
  function isRootPath(pathFromRoot: any): boolean {
332
- return typeof pathFromRoot == "string" && Pointer.parse(pathFromRoot).length == 0;
351
+ return typeof pathFromRoot == 'string' && Pointer.parse(pathFromRoot).length == 0;
333
352
  }
@@ -1,9 +1,14 @@
1
- import Pointer from "./pointer.js";
2
- import type { JSONParserError, MissingPointerError, ParserError, ResolverError } from "./util/errors.js";
3
- import { normalizeError } from "./util/errors.js";
4
- import type $Refs from "./refs.js";
5
- import type { ParserOptions } from "./options.js";
6
- import type { JSONSchema } from "./types";
1
+ import type { ParserOptions } from './options';
2
+ import Pointer from './pointer';
3
+ import type $Refs from './refs';
4
+ import type { JSONSchema } from './types';
5
+ import type {
6
+ JSONParserError,
7
+ MissingPointerError,
8
+ ParserError,
9
+ ResolverError,
10
+ } from './util/errors';
11
+ import { normalizeError } from './util/errors';
7
12
 
8
13
  export type $RefError = JSONParserError | ResolverError | ParserError | MissingPointerError;
9
14
 
@@ -70,11 +75,13 @@ class $Ref<S extends object = JSONSchema> {
70
75
  // the path has been almost certainly set at this point,
71
76
  // but just in case something went wrong, normalizeError injects path if necessary
72
77
  // moreover, certain errors might point at the same spot, so filter them out to reduce noise
73
- if ("errors" in err && Array.isArray(err.errors)) {
78
+ if ('errors' in err && Array.isArray(err.errors)) {
74
79
  this.errors.push(
75
- ...err.errors.map(normalizeError).filter(({ footprint }: any) => !existingErrors.includes(footprint)),
80
+ ...err.errors
81
+ .map(normalizeError)
82
+ .filter(({ footprint }: any) => !existingErrors.includes(footprint)),
76
83
  );
77
- } else if (!("footprint" in err) || !existingErrors.includes(err.footprint)) {
84
+ } else if (!('footprint' in err) || !existingErrors.includes(err.footprint)) {
78
85
  this.errors.push(normalizeError(err));
79
86
  }
80
87
  }
@@ -141,10 +148,10 @@ class $Ref<S extends object = JSONSchema> {
141
148
  static is$Ref(value: unknown): value is { $ref: string; length?: number } {
142
149
  return (
143
150
  Boolean(value) &&
144
- typeof value === "object" &&
151
+ typeof value === 'object' &&
145
152
  value !== null &&
146
- "$ref" in value &&
147
- typeof value.$ref === "string" &&
153
+ '$ref' in value &&
154
+ typeof value.$ref === 'string' &&
148
155
  value.$ref.length > 0
149
156
  );
150
157
  }
@@ -156,7 +163,7 @@ class $Ref<S extends object = JSONSchema> {
156
163
  * @returns
157
164
  */
158
165
  static isExternal$Ref(value: unknown): boolean {
159
- return $Ref.is$Ref(value) && value.$ref![0] !== "#";
166
+ return $Ref.is$Ref(value) && value.$ref![0] !== '#';
160
167
  }
161
168
 
162
169
  /**
@@ -168,10 +175,10 @@ class $Ref<S extends object = JSONSchema> {
168
175
  */
169
176
  static isAllowed$Ref(value: unknown) {
170
177
  if (this.is$Ref(value)) {
171
- if (value.$ref.substring(0, 2) === "#/" || value.$ref === "#") {
178
+ if (value.$ref.substring(0, 2) === '#/' || value.$ref === '#') {
172
179
  // It's a JSON Pointer reference, which is always allowed
173
180
  return true;
174
- } else if (value.$ref[0] !== "#") {
181
+ } else if (value.$ref[0] !== '#') {
175
182
  // It's an external reference, which is allowed by the options
176
183
  return true;
177
184
  }
@@ -248,14 +255,11 @@ class $Ref<S extends object = JSONSchema> {
248
255
  * @param resolvedValue - The resolved value, which can be any type
249
256
  * @returns - Returns the dereferenced value
250
257
  */
251
- static dereference<S extends object = JSONSchema>(
252
- $ref: $Ref<S>,
253
- resolvedValue: S,
254
- ): S {
255
- if (resolvedValue && typeof resolvedValue === "object" && $Ref.isExtended$Ref($ref)) {
258
+ static dereference<S extends object = JSONSchema>($ref: $Ref<S>, resolvedValue: S): S {
259
+ if (resolvedValue && typeof resolvedValue === 'object' && $Ref.isExtended$Ref($ref)) {
256
260
  const merged = {};
257
261
  for (const key of Object.keys($ref)) {
258
- if (key !== "$ref") {
262
+ if (key !== '$ref') {
259
263
  // @ts-expect-error TS(7053): Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
260
264
  merged[key] = $ref[key];
261
265
  }
@@ -1,10 +1,11 @@
1
- import { ono } from "@jsdevtools/ono";
2
- import $Ref from "./ref.js";
3
- import * as url from "./util/url.js";
4
- import type { JSONSchema4Type, JSONSchema6Type, JSONSchema7Type } from "json-schema";
5
- import type { ParserOptions } from "./options.js";
6
- import convertPathToPosix from "./util/convert-path-to-posix";
7
- import type { JSONSchema } from "./types";
1
+ import { ono } from '@jsdevtools/ono';
2
+ import type { JSONSchema4Type, JSONSchema6Type, JSONSchema7Type } from 'json-schema';
3
+
4
+ import type { ParserOptions } from './options';
5
+ import $Ref from './ref';
6
+ import type { JSONSchema } from './types';
7
+ import convertPathToPosix from './util/convert-path-to-posix';
8
+ import * as url from './util/url';
8
9
 
9
10
  interface $RefsMap<S extends object = JSONSchema> {
10
11
  [url: string]: $Ref<S>;
@@ -33,9 +34,7 @@ export default class $Refs<S extends object = JSONSchema> {
33
34
  */
34
35
  paths(...types: (string | string[])[]): string[] {
35
36
  const paths = getPaths(this._$refs, types.flat());
36
- return paths.map((path) => {
37
- return convertPathToPosix(path.decoded);
38
- });
37
+ return paths.map((path) => convertPathToPosix(path.decoded));
39
38
  }
40
39
 
41
40
  /**
@@ -49,7 +48,7 @@ export default class $Refs<S extends object = JSONSchema> {
49
48
  const $refs = this._$refs;
50
49
  const paths = getPaths($refs, types.flat());
51
50
  return paths.reduce<Record<string, any>>((obj, path) => {
52
- obj[convertPathToPosix(path.decoded)] = $refs[path.encoded].value;
51
+ obj[convertPathToPosix(path.decoded)] = $refs[path.encoded]!.value;
53
52
  return obj;
54
53
  }, {}) as S;
55
54
  }
@@ -70,7 +69,7 @@ export default class $Refs<S extends object = JSONSchema> {
70
69
  */
71
70
  exists(path: string, options: any) {
72
71
  try {
73
- this._resolve(path, "", options);
72
+ this._resolve(path, '', options);
74
73
  return true;
75
74
  } catch {
76
75
  return false;
@@ -85,7 +84,7 @@ export default class $Refs<S extends object = JSONSchema> {
85
84
  * @returns - Returns the resolved value
86
85
  */
87
86
  get(path: string, options?: ParserOptions): JSONSchema4Type | JSONSchema6Type | JSONSchema7Type {
88
- return this._resolve(path, "", options)!.value;
87
+ return this._resolve(path, '', options)!.value;
89
88
  }
90
89
 
91
90
  /**
@@ -153,6 +152,11 @@ export default class $Refs<S extends object = JSONSchema> {
153
152
  throw ono(`Error resolving $ref pointer "${path}". \n"${withoutHash}" not found.`);
154
153
  }
155
154
 
155
+ if ($ref.value === undefined) {
156
+ console.warn(`$ref entry exists but value is undefined: ${withoutHash}`);
157
+ return null; // Treat as unresolved
158
+ }
159
+
156
160
  return $ref.resolve(absPath, options, path, pathFromRoot);
157
161
  }
158
162
 
@@ -215,25 +219,18 @@ export default class $Refs<S extends object = JSONSchema> {
215
219
  * @param [types] - Only return paths of the given types ("file", "http", etc.)
216
220
  * @returns
217
221
  */
218
- function getPaths<S extends object = JSONSchema>(
219
- $refs: $RefsMap<S>,
220
- types: string[],
221
- ) {
222
+ function getPaths<S extends object = JSONSchema>($refs: $RefsMap<S>, types: string[]) {
222
223
  let paths = Object.keys($refs);
223
224
 
224
225
  // Filter the paths by type
225
226
  types = Array.isArray(types[0]) ? types[0] : Array.prototype.slice.call(types);
226
227
  if (types.length > 0 && types[0]) {
227
- paths = paths.filter((key) => {
228
- return types.includes($refs[key].pathType as string);
229
- });
228
+ paths = paths.filter((key) => types.includes($refs[key]!.pathType as string));
230
229
  }
231
230
 
232
231
  // Decode local filesystem paths
233
- return paths.map((path) => {
234
- return {
235
- encoded: path,
236
- decoded: $refs[path].pathType === "file" ? url.toFileSystemPath(path, true) : path,
237
- };
238
- });
232
+ return paths.map((path) => ({
233
+ decoded: $refs[path]!.pathType === 'file' ? url.toFileSystemPath(path, true) : path,
234
+ encoded: path,
235
+ }));
239
236
  }