@apidevtools/json-schema-ref-parser 10.0.1 → 11.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.
Files changed (111) hide show
  1. package/README.md +22 -0
  2. package/dist/lib/bundle.d.ts +10 -0
  3. package/dist/lib/bundle.js +266 -0
  4. package/dist/lib/dereference.d.ts +9 -0
  5. package/dist/lib/dereference.js +206 -0
  6. package/dist/lib/index.d.ts +206 -0
  7. package/dist/lib/index.js +206 -0
  8. package/dist/lib/normalize-args.d.ts +10 -0
  9. package/dist/lib/normalize-args.js +42 -0
  10. package/dist/lib/options.d.ts +77 -0
  11. package/dist/lib/options.js +119 -0
  12. package/dist/lib/parse.d.ts +8 -0
  13. package/dist/lib/parse.js +162 -0
  14. package/dist/lib/parsers/binary.d.ts +3 -0
  15. package/dist/lib/parsers/binary.js +35 -0
  16. package/dist/lib/parsers/json.d.ts +3 -0
  17. package/dist/lib/parsers/json.js +46 -0
  18. package/dist/lib/parsers/text.d.ts +3 -0
  19. package/dist/lib/parsers/text.js +42 -0
  20. package/dist/lib/parsers/yaml.d.ts +3 -0
  21. package/dist/lib/parsers/yaml.js +54 -0
  22. package/dist/lib/pointer.d.ts +87 -0
  23. package/dist/lib/pointer.js +256 -0
  24. package/dist/lib/ref.d.ts +180 -0
  25. package/dist/lib/ref.js +238 -0
  26. package/dist/lib/refs.d.ts +127 -0
  27. package/dist/lib/refs.js +222 -0
  28. package/dist/lib/resolve-external.d.ts +14 -0
  29. package/dist/lib/resolve-external.js +133 -0
  30. package/dist/lib/resolvers/file.d.ts +3 -0
  31. package/dist/lib/resolvers/file.js +62 -0
  32. package/dist/lib/resolvers/http.d.ts +3 -0
  33. package/dist/lib/resolvers/http.js +146 -0
  34. package/dist/lib/types/index.d.ts +104 -0
  35. package/dist/lib/types/index.js +2 -0
  36. package/dist/lib/util/convert-path-to-posix.d.ts +1 -0
  37. package/dist/lib/util/convert-path-to-posix.js +14 -0
  38. package/dist/lib/util/errors.d.ts +50 -0
  39. package/dist/lib/util/errors.js +106 -0
  40. package/dist/lib/util/is-windows.d.ts +1 -0
  41. package/dist/lib/util/is-windows.js +6 -0
  42. package/dist/lib/util/maybe.d.ts +3 -0
  43. package/dist/lib/util/maybe.js +24 -0
  44. package/dist/lib/util/next.d.ts +2 -0
  45. package/dist/lib/util/next.js +16 -0
  46. package/dist/lib/util/plugins.d.ts +36 -0
  47. package/dist/lib/util/plugins.js +133 -0
  48. package/dist/lib/util/url.d.ts +94 -0
  49. package/dist/lib/util/url.js +304 -0
  50. package/dist/vite.config.d.ts +2 -0
  51. package/dist/vite.config.js +19 -0
  52. package/lib/{bundle.js → bundle.ts} +106 -101
  53. package/lib/{dereference.js → dereference.ts} +113 -52
  54. package/lib/index.ts +413 -0
  55. package/lib/{normalize-args.js → normalize-args.ts} +7 -14
  56. package/lib/options.ts +202 -0
  57. package/lib/parse.ts +153 -0
  58. package/lib/parsers/binary.ts +39 -0
  59. package/lib/parsers/{json.js → json.ts} +9 -22
  60. package/lib/parsers/text.ts +46 -0
  61. package/lib/parsers/{yaml.js → yaml.ts} +15 -19
  62. package/lib/pointer.ts +296 -0
  63. package/lib/ref.ts +287 -0
  64. package/lib/refs.ts +236 -0
  65. package/lib/{resolve-external.js → resolve-external.ts} +44 -41
  66. package/lib/resolvers/file.ts +40 -0
  67. package/lib/resolvers/http.ts +136 -0
  68. package/lib/tsconfig.json +103 -0
  69. package/lib/types/index.ts +135 -0
  70. package/lib/util/convert-path-to-posix.ts +11 -0
  71. package/lib/util/errors.ts +141 -0
  72. package/lib/util/is-windows.ts +2 -0
  73. package/lib/util/maybe.ts +22 -0
  74. package/lib/util/next.ts +13 -0
  75. package/lib/util/{plugins.js → plugins.ts} +58 -57
  76. package/lib/util/{url.js → url.ts} +92 -91
  77. package/package.json +44 -46
  78. package/cjs/bundle.js +0 -304
  79. package/cjs/dereference.js +0 -258
  80. package/cjs/index.js +0 -603
  81. package/cjs/normalize-args.js +0 -64
  82. package/cjs/options.js +0 -125
  83. package/cjs/package.json +0 -3
  84. package/cjs/parse.js +0 -338
  85. package/cjs/parsers/binary.js +0 -54
  86. package/cjs/parsers/json.js +0 -199
  87. package/cjs/parsers/text.js +0 -61
  88. package/cjs/parsers/yaml.js +0 -239
  89. package/cjs/pointer.js +0 -290
  90. package/cjs/ref.js +0 -333
  91. package/cjs/refs.js +0 -214
  92. package/cjs/resolve-external.js +0 -333
  93. package/cjs/resolvers/file.js +0 -106
  94. package/cjs/resolvers/http.js +0 -184
  95. package/cjs/util/errors.js +0 -401
  96. package/cjs/util/plugins.js +0 -159
  97. package/cjs/util/projectDir.cjs +0 -6
  98. package/cjs/util/url.js +0 -228
  99. package/lib/index.d.ts +0 -496
  100. package/lib/index.js +0 -290
  101. package/lib/options.js +0 -128
  102. package/lib/parse.js +0 -162
  103. package/lib/parsers/binary.js +0 -53
  104. package/lib/parsers/text.js +0 -64
  105. package/lib/pointer.js +0 -293
  106. package/lib/ref.js +0 -292
  107. package/lib/refs.js +0 -196
  108. package/lib/resolvers/file.js +0 -63
  109. package/lib/resolvers/http.js +0 -155
  110. package/lib/util/errors.js +0 -134
  111. package/lib/util/projectDir.cjs +0 -6
