@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
@@ -0,0 +1,256 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __importDefault = (this && this.__importDefault) || function (mod) {
26
+ return (mod && mod.__esModule) ? mod : { "default": mod };
27
+ };
28
+ Object.defineProperty(exports, "__esModule", { value: true });
29
+ const ref_js_1 = __importDefault(require("./ref.js"));
30
+ const url = __importStar(require("./util/url.js"));
31
+ const errors_js_1 = require("./util/errors.js");
32
+ const slashes = /\//g;
33
+ const tildes = /~/g;
34
+ const escapedSlash = /~1/g;
35
+ const escapedTilde = /~0/g;
36
+ /**
37
+ * This class represents a single JSON pointer and its resolved value.
38
+ *
39
+ * @param $ref
40
+ * @param path
41
+ * @param [friendlyPath] - The original user-specified path (used for error messages)
42
+ * @class
43
+ */
44
+ class Pointer {
45
+ constructor($ref, path, friendlyPath) {
46
+ this.$ref = $ref;
47
+ this.path = path;
48
+ this.originalPath = friendlyPath || path;
49
+ this.value = undefined;
50
+ this.circular = false;
51
+ this.indirections = 0;
52
+ }
53
+ /**
54
+ * Resolves the value of a nested property within the given object.
55
+ *
56
+ * @param obj - The object that will be crawled
57
+ * @param options
58
+ * @param pathFromRoot - the path of place that initiated resolving
59
+ *
60
+ * @returns
61
+ * Returns a JSON pointer whose {@link Pointer#value} is the resolved value.
62
+ * If resolving this value required resolving other JSON references, then
63
+ * the {@link Pointer#$ref} and {@link Pointer#path} will reflect the resolution path
64
+ * of the resolved value.
65
+ */
66
+ resolve(obj, options, pathFromRoot) {
67
+ const tokens = Pointer.parse(this.path, this.originalPath);
68
+ // Crawl the object, one token at a time
69
+ this.value = unwrapOrThrow(obj);
70
+ for (let i = 0; i < tokens.length; i++) {
71
+ if (resolveIf$Ref(this, options)) {
72
+ // The $ref path has changed, so append the remaining tokens to the path
73
+ this.path = Pointer.join(this.path, tokens.slice(i));
74
+ }
75
+ if (typeof this.value === "object" && this.value !== null && "$ref" in this.value) {
76
+ return this;
77
+ }
78
+ const token = tokens[i];
79
+ if (this.value[token] === undefined || this.value[token] === null) {
80
+ this.value = null;
81
+ throw new errors_js_1.MissingPointerError(token, decodeURI(this.originalPath));
82
+ }
83
+ else {
84
+ this.value = this.value[token];
85
+ }
86
+ }
87
+ // Resolve the final value
88
+ if (!this.value || (this.value.$ref && url.resolve(this.path, this.value.$ref) !== pathFromRoot)) {
89
+ resolveIf$Ref(this, options);
90
+ }
91
+ return this;
92
+ }
93
+ /**
94
+ * Sets the value of a nested property within the given object.
95
+ *
96
+ * @param obj - The object that will be crawled
97
+ * @param value - the value to assign
98
+ * @param options
99
+ *
100
+ * @returns
101
+ * Returns the modified object, or an entirely new object if the entire object is overwritten.
102
+ */
103
+ set(obj, value, options) {
104
+ const tokens = Pointer.parse(this.path);
105
+ let token;
106
+ if (tokens.length === 0) {
107
+ // There are no tokens, replace the entire object with the new value
108
+ this.value = value;
109
+ return value;
110
+ }
111
+ // Crawl the object, one token at a time
112
+ this.value = unwrapOrThrow(obj);
113
+ for (let i = 0; i < tokens.length - 1; i++) {
114
+ resolveIf$Ref(this, options);
115
+ token = tokens[i];
116
+ if (this.value && this.value[token] !== undefined) {
117
+ // The token exists
118
+ this.value = this.value[token];
119
+ }
120
+ else {
121
+ // The token doesn't exist, so create it
122
+ this.value = setValue(this, token, {});
123
+ }
124
+ }
125
+ // Set the value of the final token
126
+ resolveIf$Ref(this, options);
127
+ token = tokens[tokens.length - 1];
128
+ setValue(this, token, value);
129
+ // Return the updated object
130
+ return obj;
131
+ }
132
+ /**
133
+ * Parses a JSON pointer (or a path containing a JSON pointer in the hash)
134
+ * and returns an array of the pointer's tokens.
135
+ * (e.g. "schema.json#/definitions/person/name" => ["definitions", "person", "name"])
136
+ *
137
+ * The pointer is parsed according to RFC 6901
138
+ * {@link https://tools.ietf.org/html/rfc6901#section-3}
139
+ *
140
+ * @param path
141
+ * @param [originalPath]
142
+ * @returns
143
+ */
144
+ static parse(path, originalPath) {
145
+ // Get the JSON pointer from the path's hash
146
+ let pointer = url.getHash(path).substr(1);
147
+ // If there's no pointer, then there are no tokens,
148
+ // so return an empty array
149
+ if (!pointer) {
150
+ return [];
151
+ }
152
+ // Split into an array
153
+ pointer = pointer.split("/");
154
+ // Decode each part, according to RFC 6901
155
+ for (let i = 0; i < pointer.length; i++) {
156
+ pointer[i] = decodeURIComponent(pointer[i].replace(escapedSlash, "/").replace(escapedTilde, "~"));
157
+ }
158
+ if (pointer[0] !== "") {
159
+ throw new errors_js_1.InvalidPointerError(pointer, originalPath === undefined ? path : originalPath);
160
+ }
161
+ return pointer.slice(1);
162
+ }
163
+ /**
164
+ * Creates a JSON pointer path, by joining one or more tokens to a base path.
165
+ *
166
+ * @param base - The base path (e.g. "schema.json#/definitions/person")
167
+ * @param tokens - The token(s) to append (e.g. ["name", "first"])
168
+ * @returns
169
+ */
170
+ static join(base, tokens) {
171
+ // Ensure that the base path contains a hash
172
+ if (base.indexOf("#") === -1) {
173
+ base += "#";
174
+ }
175
+ // Append each token to the base path
176
+ tokens = Array.isArray(tokens) ? tokens : [tokens];
177
+ for (let i = 0; i < tokens.length; i++) {
178
+ const token = tokens[i];
179
+ // Encode the token, according to RFC 6901
180
+ base += "/" + encodeURIComponent(token.replace(tildes, "~0").replace(slashes, "~1"));
181
+ }
182
+ return base;
183
+ }
184
+ }
185
+ /**
186
+ * If the given pointer's {@link Pointer#value} is a JSON reference,
187
+ * then the reference is resolved and {@link Pointer#value} is replaced with the resolved value.
188
+ * In addition, {@link Pointer#path} and {@link Pointer#$ref} are updated to reflect the
189
+ * resolution path of the new value.
190
+ *
191
+ * @param pointer
192
+ * @param options
193
+ * @returns - Returns `true` if the resolution path changed
194
+ */
195
+ function resolveIf$Ref(pointer, options) {
196
+ // Is the value a JSON reference? (and allowed?)
197
+ if (ref_js_1.default.isAllowed$Ref(pointer.value, options)) {
198
+ const $refPath = url.resolve(pointer.path, pointer.value.$ref);
199
+ if ($refPath === pointer.path) {
200
+ // The value is a reference to itself, so there's nothing to do.
201
+ pointer.circular = true;
202
+ }
203
+ else {
204
+ const resolved = pointer.$ref.$refs._resolve($refPath, pointer.path, options);
205
+ if (resolved === null) {
206
+ return false;
207
+ }
208
+ pointer.indirections += resolved.indirections + 1;
209
+ if (ref_js_1.default.isExtended$Ref(pointer.value)) {
210
+ // This JSON reference "extends" the resolved value, rather than simply pointing to it.
211
+ // So the resolved path does NOT change. Just the value does.
212
+ pointer.value = ref_js_1.default.dereference(pointer.value, resolved.value);
213
+ return false;
214
+ }
215
+ else {
216
+ // Resolve the reference
217
+ pointer.$ref = resolved.$ref;
218
+ pointer.path = resolved.path;
219
+ pointer.value = resolved.value;
220
+ }
221
+ return true;
222
+ }
223
+ }
224
+ }
225
+ exports.default = Pointer;
226
+ /**
227
+ * Sets the specified token value of the {@link Pointer#value}.
228
+ *
229
+ * The token is evaluated according to RFC 6901.
230
+ * {@link https://tools.ietf.org/html/rfc6901#section-4}
231
+ *
232
+ * @param pointer - The JSON Pointer whose value will be modified
233
+ * @param token - A JSON Pointer token that indicates how to modify `obj`
234
+ * @param value - The value to assign
235
+ * @returns - Returns the assigned value
236
+ */
237
+ function setValue(pointer, token, value) {
238
+ if (pointer.value && typeof pointer.value === "object") {
239
+ if (token === "-" && Array.isArray(pointer.value)) {
240
+ pointer.value.push(value);
241
+ }
242
+ else {
243
+ pointer.value[token] = value;
244
+ }
245
+ }
246
+ else {
247
+ throw new errors_js_1.JSONParserError(`Error assigning $ref pointer "${pointer.path}". \nCannot set "${token}" of a non-object.`);
248
+ }
249
+ return value;
250
+ }
251
+ function unwrapOrThrow(value) {
252
+ if ((0, errors_js_1.isHandledError)(value)) {
253
+ throw value;
254
+ }
255
+ return value;
256
+ }
@@ -0,0 +1,180 @@
1
+ import Pointer from "./pointer.js";
2
+ import type { JSONParserError, MissingPointerError, ParserError, ResolverError } from "./util/errors.js";
3
+ import type $Refs from "./refs.js";
4
+ import type $RefParserOptions from "./options.js";
5
+ type $RefError = JSONParserError | ResolverError | ParserError | MissingPointerError;
6
+ /**
7
+ * This class represents a single JSON reference and its resolved value.
8
+ *
9
+ * @class
10
+ */
11
+ declare class $Ref {
12
+ /**
13
+ * The file path or URL of the referenced file.
14
+ * This path is relative to the path of the main JSON schema file.
15
+ *
16
+ * This path does NOT contain document fragments (JSON pointers). It always references an ENTIRE file.
17
+ * Use methods such as {@link $Ref#get}, {@link $Ref#resolve}, and {@link $Ref#exists} to get
18
+ * specific JSON pointers within the file.
19
+ *
20
+ * @type {string}
21
+ */
22
+ path: undefined | string;
23
+ /**
24
+ * The resolved value of the JSON reference.
25
+ * Can be any JSON type, not just objects. Unknown file types are represented as Buffers (byte arrays).
26
+ *
27
+ * @type {?*}
28
+ */
29
+ value: any;
30
+ /**
31
+ * The {@link $Refs} object that contains this {@link $Ref} object.
32
+ *
33
+ * @type {$Refs}
34
+ */
35
+ $refs: $Refs;
36
+ /**
37
+ * Indicates the type of {@link $Ref#path} (e.g. "file", "http", etc.)
38
+ */
39
+ pathType: string | unknown;
40
+ /**
41
+ * List of all errors. Undefined if no errors.
42
+ */
43
+ errors: Array<$RefError>;
44
+ constructor($refs: $Refs);
45
+ /**
46
+ * Pushes an error to errors array.
47
+ *
48
+ * @param err - The error to be pushed
49
+ * @returns
50
+ */
51
+ addError(err: $RefError): void;
52
+ /**
53
+ * Determines whether the given JSON reference exists within this {@link $Ref#value}.
54
+ *
55
+ * @param path - The full path being resolved, optionally with a JSON pointer in the hash
56
+ * @param options
57
+ * @returns
58
+ */
59
+ exists(path: string, options: any): boolean;
60
+ /**
61
+ * Resolves the given JSON reference within this {@link $Ref#value} and returns the resolved value.
62
+ *
63
+ * @param path - The full path being resolved, optionally with a JSON pointer in the hash
64
+ * @param options
65
+ * @returns - Returns the resolved value
66
+ */
67
+ get(path: any, options: any): any;
68
+ /**
69
+ * Resolves the given JSON reference within this {@link $Ref#value}.
70
+ *
71
+ * @param path - The full path being resolved, optionally with a JSON pointer in the hash
72
+ * @param options
73
+ * @param friendlyPath - The original user-specified path (used for error messages)
74
+ * @param pathFromRoot - The path of `obj` from the schema root
75
+ * @returns
76
+ */
77
+ resolve(path: any, options?: $RefParserOptions, friendlyPath?: string, pathFromRoot?: string): Pointer | null;
78
+ /**
79
+ * Sets the value of a nested property within this {@link $Ref#value}.
80
+ * If the property, or any of its parents don't exist, they will be created.
81
+ *
82
+ * @param path - The full path of the property to set, optionally with a JSON pointer in the hash
83
+ * @param value - The value to assign
84
+ */
85
+ set(path: any, value: any): void;
86
+ /**
87
+ * Determines whether the given value is a JSON reference.
88
+ *
89
+ * @param value - The value to inspect
90
+ * @returns
91
+ */
92
+ static is$Ref(value: any): value is {
93
+ $ref: string;
94
+ length?: number;
95
+ };
96
+ /**
97
+ * Determines whether the given value is an external JSON reference.
98
+ *
99
+ * @param value - The value to inspect
100
+ * @returns
101
+ */
102
+ static isExternal$Ref(value: any): boolean;
103
+ /**
104
+ * Determines whether the given value is a JSON reference, and whether it is allowed by the options.
105
+ * For example, if it references an external file, then options.resolve.external must be true.
106
+ *
107
+ * @param value - The value to inspect
108
+ * @param options
109
+ * @returns
110
+ */
111
+ static isAllowed$Ref(value: any, options: any): true | undefined;
112
+ /**
113
+ * Determines whether the given value is a JSON reference that "extends" its resolved value.
114
+ * That is, it has extra properties (in addition to "$ref"), so rather than simply pointing to
115
+ * an existing value, this $ref actually creates a NEW value that is a shallow copy of the resolved
116
+ * value, plus the extra properties.
117
+ *
118
+ * @example: {
119
+ person: {
120
+ properties: {
121
+ firstName: { type: string }
122
+ lastName: { type: string }
123
+ }
124
+ }
125
+ employee: {
126
+ properties: {
127
+ $ref: #/person/properties
128
+ salary: { type: number }
129
+ }
130
+ }
131
+ }
132
+ * In this example, "employee" is an extended $ref, since it extends "person" with an additional
133
+ * property (salary). The result is a NEW value that looks like this:
134
+ *
135
+ * {
136
+ * properties: {
137
+ * firstName: { type: string }
138
+ * lastName: { type: string }
139
+ * salary: { type: number }
140
+ * }
141
+ * }
142
+ *
143
+ * @param value - The value to inspect
144
+ * @returns
145
+ */
146
+ static isExtended$Ref(value: any): boolean;
147
+ /**
148
+ * Returns the resolved value of a JSON Reference.
149
+ * If necessary, the resolved value is merged with the JSON Reference to create a new object
150
+ *
151
+ * @example: {
152
+ person: {
153
+ properties: {
154
+ firstName: { type: string }
155
+ lastName: { type: string }
156
+ }
157
+ }
158
+ employee: {
159
+ properties: {
160
+ $ref: #/person/properties
161
+ salary: { type: number }
162
+ }
163
+ }
164
+ } When "person" and "employee" are merged, you end up with the following object:
165
+ *
166
+ * {
167
+ * properties: {
168
+ * firstName: { type: string }
169
+ * lastName: { type: string }
170
+ * salary: { type: number }
171
+ * }
172
+ * }
173
+ *
174
+ * @param $ref - The JSON reference object (the one with the "$ref" property)
175
+ * @param resolvedValue - The resolved value, which can be any type
176
+ * @returns - Returns the dereferenced value
177
+ */
178
+ static dereference($ref: $Ref, resolvedValue: any): any;
179
+ }
180
+ export default $Ref;
@@ -0,0 +1,238 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const pointer_js_1 = __importDefault(require("./pointer.js"));
7
+ const errors_js_1 = require("./util/errors.js");
8
+ const url_js_1 = require("./util/url.js");
9
+ /**
10
+ * This class represents a single JSON reference and its resolved value.
11
+ *
12
+ * @class
13
+ */
14
+ class $Ref {
15
+ constructor($refs) {
16
+ /**
17
+ * List of all errors. Undefined if no errors.
18
+ */
19
+ this.errors = [];
20
+ this.$refs = $refs;
21
+ }
22
+ /**
23
+ * Pushes an error to errors array.
24
+ *
25
+ * @param err - The error to be pushed
26
+ * @returns
27
+ */
28
+ addError(err) {
29
+ if (this.errors === undefined) {
30
+ this.errors = [];
31
+ }
32
+ const existingErrors = this.errors.map(({ footprint }) => footprint);
33
+ // the path has been almost certainly set at this point,
34
+ // but just in case something went wrong, normalizeError injects path if necessary
35
+ // moreover, certain errors might point at the same spot, so filter them out to reduce noise
36
+ if ("errors" in err && Array.isArray(err.errors)) {
37
+ this.errors.push(...err.errors.map(errors_js_1.normalizeError).filter(({ footprint }) => !existingErrors.includes(footprint)));
38
+ }
39
+ else if (!("footprint" in err) || !existingErrors.includes(err.footprint)) {
40
+ this.errors.push((0, errors_js_1.normalizeError)(err));
41
+ }
42
+ }
43
+ /**
44
+ * Determines whether the given JSON reference exists within this {@link $Ref#value}.
45
+ *
46
+ * @param path - The full path being resolved, optionally with a JSON pointer in the hash
47
+ * @param options
48
+ * @returns
49
+ */
50
+ exists(path, options) {
51
+ try {
52
+ this.resolve(path, options);
53
+ return true;
54
+ }
55
+ catch (e) {
56
+ return false;
57
+ }
58
+ }
59
+ /**
60
+ * Resolves the given JSON reference within this {@link $Ref#value} and returns the resolved value.
61
+ *
62
+ * @param path - The full path being resolved, optionally with a JSON pointer in the hash
63
+ * @param options
64
+ * @returns - Returns the resolved value
65
+ */
66
+ get(path, options) {
67
+ return this.resolve(path, options)?.value;
68
+ }
69
+ /**
70
+ * Resolves the given JSON reference within this {@link $Ref#value}.
71
+ *
72
+ * @param path - The full path being resolved, optionally with a JSON pointer in the hash
73
+ * @param options
74
+ * @param friendlyPath - The original user-specified path (used for error messages)
75
+ * @param pathFromRoot - The path of `obj` from the schema root
76
+ * @returns
77
+ */
78
+ resolve(path, options, friendlyPath, pathFromRoot) {
79
+ const pointer = new pointer_js_1.default(this, path, friendlyPath);
80
+ try {
81
+ return pointer.resolve(this.value, options, pathFromRoot);
82
+ }
83
+ catch (err) {
84
+ if (!options || !options.continueOnError || !(0, errors_js_1.isHandledError)(err)) {
85
+ throw err;
86
+ }
87
+ if (err.path === null) {
88
+ err.path = (0, url_js_1.safePointerToPath)((0, url_js_1.getHash)(pathFromRoot));
89
+ }
90
+ if (err instanceof errors_js_1.InvalidPointerError) {
91
+ err.source = decodeURI((0, url_js_1.stripHash)(pathFromRoot));
92
+ }
93
+ this.addError(err);
94
+ return null;
95
+ }
96
+ }
97
+ /**
98
+ * Sets the value of a nested property within this {@link $Ref#value}.
99
+ * If the property, or any of its parents don't exist, they will be created.
100
+ *
101
+ * @param path - The full path of the property to set, optionally with a JSON pointer in the hash
102
+ * @param value - The value to assign
103
+ */
104
+ set(path, value) {
105
+ // @ts-expect-error TS(2554): Expected 3 arguments, but got 2.
106
+ const pointer = new pointer_js_1.default(this, path);
107
+ this.value = pointer.set(this.value, value);
108
+ }
109
+ /**
110
+ * Determines whether the given value is a JSON reference.
111
+ *
112
+ * @param value - The value to inspect
113
+ * @returns
114
+ */
115
+ static is$Ref(value) {
116
+ return value && typeof value === "object" && typeof value.$ref === "string" && value.$ref.length > 0;
117
+ }
118
+ /**
119
+ * Determines whether the given value is an external JSON reference.
120
+ *
121
+ * @param value - The value to inspect
122
+ * @returns
123
+ */
124
+ static isExternal$Ref(value) {
125
+ return $Ref.is$Ref(value) && value.$ref[0] !== "#";
126
+ }
127
+ /**
128
+ * Determines whether the given value is a JSON reference, and whether it is allowed by the options.
129
+ * For example, if it references an external file, then options.resolve.external must be true.
130
+ *
131
+ * @param value - The value to inspect
132
+ * @param options
133
+ * @returns
134
+ */
135
+ static isAllowed$Ref(value, options) {
136
+ if (this.is$Ref(value)) {
137
+ if (value.$ref.substring(0, 2) === "#/" || value.$ref === "#") {
138
+ // It's a JSON Pointer reference, which is always allowed
139
+ return true;
140
+ }
141
+ else if (value.$ref[0] !== "#" && (!options || options.resolve.external)) {
142
+ // It's an external reference, which is allowed by the options
143
+ return true;
144
+ }
145
+ }
146
+ }
147
+ /**
148
+ * Determines whether the given value is a JSON reference that "extends" its resolved value.
149
+ * That is, it has extra properties (in addition to "$ref"), so rather than simply pointing to
150
+ * an existing value, this $ref actually creates a NEW value that is a shallow copy of the resolved
151
+ * value, plus the extra properties.
152
+ *
153
+ * @example: {
154
+ person: {
155
+ properties: {
156
+ firstName: { type: string }
157
+ lastName: { type: string }
158
+ }
159
+ }
160
+ employee: {
161
+ properties: {
162
+ $ref: #/person/properties
163
+ salary: { type: number }
164
+ }
165
+ }
166
+ }
167
+ * In this example, "employee" is an extended $ref, since it extends "person" with an additional
168
+ * property (salary). The result is a NEW value that looks like this:
169
+ *
170
+ * {
171
+ * properties: {
172
+ * firstName: { type: string }
173
+ * lastName: { type: string }
174
+ * salary: { type: number }
175
+ * }
176
+ * }
177
+ *
178
+ * @param value - The value to inspect
179
+ * @returns
180
+ */
181
+ static isExtended$Ref(value) {
182
+ return $Ref.is$Ref(value) && Object.keys(value).length > 1;
183
+ }
184
+ /**
185
+ * Returns the resolved value of a JSON Reference.
186
+ * If necessary, the resolved value is merged with the JSON Reference to create a new object
187
+ *
188
+ * @example: {
189
+ person: {
190
+ properties: {
191
+ firstName: { type: string }
192
+ lastName: { type: string }
193
+ }
194
+ }
195
+ employee: {
196
+ properties: {
197
+ $ref: #/person/properties
198
+ salary: { type: number }
199
+ }
200
+ }
201
+ } When "person" and "employee" are merged, you end up with the following object:
202
+ *
203
+ * {
204
+ * properties: {
205
+ * firstName: { type: string }
206
+ * lastName: { type: string }
207
+ * salary: { type: number }
208
+ * }
209
+ * }
210
+ *
211
+ * @param $ref - The JSON reference object (the one with the "$ref" property)
212
+ * @param resolvedValue - The resolved value, which can be any type
213
+ * @returns - Returns the dereferenced value
214
+ */
215
+ static dereference($ref, resolvedValue) {
216
+ if (resolvedValue && typeof resolvedValue === "object" && $Ref.isExtended$Ref($ref)) {
217
+ const merged = {};
218
+ for (const key of Object.keys($ref)) {
219
+ if (key !== "$ref") {
220
+ // @ts-expect-error TS(7053): Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
221
+ merged[key] = $ref[key];
222
+ }
223
+ }
224
+ for (const key of Object.keys(resolvedValue)) {
225
+ if (!(key in merged)) {
226
+ // @ts-expect-error TS(7053): Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
227
+ merged[key] = resolvedValue[key];
228
+ }
229
+ }
230
+ return merged;
231
+ }
232
+ else {
233
+ // Completely replace the original reference with the resolved value
234
+ return resolvedValue;
235
+ }
236
+ }
237
+ }
238
+ exports.default = $Ref;