package/lib/ref.ts ADDED
@@ -0,0 +1,287 @@
1
+ import Pointer from "./pointer.js";
2
+ import type { JSONParserError, MissingPointerError, ParserError, ResolverError } from "./util/errors.js";
3
+ import { InvalidPointerError, isHandledError, normalizeError } from "./util/errors.js";
4
+ import { safePointerToPath, stripHash, getHash } from "./util/url.js";
5
+ import type $Refs from "./refs.js";
6
+ import type $RefParserOptions from "./options.js";
7
+
8
+ type $RefError = JSONParserError | ResolverError | ParserError | MissingPointerError;
9
+
10
+ /**
11
+ * This class represents a single JSON reference and its resolved value.
12
+ *
13
+ * @class
14
+ */
15
+ class $Ref {
16
+ /**
17
+ * The file path or URL of the referenced file.
18
+ * This path is relative to the path of the main JSON schema file.
19
+ *
20
+ * This path does NOT contain document fragments (JSON pointers). It always references an ENTIRE file.
21
+ * Use methods such as {@link $Ref#get}, {@link $Ref#resolve}, and {@link $Ref#exists} to get
22
+ * specific JSON pointers within the file.
23
+ *
24
+ * @type {string}
25
+ */
26
+ path: undefined | string;
27
+
28
+ /**
29
+ * The resolved value of the JSON reference.
30
+ * Can be any JSON type, not just objects. Unknown file types are represented as Buffers (byte arrays).
31
+ *
32
+ * @type {?*}
33
+ */
34
+ value: any;
35
+
36
+ /**
37
+ * The {@link $Refs} object that contains this {@link $Ref} object.
38
+ *
39
+ * @type {$Refs}
40
+ */
41
+ $refs: $Refs;
42
+
43
+ /**
44
+ * Indicates the type of {@link $Ref#path} (e.g. "file", "http", etc.)
45
+ */
46
+ pathType: string | unknown;
47
+
48
+ /**
49
+ * List of all errors. Undefined if no errors.
50
+ */
51
+ errors: Array<$RefError> = [];
52
+
53
+ constructor($refs: $Refs) {
54
+ this.$refs = $refs;
55
+ }
56
+
57
+ /**
58
+ * Pushes an error to errors array.
59
+ *
60
+ * @param err - The error to be pushed
61
+ * @returns
62
+ */
63
+ addError(err: $RefError) {
64
+ if (this.errors === undefined) {
65
+ this.errors = [];
66
+ }
67
+
68
+ const existingErrors = this.errors.map(({ footprint }: any) => footprint);
69
+
70
+ // the path has been almost certainly set at this point,
71
+ // but just in case something went wrong, normalizeError injects path if necessary
72
+ // 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)) {
74
+ this.errors.push(
75
+ ...err.errors.map(normalizeError).filter(({ footprint }: any) => !existingErrors.includes(footprint)),
76
+ );
77
+ } else if (!("footprint" in err) || !existingErrors.includes(err.footprint)) {
78
+ this.errors.push(normalizeError(err));
79
+ }
80
+ }
81
+
82
+ /**
83
+ * Determines whether the given JSON reference exists within this {@link $Ref#value}.
84
+ *
85
+ * @param path - The full path being resolved, optionally with a JSON pointer in the hash
86
+ * @param options
87
+ * @returns
88
+ */
89
+ exists(path: string, options: any) {
90
+ try {
91
+ this.resolve(path, options);
92
+ return true;
93
+ } catch (e) {
94
+ return false;
95
+ }
96
+ }
97
+
98
+ /**
99
+ * Resolves the given JSON reference within this {@link $Ref#value} and returns the resolved value.
100
+ *
101
+ * @param path - The full path being resolved, optionally with a JSON pointer in the hash
102
+ * @param options
103
+ * @returns - Returns the resolved value
104
+ */
105
+ get(path: any, options: any) {
106
+ return this.resolve(path, options)?.value;
107
+ }
108
+
109
+ /**
110
+ * Resolves the given JSON reference within this {@link $Ref#value}.
111
+ *
112
+ * @param path - The full path being resolved, optionally with a JSON pointer in the hash
113
+ * @param options
114
+ * @param friendlyPath - The original user-specified path (used for error messages)
115
+ * @param pathFromRoot - The path of `obj` from the schema root
116
+ * @returns
117
+ */
118
+ resolve(path: any, options?: $RefParserOptions, friendlyPath?: string, pathFromRoot?: string) {
119
+ const pointer = new Pointer(this, path, friendlyPath);
120
+ try {
121
+ return pointer.resolve(this.value, options, pathFromRoot);
122
+ } catch (err: any) {
123
+ if (!options || !options.continueOnError || !isHandledError(err)) {
124
+ throw err;
125
+ }
126
+
127
+ if (err.path === null) {
128
+ err.path = safePointerToPath(getHash(pathFromRoot));
129
+ }
130
+
131
+ if (err instanceof InvalidPointerError) {
132
+ err.source = decodeURI(stripHash(pathFromRoot));
133
+ }
134
+
135
+ this.addError(err);
136
+ return null;
137
+ }
138
+ }
139
+
140
+ /**
141
+ * Sets the value of a nested property within this {@link $Ref#value}.
142
+ * If the property, or any of its parents don't exist, they will be created.
143
+ *
144
+ * @param path - The full path of the property to set, optionally with a JSON pointer in the hash
145
+ * @param value - The value to assign
146
+ */
147
+ set(path: any, value: any) {
148
+ // @ts-expect-error TS(2554): Expected 3 arguments, but got 2.
149
+ const pointer = new Pointer(this, path);
150
+ this.value = pointer.set(this.value, value);
151
+ }
152
+
153
+ /**
154
+ * Determines whether the given value is a JSON reference.
155
+ *
156
+ * @param value - The value to inspect
157
+ * @returns
158
+ */
159
+ static is$Ref(value: any): value is { $ref: string; length?: number } {
160
+ return value && typeof value === "object" && typeof value.$ref === "string" && value.$ref.length > 0;
161
+ }
162
+
163
+ /**
164
+ * Determines whether the given value is an external JSON reference.
165
+ *
166
+ * @param value - The value to inspect
167
+ * @returns
168
+ */
169
+ static isExternal$Ref(value: any): boolean {
170
+ return $Ref.is$Ref(value) && value.$ref![0] !== "#";
171
+ }
172
+
173
+ /**
174
+ * Determines whether the given value is a JSON reference, and whether it is allowed by the options.
175
+ * For example, if it references an external file, then options.resolve.external must be true.
176
+ *
177
+ * @param value - The value to inspect
178
+ * @param options
179
+ * @returns
180
+ */
181
+ static isAllowed$Ref(value: any, options: any) {
182
+ if (this.is$Ref(value)) {
183
+ if (value.$ref.substring(0, 2) === "#/" || value.$ref === "#") {
184
+ // It's a JSON Pointer reference, which is always allowed
185
+ return true;
186
+ } else if (value.$ref[0] !== "#" && (!options || options.resolve.external)) {
187
+ // It's an external reference, which is allowed by the options
188
+ return true;
189
+ }
190
+ }
191
+ }
192
+
193
+ /**
194
+ * Determines whether the given value is a JSON reference that "extends" its resolved value.
195
+ * That is, it has extra properties (in addition to "$ref"), so rather than simply pointing to
196
+ * an existing value, this $ref actually creates a NEW value that is a shallow copy of the resolved
197
+ * value, plus the extra properties.
198
+ *
199
+ * @example: {
200
+ person: {
201
+ properties: {
202
+ firstName: { type: string }
203
+ lastName: { type: string }
204
+ }
205
+ }
206
+ employee: {
207
+ properties: {
208
+ $ref: #/person/properties
209
+ salary: { type: number }
210
+ }
211
+ }
212
+ }
213
+ * In this example, "employee" is an extended $ref, since it extends "person" with an additional
214
+ * property (salary). The result is a NEW value that looks like this:
215
+ *
216
+ * {
217
+ * properties: {
218
+ * firstName: { type: string }
219
+ * lastName: { type: string }
220
+ * salary: { type: number }
221
+ * }
222
+ * }
223
+ *
224
+ * @param value - The value to inspect
225
+ * @returns
226
+ */
227
+ static isExtended$Ref(value: any) {
228
+ return $Ref.is$Ref(value) && Object.keys(value).length > 1;
229
+ }
230
+
231
+ /**
232
+ * Returns the resolved value of a JSON Reference.
233
+ * If necessary, the resolved value is merged with the JSON Reference to create a new object
234
+ *
235
+ * @example: {
236
+ person: {
237
+ properties: {
238
+ firstName: { type: string }
239
+ lastName: { type: string }
240
+ }
241
+ }
242
+ employee: {
243
+ properties: {
244
+ $ref: #/person/properties
245
+ salary: { type: number }
246
+ }
247
+ }
248
+ } When "person" and "employee" are merged, you end up with the following object:
249
+ *
250
+ * {
251
+ * properties: {
252
+ * firstName: { type: string }
253
+ * lastName: { type: string }
254
+ * salary: { type: number }
255
+ * }
256
+ * }
257
+ *
258
+ * @param $ref - The JSON reference object (the one with the "$ref" property)
259
+ * @param resolvedValue - The resolved value, which can be any type
260
+ * @returns - Returns the dereferenced value
261
+ */
262
+ static dereference($ref: $Ref, resolvedValue: any) {
263
+ if (resolvedValue && typeof resolvedValue === "object" && $Ref.isExtended$Ref($ref)) {
264
+ const merged = {};
265
+ for (const key of Object.keys($ref)) {
266
+ if (key !== "$ref") {
267
+ // @ts-expect-error TS(7053): Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
268
+ merged[key] = $ref[key];
269
+ }
270
+ }
271
+
272
+ for (const key of Object.keys(resolvedValue)) {
273
+ if (!(key in merged)) {
274
+ // @ts-expect-error TS(7053): Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
275
+ merged[key] = resolvedValue[key];
276
+ }
277
+ }
278
+
279
+ return merged;
280
+ } else {
281
+ // Completely replace the original reference with the resolved value
282
+ return resolvedValue;
283
+ }
284
+ }
285
+ }
286
+
287
+ export default $Ref;
package/lib/refs.ts ADDED
@@ -0,0 +1,236 @@
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 { JSONSchema } from "./types/index.js";
6
+ import type $RefParserOptions from "./options.js";
7
+ import convertPathToPosix from "./util/convert-path-to-posix";
8
+
9
+ interface $RefsMap {
10
+ [url: string]: $Ref;
11
+ }
12
+ /**
13
+ * When you call the resolve method, the value that gets passed to the callback function (or Promise) is a $Refs object. This same object is accessible via the parser.$refs property of $RefParser objects.
14
+ *
15
+ * This object is a map of JSON References and their resolved values. It also has several convenient helper methods that make it easy for you to navigate and manipulate the JSON References.
16
+ *
17
+ * See https://apitools.dev/json-schema-ref-parser/docs/refs.html
18
+ */
19
+ export default class $Refs {
20
+ /**
21
+ * This property is true if the schema contains any circular references. You may want to check this property before serializing the dereferenced schema as JSON, since JSON.stringify() does not support circular references by default.
22
+ *
23
+ * See https://apitools.dev/json-schema-ref-parser/docs/refs.html#circular
24
+ */
25
+ public circular: boolean;
26
+
27
+ /**
28
+ * Returns the paths/URLs of all the files in your schema (including the main schema file).
29
+ *
30
+ * See https://apitools.dev/json-schema-ref-parser/docs/refs.html#pathstypes
31
+ *
32
+ * @param types (optional) Optionally only return certain types of paths ("file", "http", etc.)
33
+ */
34
+ paths(...types: string[]): string[] {
35
+ const paths = getPaths(this._$refs, types);
36
+ return paths.map((path) => {
37
+ return convertPathToPosix(path.decoded);
38
+ });
39
+ }
40
+
41
+ /**
42
+ * Returns a map of paths/URLs and their correspond values.
43
+ *
44
+ * See https://apitools.dev/json-schema-ref-parser/docs/refs.html#valuestypes
45
+ *
46
+ * @param types (optional) Optionally only return values from certain locations ("file", "http", etc.)
47
+ */
48
+ values(...types: string[]): JSONSchema {
49
+ const $refs = this._$refs;
50
+ const paths = getPaths($refs, types);
51
+ return paths.reduce<Record<string, any>>((obj, path) => {
52
+ obj[convertPathToPosix(path.decoded)] = $refs[path.encoded].value;
53
+ return obj;
54
+ }, {});
55
+ }
56
+
57
+ /**
58
+ * Returns `true` if the given path exists in the schema; otherwise, returns `false`
59
+ *
60
+ * See https://apitools.dev/json-schema-ref-parser/docs/refs.html#existsref
61
+ *
62
+ * @param $ref The JSON Reference path, optionally with a JSON Pointer in the hash
63
+ */
64
+ /**
65
+ * Determines whether the given JSON reference exists.
66
+ *
67
+ * @param path - The path being resolved, optionally with a JSON pointer in the hash
68
+ * @param [options]
69
+ * @returns
70
+ */
71
+ exists(path: string, options: any) {
72
+ try {
73
+ this._resolve(path, "", options);
74
+ return true;
75
+ } catch (e) {
76
+ return false;
77
+ }
78
+ }
79
+
80
+ /**
81
+ * Resolves the given JSON reference and returns the resolved value.
82
+ *
83
+ * @param path - The path being resolved, with a JSON pointer in the hash
84
+ * @param [options]
85
+ * @returns - Returns the resolved value
86
+ */
87
+ get(path: string, options?: $RefParserOptions): JSONSchema4Type | JSONSchema6Type | JSONSchema7Type {
88
+ return this._resolve(path, "", options)!.value;
89
+ }
90
+
91
+ /**
92
+ * Sets the value at the given path in the schema. If the property, or any of its parents, don't exist, they will be created.
93
+ *
94
+ * @param $ref The JSON Reference path, optionally with a JSON Pointer in the hash
95
+ * @param value The value to assign. Can be anything (object, string, number, etc.)
96
+ */
97
+ set(path: any, value: JSONSchema4Type | JSONSchema6Type | JSONSchema7Type) {
98
+ const absPath = url.resolve(this._root$Ref.path, path);
99
+ const withoutHash = url.stripHash(absPath);
100
+ const $ref = this._$refs[withoutHash];
101
+
102
+ if (!$ref) {
103
+ throw ono(`Error resolving $ref pointer "${path}". \n"${withoutHash}" not found.`);
104
+ }
105
+
106
+ $ref.set(absPath, value);
107
+ }
108
+ /**
109
+ * Returns the specified {@link $Ref} object, or undefined.
110
+ *
111
+ * @param path - The path being resolved, optionally with a JSON pointer in the hash
112
+ * @returns
113
+ * @protected
114
+ */
115
+ _get$Ref(path: any) {
116
+ path = url.resolve(this._root$Ref.path, path);
117
+ const withoutHash = url.stripHash(path);
118
+ return this._$refs[withoutHash];
119
+ }
120
+
121
+ /**
122
+ * Creates a new {@link $Ref} object and adds it to this {@link $Refs} object.
123
+ *
124
+ * @param path - The file path or URL of the referenced file
125
+ */
126
+ _add(path: string) {
127
+ const withoutHash = url.stripHash(path);
128
+
129
+ const $ref = new $Ref(this);
130
+ $ref.path = withoutHash;
131
+
132
+ this._$refs[withoutHash] = $ref;
133
+ this._root$Ref = this._root$Ref || $ref;
134
+
135
+ return $ref;
136
+ }
137
+
138
+ /**
139
+ * Resolves the given JSON reference.
140
+ *
141
+ * @param path - The path being resolved, optionally with a JSON pointer in the hash
142
+ * @param pathFromRoot - The path of `obj` from the schema root
143
+ * @param [options]
144
+ * @returns
145
+ * @protected
146
+ */
147
+ _resolve(path: string, pathFromRoot: string, options?: any) {
148
+ const absPath = url.resolve(this._root$Ref.path, path);
149
+ const withoutHash = url.stripHash(absPath);
150
+ const $ref = this._$refs[withoutHash];
151
+
152
+ if (!$ref) {
153
+ throw ono(`Error resolving $ref pointer "${path}". \n"${withoutHash}" not found.`);
154
+ }
155
+
156
+ return $ref.resolve(absPath, options, path, pathFromRoot);
157
+ }
158
+
159
+ /**
160
+ * A map of paths/urls to {@link $Ref} objects
161
+ *
162
+ * @type {object}
163
+ * @protected
164
+ */
165
+ _$refs: $RefsMap = {};
166
+
167
+ /**
168
+ * The {@link $Ref} object that is the root of the JSON schema.
169
+ *
170
+ * @type {$Ref}
171
+ * @protected
172
+ */
173
+ _root$Ref: $Ref;
174
+
175
+ constructor() {
176
+ /**
177
+ * Indicates whether the schema contains any circular references.
178
+ *
179
+ * @type {boolean}
180
+ */
181
+ this.circular = false;
182
+
183
+ this._$refs = {};
184
+
185
+ // @ts-ignore
186
+ this._root$Ref = null;
187
+ }
188
+
189
+ /**
190
+ * Returns the paths of all the files/URLs that are referenced by the JSON schema,
191
+ * including the schema itself.
192
+ *
193
+ * @param [types] - Only return paths of the given types ("file", "http", etc.)
194
+ * @returns
195
+ */
196
+ /**
197
+ * Returns the map of JSON references and their resolved values.
198
+ *
199
+ * @param [types] - Only return references of the given types ("file", "http", etc.)
200
+ * @returns
201
+ */
202
+
203
+ /**
204
+ * Returns a POJO (plain old JavaScript object) for serialization as JSON.
205
+ *
206
+ * @returns {object}
207
+ */
208
+ toJSON = this.values;
209
+ }
210
+
211
+ /**
212
+ * Returns the encoded and decoded paths keys of the given object.
213
+ *
214
+ * @param $refs - The object whose keys are URL-encoded paths
215
+ * @param [types] - Only return paths of the given types ("file", "http", etc.)
216
+ * @returns
217
+ */
218
+ function getPaths($refs: $RefsMap, types: string[]) {
219
+ let paths = Object.keys($refs);
220
+
221
+ // Filter the paths by type
222
+ types = Array.isArray(types[0]) ? types[0] : Array.prototype.slice.call(types);
223
+ if (types.length > 0 && types[0]) {
224
+ paths = paths.filter((key) => {
225
+ return types.includes($refs[key].pathType as string);
226
+ });
227
+ }
228
+
229
+ // Decode local filesystem paths
230
+ return paths.map((path) => {
231
+ return {
232
+ encoded: path,
233
+ decoded: $refs[path].pathType === "file" ? url.toFileSystemPath(path, true) : path,
234
+ };
235
+ });
236
+ }
@@ -3,6 +3,10 @@ import Pointer from "./pointer.js";
3
3
  import parse from "./parse.js";
4
4
  import * as url from "./util/url.js";
5
5
  import { isHandledError } from "./util/errors.js";
6
+ import type $Refs from "./refs.js";
7
+ import type { Options } from "./options.js";
8
+ import type { JSONSchema } from "./types/index.js";
9
+ import type $RefParser from "./index.js";
6
10
 
7
11
  export default resolveExternal;
8
12
 
@@ -12,14 +16,11 @@ export default resolveExternal;
12
16
  *
13
17
  * NOTE: We only care about EXTERNAL references here. INTERNAL references are only relevant when dereferencing.
14
18
  *
15
- * @param {$RefParser} parser
16
- * @param {$RefParserOptions} options
17
- *
18
- * @returns {Promise}
19
+ * @returns
19
20
  * The promise resolves once all JSON references in the schema have been resolved,
20
21
  * including nested references that are contained in externally-referenced files.
21
22
  */
22
- function resolveExternal (parser, options) {
23
+ function resolveExternal(parser: $RefParser, options: Options) {
23
24
  if (!options.resolve.external) {
24
25
  // Nothing to resolve, so exit early
25
26
  return Promise.resolve();
@@ -27,10 +28,9 @@ function resolveExternal (parser, options) {
27
28
 
28
29
  try {
29
30
  // console.log('Resolving $ref pointers in %s', parser.$refs._root$Ref.path);
30
- let promises = crawl(parser.schema, parser.$refs._root$Ref.path + "#", parser.$refs, options);
31
+ const promises = crawl(parser.schema, parser.$refs._root$Ref.path + "#", parser.$refs, options);
31
32
  return Promise.all(promises);
32
- }
33
- catch (e) {
33
+ } catch (e) {
34
34
  return Promise.reject(e);
35
35
  }
36
36
  }
@@ -38,39 +38,41 @@ function resolveExternal (parser, options) {
38
38
  /**
39
39
  * Recursively crawls the given value, and resolves any external JSON references.
40
40
  *
41
- * @param {*} obj - The value to crawl. If it's not an object or array, it will be ignored.
42
- * @param {string} path - The full path of `obj`, possibly with a JSON Pointer in the hash
43
- * @param {$Refs} $refs
44
- * @param {$RefParserOptions} options
45
- * @param {Set} seen - Internal.
41
+ * @param obj - The value to crawl. If it's not an object or array, it will be ignored.
42
+ * @param path - The full path of `obj`, possibly with a JSON Pointer in the hash
43
+ * @param {boolean} external - Whether `obj` was found in an external document.
44
+ * @param $refs
45
+ * @param options
46
+ * @param seen - Internal.
46
47
  *
47
- * @returns {Promise[]}
48
+ * @returns
48
49
  * Returns an array of promises. There will be one promise for each JSON reference in `obj`.
49
50
  * If `obj` does not contain any JSON references, then the array will be empty.
50
51
  * If any of the JSON references point to files that contain additional JSON references,
51
52
  * then the corresponding promise will internally reference an array of promises.
52
53
  */
53
- function crawl (obj, path, $refs, options, seen) {
54
- seen = seen || new Set();
55
- let promises = [];
54
+ function crawl(
55
+ obj: string | Buffer | JSONSchema | undefined | null,
56
+ path: string,
57
+ $refs: $Refs,
58
+ options: Options,
59
+ seen?: Set<any>,
60
+ external?: boolean,
61
+ ) {
62
+ seen ||= new Set();
63
+ let promises: any = [];
56
64
 
57
65
  if (obj && typeof obj === "object" && !ArrayBuffer.isView(obj) && !seen.has(obj)) {
58
66
  seen.add(obj); // Track previously seen objects to avoid infinite recursion
59
67
  if ($Ref.isExternal$Ref(obj)) {
60
68
  promises.push(resolve$Ref(obj, path, $refs, options));
61
69
  }
62
- else {
63
- for (let key of Object.keys(obj)) {
64
- let keyPath = Pointer.join(path, key);
65
- let value = obj[key];
66
-
67
- if ($Ref.isExternal$Ref(value)) {
68
- promises.push(resolve$Ref(value, keyPath, $refs, options));
69
- }
70
- else {
71
- promises = promises.concat(crawl(value, keyPath, $refs, options, seen));
72
- }
73
- }
70
+
71
+ const keys = Object.keys(obj) as (keyof typeof obj)[];
72
+ for (const key of keys) {
73
+ const keyPath = Pointer.join(path, key);
74
+ const value = obj[key] as string | JSONSchema | Buffer | undefined;
75
+ promises = promises.concat(crawl(value, keyPath, $refs, options, seen, external));
74
76
  }
75
77
  }
76
78
 
@@ -80,20 +82,22 @@ function crawl (obj, path, $refs, options, seen) {
80
82
  /**
81
83
  * Resolves the given JSON Reference, and then crawls the resulting value.
82
84
  *
83
- * @param {{$ref: string}} $ref - The JSON Reference to resolve
84
- * @param {string} path - The full path of `$ref`, possibly with a JSON Pointer in the hash
85
- * @param {$Refs} $refs
86
- * @param {$RefParserOptions} options
85
+ * @param $ref - The JSON Reference to resolve
86
+ * @param path - The full path of `$ref`, possibly with a JSON Pointer in the hash
87
+ * @param $refs
88
+ * @param options
87
89
  *
88
- * @returns {Promise}
90
+ * @returns
89
91
  * The promise resolves once all JSON references in the object have been resolved,
90
92
  * including nested references that are contained in externally-referenced files.
91
93
  */
92
- async function resolve$Ref ($ref, path, $refs, options) {
94
+ async function resolve$Ref($ref: JSONSchema, path: string, $refs: $Refs, options: Options) {
93
95
  // console.log('Resolving $ref pointer "%s" at %s', $ref.$ref, path);
94
96
 
95
- let resolvedPath = url.resolve(path, $ref.$ref);
96
- let withoutHash = url.stripHash(resolvedPath);
97
+ const resolvedPath = url.resolve(path, $ref.$ref);
98
+ const withoutHash = url.stripHash(resolvedPath);
99
+
100
+ // $ref.$ref = url.relative($refs._root$Ref.path, resolvedPath);
97
101
 
98
102
  // Do we already have this $ref?
99
103
  $ref = $refs._$refs[withoutHash];
@@ -108,12 +112,11 @@ async function resolve$Ref ($ref, path, $refs, options) {
108
112
 
109
113
  // Crawl the parsed value
110
114
  // console.log('Resolving $ref pointers in %s', withoutHash);
111
- let promises = crawl(result, withoutHash + "#", $refs, options);
115
+ const promises = crawl(result, withoutHash + "#", $refs, options, new Set(), true);
112
116
 
113
117
  return Promise.all(promises);
114
- }
115
- catch (err) {
116
- if (!options.continueOnError || !isHandledError(err)) {
118
+ } catch (err) {
119
+ if (!options?.continueOnError || !isHandledError(err)) {
117
120
  throw err;
118
121
  }
119
122