schema-shield 0.0.6 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +219 -65
- package/dist/formats.d.ts.map +1 -1
- package/dist/index.d.ts +25 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1837 -484
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/dist/index.mjs +1837 -484
- package/dist/keywords/array-keywords.d.ts.map +1 -1
- package/dist/keywords/object-keywords.d.ts.map +1 -1
- package/dist/keywords/other-keywords.d.ts.map +1 -1
- package/dist/keywords/string-keywords.d.ts.map +1 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/deep-freeze.d.ts +5 -0
- package/dist/utils/deep-freeze.d.ts.map +1 -0
- package/dist/utils/has-changed.d.ts +2 -0
- package/dist/utils/has-changed.d.ts.map +1 -0
- package/dist/utils/index.d.ts +5 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/{utils.d.ts → utils/main-utils.d.ts} +7 -9
- package/dist/utils/main-utils.d.ts.map +1 -0
- package/dist/utils/pattern-matcher.d.ts +3 -0
- package/dist/utils/pattern-matcher.d.ts.map +1 -0
- package/lib/formats.ts +468 -155
- package/lib/index.ts +702 -107
- package/lib/keywords/array-keywords.ts +260 -52
- package/lib/keywords/number-keywords.ts +1 -1
- package/lib/keywords/object-keywords.ts +295 -88
- package/lib/keywords/other-keywords.ts +263 -70
- package/lib/keywords/string-keywords.ts +123 -7
- package/lib/types.ts +5 -18
- package/lib/utils/deep-freeze.ts +208 -0
- package/lib/utils/has-changed.ts +51 -0
- package/lib/utils/index.ts +4 -0
- package/lib/{utils.ts → utils/main-utils.ts} +63 -77
- package/lib/utils/pattern-matcher.ts +66 -0
- package/package.json +2 -2
- package/tsconfig.json +4 -4
- package/dist/utils.d.ts.map +0 -1
package/dist/index.js
CHANGED
|
@@ -21,11 +21,11 @@ var lib_exports = {};
|
|
|
21
21
|
__export(lib_exports, {
|
|
22
22
|
SchemaShield: () => SchemaShield,
|
|
23
23
|
ValidationError: () => ValidationError,
|
|
24
|
-
deepClone: () =>
|
|
24
|
+
deepClone: () => deepCloneUnfreeze
|
|
25
25
|
});
|
|
26
26
|
module.exports = __toCommonJS(lib_exports);
|
|
27
27
|
|
|
28
|
-
// lib/utils.ts
|
|
28
|
+
// lib/utils/main-utils.ts
|
|
29
29
|
var ValidationError = class extends Error {
|
|
30
30
|
message;
|
|
31
31
|
item;
|
|
@@ -80,14 +80,18 @@ var ValidationError = class extends Error {
|
|
|
80
80
|
};
|
|
81
81
|
}
|
|
82
82
|
};
|
|
83
|
-
|
|
83
|
+
var FAIL_FAST_DEFINE_ERROR = () => true;
|
|
84
|
+
function getDefinedErrorFunctionForKey(key, schema, failFast) {
|
|
85
|
+
if (failFast) {
|
|
86
|
+
return FAIL_FAST_DEFINE_ERROR;
|
|
87
|
+
}
|
|
84
88
|
const KeywordError = new ValidationError(`Invalid ${key}`);
|
|
85
89
|
KeywordError.keyword = key;
|
|
86
90
|
KeywordError.schema = schema;
|
|
87
91
|
const defineError = (message, options = {}) => {
|
|
88
92
|
KeywordError.message = message;
|
|
89
93
|
KeywordError.item = options.item;
|
|
90
|
-
KeywordError.cause = options.cause;
|
|
94
|
+
KeywordError.cause = options.cause && options.cause !== true ? options.cause : void 0;
|
|
91
95
|
KeywordError.data = options.data;
|
|
92
96
|
return KeywordError;
|
|
93
97
|
};
|
|
@@ -96,216 +100,394 @@ function getDefinedErrorFunctionForKey(key, schema) {
|
|
|
96
100
|
defineError
|
|
97
101
|
);
|
|
98
102
|
}
|
|
99
|
-
function
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
+
function isCompiledSchema(subSchema) {
|
|
104
|
+
return !!subSchema && typeof subSchema === "object" && !Array.isArray(subSchema) && "$validate" in subSchema;
|
|
105
|
+
}
|
|
106
|
+
function getNamedFunction(name, fn) {
|
|
107
|
+
return Object.defineProperty(fn, "name", { value: name });
|
|
108
|
+
}
|
|
109
|
+
function resolvePath(root, path) {
|
|
110
|
+
if (!path || path === "#") {
|
|
111
|
+
return root;
|
|
112
|
+
}
|
|
113
|
+
if (path.startsWith("#/")) {
|
|
114
|
+
const parts = path.split("/").slice(1);
|
|
115
|
+
let current = root;
|
|
116
|
+
for (const part of parts) {
|
|
117
|
+
const decodedUriPart = decodeURIComponent(part);
|
|
118
|
+
const key = decodedUriPart.replace(/~1/g, "/").replace(/~0/g, "~");
|
|
119
|
+
if (current && typeof current === "object" && key in current) {
|
|
120
|
+
current = current[key];
|
|
121
|
+
} else {
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
103
124
|
}
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
125
|
+
return current;
|
|
126
|
+
}
|
|
127
|
+
if (!path.includes("#")) {
|
|
128
|
+
if (root.definitions && root.definitions[path]) {
|
|
129
|
+
return root.definitions[path];
|
|
130
|
+
}
|
|
131
|
+
if (root.defs && root.defs[path]) {
|
|
132
|
+
return root.defs[path];
|
|
133
|
+
}
|
|
134
|
+
if (root.$id && typeof root.$id === "string") {
|
|
135
|
+
if (root.$id === path || root.$id.endsWith("/" + path)) {
|
|
136
|
+
return root;
|
|
107
137
|
}
|
|
108
138
|
}
|
|
109
|
-
return true;
|
|
110
139
|
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
function areCloseEnough(a, b, epsilon = 1e-15) {
|
|
143
|
+
return Math.abs(a - b) <= epsilon * Math.max(Math.abs(a), Math.abs(b));
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// lib/formats.ts
|
|
147
|
+
var UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
148
|
+
var DURATION_REGEX = /^P(?!$)((\d+Y)?(\d+M)?(\d+W)?(\d+D)?)(T(?=\d)(\d+H)?(\d+M)?(\d+S)?)?$/;
|
|
149
|
+
var URI_REGEX = /^[a-zA-Z][a-zA-Z0-9+\-.]*:[^\s]*$/;
|
|
150
|
+
var EMAIL_REGEX = /^(?!\.)(?!.*\.$)[a-z0-9!#$%&'*+/=?^_`{|}~-]{1,20}(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]{1,21}){0,2}@[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]{0,60}[a-z0-9])?){0,3}$/i;
|
|
151
|
+
var HOSTNAME_REGEX = /^[a-z0-9][a-z0-9-]{0,62}(?:\.[a-z0-9][a-z0-9-]{0,62})*[a-z0-9]$/i;
|
|
152
|
+
var DATE_REGEX = /^(\d{4})-(\d{2})-(\d{2})$/;
|
|
153
|
+
var TIME_REGEX = /^([01]\d|2[0-3]):([0-5]\d):([0-5]\d)(\.\d+)?(Z|([+-])([01]\d|2[0-3]):([0-5]\d))$/;
|
|
154
|
+
var URI_REFERENCE_REGEX = /^(([^:/?#]+):)?(\/\/([^/?#]*))?([^?#]*)(\?([^#]*))?(#((?![^#]*\\)[^#]*))?/i;
|
|
155
|
+
var IRI_REGEX = /^[a-zA-Z][a-zA-Z0-9+\-.]*:[^\s]*$/;
|
|
156
|
+
var IRI_REFERENCE_REGEX = /^(([^:/?#]+):)?(\/\/([^/?#]*))?([^?#]*)(\?([^#]*))?(#((?![^#]*\\)[^#]*))?/i;
|
|
157
|
+
var IDN_EMAIL_REGEX = /^[^@\s]+@[^@\s]+\.[^@\s]+$/;
|
|
158
|
+
var IDN_HOSTNAME_REGEX = /^[^\s!@#$%^&*()_+\=\[\]{};':"\\|,<>\/?]+$/;
|
|
159
|
+
var DAYS_IN_MONTH = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
|
|
160
|
+
function isDigitCharCode(code) {
|
|
161
|
+
return code >= 48 && code <= 57;
|
|
162
|
+
}
|
|
163
|
+
function parseTwoDigits(data, index) {
|
|
164
|
+
const first = data.charCodeAt(index) - 48;
|
|
165
|
+
const second = data.charCodeAt(index + 1) - 48;
|
|
166
|
+
if (first < 0 || first > 9 || second < 0 || second > 9) {
|
|
167
|
+
return -1;
|
|
168
|
+
}
|
|
169
|
+
return first * 10 + second;
|
|
170
|
+
}
|
|
171
|
+
function parseFourDigits(data, index) {
|
|
172
|
+
const a = data.charCodeAt(index) - 48;
|
|
173
|
+
const b = data.charCodeAt(index + 1) - 48;
|
|
174
|
+
const c = data.charCodeAt(index + 2) - 48;
|
|
175
|
+
const d = data.charCodeAt(index + 3) - 48;
|
|
176
|
+
if (a < 0 || a > 9 || b < 0 || b > 9 || c < 0 || c > 9 || d < 0 || d > 9) {
|
|
177
|
+
return -1;
|
|
178
|
+
}
|
|
179
|
+
return a * 1e3 + b * 100 + c * 10 + d;
|
|
180
|
+
}
|
|
181
|
+
function isValidIpv4Range(data, start, end) {
|
|
182
|
+
let segmentCount = 0;
|
|
183
|
+
let segmentStart = start;
|
|
184
|
+
for (let i = start; i <= end; i++) {
|
|
185
|
+
if (i !== end && data.charCodeAt(i) !== 46) {
|
|
186
|
+
continue;
|
|
187
|
+
}
|
|
188
|
+
const segmentLength = i - segmentStart;
|
|
189
|
+
if (segmentLength < 1 || segmentLength > 3) {
|
|
190
|
+
return false;
|
|
114
191
|
}
|
|
115
|
-
|
|
116
|
-
if (keys.length !== Object.keys(other).length) {
|
|
192
|
+
if (segmentLength > 1 && data.charCodeAt(segmentStart) === 48) {
|
|
117
193
|
return false;
|
|
118
194
|
}
|
|
119
|
-
|
|
120
|
-
|
|
195
|
+
let value = 0;
|
|
196
|
+
for (let j = segmentStart; j < i; j++) {
|
|
197
|
+
const digit = data.charCodeAt(j) - 48;
|
|
198
|
+
if (digit < 0 || digit > 9) {
|
|
121
199
|
return false;
|
|
122
200
|
}
|
|
201
|
+
value = value * 10 + digit;
|
|
123
202
|
}
|
|
124
|
-
|
|
203
|
+
if (value > 255) {
|
|
204
|
+
return false;
|
|
205
|
+
}
|
|
206
|
+
segmentCount++;
|
|
207
|
+
segmentStart = i + 1;
|
|
125
208
|
}
|
|
126
|
-
return
|
|
209
|
+
return segmentCount === 4;
|
|
127
210
|
}
|
|
128
|
-
function
|
|
129
|
-
return
|
|
211
|
+
function isValidIpv4(data) {
|
|
212
|
+
return isValidIpv4Range(data, 0, data.length);
|
|
130
213
|
}
|
|
131
|
-
function
|
|
132
|
-
return
|
|
214
|
+
function isHexCharCode(code) {
|
|
215
|
+
return code >= 48 && code <= 57 || code >= 65 && code <= 70 || code >= 97 && code <= 102;
|
|
133
216
|
}
|
|
134
|
-
function
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
217
|
+
function isValidIpv6(data) {
|
|
218
|
+
const length = data.length;
|
|
219
|
+
if (length === 0) {
|
|
220
|
+
return false;
|
|
221
|
+
}
|
|
222
|
+
let hasColon = false;
|
|
223
|
+
let hasDoubleColon = false;
|
|
224
|
+
let hextetCount = 0;
|
|
225
|
+
let i = 0;
|
|
226
|
+
while (i < length) {
|
|
227
|
+
if (data.charCodeAt(i) === 58) {
|
|
228
|
+
hasColon = true;
|
|
229
|
+
if (i + 1 < length && data.charCodeAt(i + 1) === 58) {
|
|
230
|
+
if (hasDoubleColon) {
|
|
231
|
+
return false;
|
|
232
|
+
}
|
|
233
|
+
hasDoubleColon = true;
|
|
234
|
+
i += 2;
|
|
235
|
+
if (i === length) {
|
|
236
|
+
break;
|
|
237
|
+
}
|
|
238
|
+
continue;
|
|
239
|
+
}
|
|
240
|
+
return false;
|
|
241
|
+
}
|
|
242
|
+
const segmentStart = i;
|
|
243
|
+
let segmentLength = 0;
|
|
244
|
+
while (i < length && isHexCharCode(data.charCodeAt(i))) {
|
|
245
|
+
segmentLength++;
|
|
246
|
+
if (segmentLength > 4) {
|
|
247
|
+
return false;
|
|
248
|
+
}
|
|
249
|
+
i++;
|
|
250
|
+
}
|
|
251
|
+
if (segmentLength === 0) {
|
|
252
|
+
return false;
|
|
253
|
+
}
|
|
254
|
+
if (i < length && data.charCodeAt(i) === 46) {
|
|
255
|
+
if (!hasColon) {
|
|
256
|
+
return false;
|
|
257
|
+
}
|
|
258
|
+
if (!isValidIpv4Range(data, segmentStart, length)) {
|
|
259
|
+
return false;
|
|
260
|
+
}
|
|
261
|
+
if (hasDoubleColon) {
|
|
262
|
+
return hextetCount < 6;
|
|
263
|
+
}
|
|
264
|
+
return hextetCount === 6;
|
|
265
|
+
}
|
|
266
|
+
hextetCount++;
|
|
267
|
+
if (hextetCount > 8) {
|
|
268
|
+
return false;
|
|
269
|
+
}
|
|
270
|
+
if (i === length) {
|
|
271
|
+
break;
|
|
272
|
+
}
|
|
273
|
+
if (data.charCodeAt(i) !== 58) {
|
|
274
|
+
return false;
|
|
275
|
+
}
|
|
276
|
+
hasColon = true;
|
|
277
|
+
i++;
|
|
278
|
+
if (i === length) {
|
|
279
|
+
return false;
|
|
280
|
+
}
|
|
281
|
+
if (data.charCodeAt(i) === 58) {
|
|
282
|
+
if (hasDoubleColon) {
|
|
283
|
+
return false;
|
|
284
|
+
}
|
|
285
|
+
hasDoubleColon = true;
|
|
286
|
+
i++;
|
|
287
|
+
if (i === length) {
|
|
288
|
+
break;
|
|
289
|
+
}
|
|
139
290
|
}
|
|
140
|
-
return result;
|
|
141
291
|
}
|
|
142
|
-
if (
|
|
143
|
-
return
|
|
292
|
+
if (!hasColon) {
|
|
293
|
+
return false;
|
|
144
294
|
}
|
|
145
|
-
if (
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
295
|
+
if (hasDoubleColon) {
|
|
296
|
+
return hextetCount < 8;
|
|
297
|
+
}
|
|
298
|
+
return hextetCount === 8;
|
|
299
|
+
}
|
|
300
|
+
function isValidJsonPointer(data) {
|
|
301
|
+
if (data === "") {
|
|
302
|
+
return true;
|
|
303
|
+
}
|
|
304
|
+
if (data.charCodeAt(0) !== 47) {
|
|
305
|
+
return false;
|
|
306
|
+
}
|
|
307
|
+
for (let i = 1; i < data.length; i++) {
|
|
308
|
+
if (data.charCodeAt(i) !== 126) {
|
|
309
|
+
continue;
|
|
310
|
+
}
|
|
311
|
+
const next = data.charCodeAt(i + 1);
|
|
312
|
+
if (next !== 48 && next !== 49) {
|
|
313
|
+
return false;
|
|
151
314
|
}
|
|
152
|
-
|
|
315
|
+
i++;
|
|
153
316
|
}
|
|
154
|
-
return
|
|
317
|
+
return true;
|
|
155
318
|
}
|
|
156
|
-
function
|
|
157
|
-
|
|
319
|
+
function isValidRelativeJsonPointer(data) {
|
|
320
|
+
if (data.length === 0) {
|
|
321
|
+
return true;
|
|
322
|
+
}
|
|
323
|
+
let i = 0;
|
|
324
|
+
while (i < data.length) {
|
|
325
|
+
const code = data.charCodeAt(i);
|
|
326
|
+
if (code < 48 || code > 57) {
|
|
327
|
+
break;
|
|
328
|
+
}
|
|
329
|
+
i++;
|
|
330
|
+
}
|
|
331
|
+
if (i === 0) {
|
|
332
|
+
return false;
|
|
333
|
+
}
|
|
334
|
+
if (i === data.length) {
|
|
335
|
+
return true;
|
|
336
|
+
}
|
|
337
|
+
if (data.charCodeAt(i) === 35) {
|
|
338
|
+
return i + 1 === data.length;
|
|
339
|
+
}
|
|
340
|
+
if (data.charCodeAt(i) !== 47) {
|
|
341
|
+
return false;
|
|
342
|
+
}
|
|
343
|
+
for (i = i + 1; i < data.length; i++) {
|
|
344
|
+
if (data.charCodeAt(i) !== 126) {
|
|
345
|
+
continue;
|
|
346
|
+
}
|
|
347
|
+
const next = data.charCodeAt(i + 1);
|
|
348
|
+
if (next !== 48 && next !== 49) {
|
|
349
|
+
return false;
|
|
350
|
+
}
|
|
351
|
+
i++;
|
|
352
|
+
}
|
|
353
|
+
return true;
|
|
158
354
|
}
|
|
159
|
-
function
|
|
160
|
-
|
|
355
|
+
function isValidUriTemplate(data) {
|
|
356
|
+
for (let i = 0; i < data.length; i++) {
|
|
357
|
+
const code = data.charCodeAt(i);
|
|
358
|
+
if (code === 125) {
|
|
359
|
+
return false;
|
|
360
|
+
}
|
|
361
|
+
if (code !== 123) {
|
|
362
|
+
continue;
|
|
363
|
+
}
|
|
364
|
+
const closeIndex = data.indexOf("}", i + 1);
|
|
365
|
+
if (closeIndex === -1 || closeIndex === i + 1) {
|
|
366
|
+
return false;
|
|
367
|
+
}
|
|
368
|
+
i = closeIndex;
|
|
369
|
+
}
|
|
370
|
+
return true;
|
|
161
371
|
}
|
|
162
|
-
|
|
163
|
-
// lib/formats.ts
|
|
164
372
|
var Formats = {
|
|
165
373
|
["date-time"](data) {
|
|
166
|
-
const
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
374
|
+
const length = data.length;
|
|
375
|
+
if (length < 19) {
|
|
376
|
+
return false;
|
|
377
|
+
}
|
|
378
|
+
if (data.charCodeAt(4) !== 45 || data.charCodeAt(7) !== 45 || data.charCodeAt(13) !== 58 || data.charCodeAt(16) !== 58) {
|
|
379
|
+
return false;
|
|
380
|
+
}
|
|
381
|
+
const tCode = data.charCodeAt(10);
|
|
382
|
+
if (tCode !== 84 && tCode !== 116) {
|
|
170
383
|
return false;
|
|
171
384
|
}
|
|
172
|
-
|
|
173
|
-
|
|
385
|
+
const year = parseFourDigits(data, 0);
|
|
386
|
+
const month = parseTwoDigits(data, 5);
|
|
387
|
+
const day = parseTwoDigits(data, 8);
|
|
388
|
+
const hour = parseTwoDigits(data, 11);
|
|
389
|
+
const minute = parseTwoDigits(data, 14);
|
|
390
|
+
const second = parseTwoDigits(data, 17);
|
|
391
|
+
if (year < 0 || month < 0 || day < 0 || hour < 0 || minute < 0 || second < 0) {
|
|
174
392
|
return false;
|
|
175
393
|
}
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
if (
|
|
194
|
-
const
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
}
|
|
210
|
-
if (hour > 23) {
|
|
211
|
-
day += 1;
|
|
212
|
-
hour -= 24;
|
|
213
|
-
} else if (hour < 0) {
|
|
214
|
-
day -= 1;
|
|
215
|
-
hour += 24;
|
|
216
|
-
}
|
|
217
|
-
if (day > 31) {
|
|
218
|
-
month += 1;
|
|
219
|
-
day -= 31;
|
|
220
|
-
} else if (day < 1) {
|
|
221
|
-
month -= 1;
|
|
222
|
-
day += 31;
|
|
223
|
-
}
|
|
224
|
-
if (month > 12) {
|
|
225
|
-
year += 1;
|
|
226
|
-
month -= 12;
|
|
227
|
-
} else if (month < 1) {
|
|
228
|
-
year -= 1;
|
|
229
|
-
month += 12;
|
|
230
|
-
}
|
|
231
|
-
if (year < 0) {
|
|
394
|
+
if (hour > 23 || minute > 59 || second > 60) {
|
|
395
|
+
return false;
|
|
396
|
+
}
|
|
397
|
+
let cursor = 19;
|
|
398
|
+
let offsetSign = null;
|
|
399
|
+
let offsetHour = 0;
|
|
400
|
+
let offsetMinute = 0;
|
|
401
|
+
if (cursor < length && data.charCodeAt(cursor) === 46) {
|
|
402
|
+
cursor++;
|
|
403
|
+
const fracStart = cursor;
|
|
404
|
+
while (cursor < length && isDigitCharCode(data.charCodeAt(cursor))) {
|
|
405
|
+
cursor++;
|
|
406
|
+
}
|
|
407
|
+
if (cursor === fracStart) {
|
|
408
|
+
return false;
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
if (cursor < length) {
|
|
412
|
+
const tzCode = data.charCodeAt(cursor);
|
|
413
|
+
if (tzCode === 90 || tzCode === 122) {
|
|
414
|
+
cursor++;
|
|
415
|
+
} else if (tzCode === 43 || tzCode === 45) {
|
|
416
|
+
offsetSign = tzCode === 43 ? "+" : "-";
|
|
417
|
+
if (cursor + 6 > length || data.charCodeAt(cursor + 3) !== 58) {
|
|
418
|
+
return false;
|
|
419
|
+
}
|
|
420
|
+
offsetHour = parseTwoDigits(data, cursor + 1);
|
|
421
|
+
offsetMinute = parseTwoDigits(data, cursor + 4);
|
|
422
|
+
if (offsetHour < 0 || offsetMinute < 0 || offsetHour > 23 || offsetMinute > 59) {
|
|
423
|
+
return false;
|
|
424
|
+
}
|
|
425
|
+
cursor += 6;
|
|
426
|
+
} else {
|
|
232
427
|
return false;
|
|
233
428
|
}
|
|
234
429
|
}
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
430
|
+
if (cursor !== length) {
|
|
431
|
+
return false;
|
|
432
|
+
}
|
|
433
|
+
if (month < 1 || month > 12) {
|
|
238
434
|
return false;
|
|
239
435
|
}
|
|
240
|
-
if (
|
|
436
|
+
if (day < 1) {
|
|
241
437
|
return false;
|
|
242
438
|
}
|
|
439
|
+
const maxDays = month === 2 ? year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0) ? 29 : 28 : DAYS_IN_MONTH[month - 1];
|
|
440
|
+
if (!maxDays || day > maxDays) {
|
|
441
|
+
return false;
|
|
442
|
+
}
|
|
443
|
+
if (second === 60) {
|
|
444
|
+
let utcTotalMinutes = hour * 60 + minute;
|
|
445
|
+
if (offsetSign) {
|
|
446
|
+
const offsetTotalMinutes = offsetHour * 60 + offsetMinute;
|
|
447
|
+
utcTotalMinutes += offsetSign === "+" ? -offsetTotalMinutes : offsetTotalMinutes;
|
|
448
|
+
utcTotalMinutes %= 24 * 60;
|
|
449
|
+
if (utcTotalMinutes < 0) {
|
|
450
|
+
utcTotalMinutes += 24 * 60;
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
if (utcTotalMinutes !== 23 * 60 + 59) {
|
|
454
|
+
return false;
|
|
455
|
+
}
|
|
456
|
+
}
|
|
243
457
|
return true;
|
|
244
458
|
},
|
|
245
459
|
uri(data) {
|
|
246
|
-
return
|
|
460
|
+
return URI_REGEX.test(data);
|
|
247
461
|
},
|
|
248
462
|
email(data) {
|
|
249
|
-
return
|
|
250
|
-
data
|
|
251
|
-
);
|
|
463
|
+
return EMAIL_REGEX.test(data);
|
|
252
464
|
},
|
|
253
465
|
ipv4(data) {
|
|
254
|
-
return
|
|
255
|
-
data
|
|
256
|
-
);
|
|
466
|
+
return isValidIpv4(data);
|
|
257
467
|
},
|
|
258
|
-
// ipv6: isMyIpValid({ version: 6 }),
|
|
259
468
|
ipv6(data) {
|
|
260
|
-
|
|
261
|
-
return true;
|
|
262
|
-
}
|
|
263
|
-
if (data.indexOf(":") === -1 || /(?:\s+|:::+|^\w{5,}|\w{5}$|^:{1}\w|\w:{1}$)/.test(data)) {
|
|
264
|
-
return false;
|
|
265
|
-
}
|
|
266
|
-
const hasIpv4 = data.indexOf(".") !== -1;
|
|
267
|
-
let addressParts = data;
|
|
268
|
-
if (hasIpv4) {
|
|
269
|
-
addressParts = data.split(":");
|
|
270
|
-
const ipv4Part = addressParts.pop();
|
|
271
|
-
if (!/^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])$/.test(
|
|
272
|
-
ipv4Part
|
|
273
|
-
)) {
|
|
274
|
-
return false;
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
const isShortened = data.indexOf("::") !== -1;
|
|
278
|
-
const ipv6Part = hasIpv4 ? addressParts.join(":") : data;
|
|
279
|
-
if (isShortened) {
|
|
280
|
-
if (ipv6Part.split("::").length - 1 > 1) {
|
|
281
|
-
return false;
|
|
282
|
-
}
|
|
283
|
-
if (!/^[0-9a-fA-F:.]*$/.test(ipv6Part)) {
|
|
284
|
-
return false;
|
|
285
|
-
}
|
|
286
|
-
return /^(?:(?:(?:[0-9a-fA-F]{1,4}(?::|$)){1,6}))|(?:::(?:[0-9a-fA-F]{1,4})){0,5}$/.test(
|
|
287
|
-
ipv6Part
|
|
288
|
-
);
|
|
289
|
-
}
|
|
290
|
-
const isIpv6Valid = /^(?:(?:[0-9a-fA-F]{1,4}:){7}(?:[0-9a-fA-F]{1,4}|:))$/.test(ipv6Part);
|
|
291
|
-
const hasInvalidChar = /(?:[0-9a-fA-F]{5,}|\D[0-9a-fA-F]{3}:)/.test(
|
|
292
|
-
ipv6Part
|
|
293
|
-
);
|
|
294
|
-
if (hasIpv4) {
|
|
295
|
-
return isIpv6Valid || !hasInvalidChar;
|
|
296
|
-
}
|
|
297
|
-
return isIpv6Valid && !hasInvalidChar;
|
|
469
|
+
return isValidIpv6(data);
|
|
298
470
|
},
|
|
299
471
|
hostname(data) {
|
|
300
|
-
return
|
|
301
|
-
data
|
|
302
|
-
);
|
|
472
|
+
return HOSTNAME_REGEX.test(data);
|
|
303
473
|
},
|
|
304
474
|
date(data) {
|
|
305
|
-
|
|
475
|
+
const match = DATE_REGEX.exec(data);
|
|
476
|
+
if (!match) {
|
|
306
477
|
return false;
|
|
307
478
|
}
|
|
308
|
-
|
|
479
|
+
const [, yearStr, monthStr, dayStr] = match;
|
|
480
|
+
const year = Number(yearStr);
|
|
481
|
+
const month = Number(monthStr);
|
|
482
|
+
const day = Number(dayStr);
|
|
483
|
+
if (month < 1 || month > 12) {
|
|
484
|
+
return false;
|
|
485
|
+
}
|
|
486
|
+
if (day < 1) {
|
|
487
|
+
return false;
|
|
488
|
+
}
|
|
489
|
+
const maxDays = month === 2 ? year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0) ? 29 : 28 : DAYS_IN_MONTH[month - 1];
|
|
490
|
+
return !!maxDays && day <= maxDays;
|
|
309
491
|
},
|
|
310
492
|
regex(data) {
|
|
311
493
|
try {
|
|
@@ -316,54 +498,55 @@ var Formats = {
|
|
|
316
498
|
}
|
|
317
499
|
},
|
|
318
500
|
"json-pointer"(data) {
|
|
319
|
-
|
|
320
|
-
return true;
|
|
321
|
-
}
|
|
322
|
-
return /^\/(?:[^~]|~0|~1)*$/.test(data);
|
|
501
|
+
return isValidJsonPointer(data);
|
|
323
502
|
},
|
|
324
503
|
"relative-json-pointer"(data) {
|
|
325
|
-
|
|
326
|
-
return true;
|
|
327
|
-
}
|
|
328
|
-
return /^([0-9]+)(#|\/(?:[^~]|~0|~1)*)?$/.test(data);
|
|
504
|
+
return isValidRelativeJsonPointer(data);
|
|
329
505
|
},
|
|
330
506
|
time(data) {
|
|
331
|
-
return
|
|
332
|
-
data
|
|
333
|
-
);
|
|
507
|
+
return TIME_REGEX.test(data);
|
|
334
508
|
},
|
|
335
509
|
"uri-reference"(data) {
|
|
336
|
-
if (
|
|
510
|
+
if (data.includes("\\")) {
|
|
337
511
|
return false;
|
|
338
512
|
}
|
|
339
|
-
return
|
|
340
|
-
data
|
|
341
|
-
);
|
|
513
|
+
return URI_REFERENCE_REGEX.test(data);
|
|
342
514
|
},
|
|
343
515
|
"uri-template"(data) {
|
|
344
|
-
return
|
|
345
|
-
|
|
346
|
-
|
|
516
|
+
return isValidUriTemplate(data);
|
|
517
|
+
},
|
|
518
|
+
duration(data) {
|
|
519
|
+
return DURATION_REGEX.test(data);
|
|
520
|
+
},
|
|
521
|
+
uuid(data) {
|
|
522
|
+
return UUID_REGEX.test(data);
|
|
347
523
|
},
|
|
348
|
-
//
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
"
|
|
353
|
-
|
|
354
|
-
|
|
524
|
+
// IRI is like URI but allows Unicode. We reuse a permissive logic.
|
|
525
|
+
iri(data) {
|
|
526
|
+
return IRI_REGEX.test(data);
|
|
527
|
+
},
|
|
528
|
+
"iri-reference"(data) {
|
|
529
|
+
if (data.includes("\\")) {
|
|
530
|
+
return false;
|
|
531
|
+
}
|
|
532
|
+
return IRI_REFERENCE_REGEX.test(data);
|
|
533
|
+
},
|
|
534
|
+
// Best-effort structural validation for IDN (no punycode/tables)
|
|
535
|
+
"idn-email"(data) {
|
|
536
|
+
return IDN_EMAIL_REGEX.test(data);
|
|
537
|
+
},
|
|
538
|
+
"idn-hostname"(data) {
|
|
539
|
+
return IDN_HOSTNAME_REGEX.test(data);
|
|
540
|
+
}
|
|
355
541
|
};
|
|
356
542
|
|
|
357
543
|
// lib/types.ts
|
|
358
544
|
var Types = {
|
|
359
545
|
object(data) {
|
|
360
|
-
return
|
|
546
|
+
return data !== null && typeof data === "object" && !Array.isArray(data);
|
|
361
547
|
},
|
|
362
548
|
array(data) {
|
|
363
|
-
|
|
364
|
-
return true;
|
|
365
|
-
}
|
|
366
|
-
return typeof data === "object" && data !== null && "length" in data && "0" in data && Object.keys(data).length - 1 === data.length;
|
|
549
|
+
return Array.isArray(data);
|
|
367
550
|
},
|
|
368
551
|
string(data) {
|
|
369
552
|
return typeof data === "string";
|
|
@@ -383,17 +566,126 @@ var Types = {
|
|
|
383
566
|
// Not implemented yet
|
|
384
567
|
timestamp: false,
|
|
385
568
|
int8: false,
|
|
386
|
-
|
|
569
|
+
uint8: false,
|
|
387
570
|
int16: false,
|
|
388
|
-
|
|
571
|
+
uint16: false,
|
|
389
572
|
int32: false,
|
|
390
|
-
|
|
573
|
+
uint32: false,
|
|
391
574
|
float32: false,
|
|
392
575
|
float64: false
|
|
393
576
|
};
|
|
394
577
|
|
|
578
|
+
// lib/utils/has-changed.ts
|
|
579
|
+
function hasChanged(prev, current) {
|
|
580
|
+
if (Object.is(prev, current)) {
|
|
581
|
+
return false;
|
|
582
|
+
}
|
|
583
|
+
if (Array.isArray(prev)) {
|
|
584
|
+
if (Array.isArray(current) === false) {
|
|
585
|
+
return true;
|
|
586
|
+
}
|
|
587
|
+
if (prev.length !== current.length) {
|
|
588
|
+
return true;
|
|
589
|
+
}
|
|
590
|
+
for (let i = 0; i < current.length; i++) {
|
|
591
|
+
if (hasChanged(prev[i], current[i])) {
|
|
592
|
+
return true;
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
return false;
|
|
596
|
+
}
|
|
597
|
+
if (typeof prev === "object" && prev !== null) {
|
|
598
|
+
if (typeof current !== "object" || current === null) {
|
|
599
|
+
return true;
|
|
600
|
+
}
|
|
601
|
+
for (const key in current) {
|
|
602
|
+
if (hasChanged(prev[key], current[key])) {
|
|
603
|
+
return true;
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
for (const key in prev) {
|
|
607
|
+
if (key in current) {
|
|
608
|
+
continue;
|
|
609
|
+
}
|
|
610
|
+
if (hasChanged(prev[key], void 0)) {
|
|
611
|
+
return true;
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
return false;
|
|
615
|
+
}
|
|
616
|
+
return true;
|
|
617
|
+
}
|
|
618
|
+
|
|
395
619
|
// lib/keywords/array-keywords.ts
|
|
620
|
+
function isUniquePrimitive(value) {
|
|
621
|
+
return value === null || typeof value === "string" || typeof value === "number" || typeof value === "boolean";
|
|
622
|
+
}
|
|
623
|
+
function getArrayBucketKey(value) {
|
|
624
|
+
const length = value.length;
|
|
625
|
+
if (length === 0) {
|
|
626
|
+
return "0";
|
|
627
|
+
}
|
|
628
|
+
const first = value[0];
|
|
629
|
+
const last = value[length - 1];
|
|
630
|
+
const firstType = first === null ? "null" : typeof first;
|
|
631
|
+
const lastType = last === null ? "null" : typeof last;
|
|
632
|
+
let firstArrayMarker = "";
|
|
633
|
+
if (Array.isArray(first)) {
|
|
634
|
+
const firstSignature = getPrimitiveArraySignature(first);
|
|
635
|
+
firstArrayMarker = firstSignature === null ? `a:${first.length}` : firstSignature;
|
|
636
|
+
}
|
|
637
|
+
let lastArrayMarker = "";
|
|
638
|
+
if (Array.isArray(last)) {
|
|
639
|
+
const lastSignature = getPrimitiveArraySignature(last);
|
|
640
|
+
lastArrayMarker = lastSignature === null ? `a:${last.length}` : lastSignature;
|
|
641
|
+
}
|
|
642
|
+
return `${length}:${firstType}:${firstArrayMarker}:${lastType}:${lastArrayMarker}`;
|
|
643
|
+
}
|
|
644
|
+
function getObjectShapeKey(value) {
|
|
645
|
+
const keys = Object.keys(value).sort();
|
|
646
|
+
return `${keys.length}:${keys.join("")}`;
|
|
647
|
+
}
|
|
648
|
+
function getPrimitiveArraySignature(value) {
|
|
649
|
+
const length = value.length;
|
|
650
|
+
if (length === 0) {
|
|
651
|
+
return "a:0";
|
|
652
|
+
}
|
|
653
|
+
if (!isUniquePrimitive(value[0]) || !isUniquePrimitive(value[length - 1])) {
|
|
654
|
+
return null;
|
|
655
|
+
}
|
|
656
|
+
let signature = `a:${length}:`;
|
|
657
|
+
for (let i = 0; i < length; i++) {
|
|
658
|
+
const item = value[i];
|
|
659
|
+
if (item === null) {
|
|
660
|
+
signature += "l;";
|
|
661
|
+
continue;
|
|
662
|
+
}
|
|
663
|
+
if (typeof item === "string") {
|
|
664
|
+
signature += `s${item.length}:${item};`;
|
|
665
|
+
continue;
|
|
666
|
+
}
|
|
667
|
+
if (typeof item === "number") {
|
|
668
|
+
if (Number.isNaN(item)) {
|
|
669
|
+
signature += "n:NaN;";
|
|
670
|
+
continue;
|
|
671
|
+
}
|
|
672
|
+
if (Object.is(item, -0)) {
|
|
673
|
+
signature += "n:-0;";
|
|
674
|
+
continue;
|
|
675
|
+
}
|
|
676
|
+
signature += `n:${item};`;
|
|
677
|
+
continue;
|
|
678
|
+
}
|
|
679
|
+
if (typeof item === "boolean") {
|
|
680
|
+
signature += item ? "b:1;" : "b:0;";
|
|
681
|
+
continue;
|
|
682
|
+
}
|
|
683
|
+
return null;
|
|
684
|
+
}
|
|
685
|
+
return signature;
|
|
686
|
+
}
|
|
396
687
|
var ArrayKeywords = {
|
|
688
|
+
// lib/keywords/array-keywords.ts
|
|
397
689
|
items(schema, data, defineError) {
|
|
398
690
|
if (!Array.isArray(data)) {
|
|
399
691
|
return;
|
|
@@ -408,11 +700,11 @@ var ArrayKeywords = {
|
|
|
408
700
|
}
|
|
409
701
|
if (Array.isArray(schemaItems)) {
|
|
410
702
|
const schemaItemsLength = schemaItems.length;
|
|
411
|
-
const itemsLength =
|
|
703
|
+
const itemsLength = schemaItemsLength < dataLength ? schemaItemsLength : dataLength;
|
|
412
704
|
for (let i = 0; i < itemsLength; i++) {
|
|
413
705
|
const schemaItem = schemaItems[i];
|
|
414
706
|
if (typeof schemaItem === "boolean") {
|
|
415
|
-
if (schemaItem === false &&
|
|
707
|
+
if (schemaItem === false && data[i] !== void 0) {
|
|
416
708
|
return defineError("Array item is not allowed", {
|
|
417
709
|
item: i,
|
|
418
710
|
data: data[i]
|
|
@@ -420,8 +712,9 @@ var ArrayKeywords = {
|
|
|
420
712
|
}
|
|
421
713
|
continue;
|
|
422
714
|
}
|
|
423
|
-
|
|
424
|
-
|
|
715
|
+
const validate2 = schemaItem && schemaItem.$validate;
|
|
716
|
+
if (typeof validate2 === "function") {
|
|
717
|
+
const error = validate2(data[i]);
|
|
425
718
|
if (error) {
|
|
426
719
|
return defineError("Array item is invalid", {
|
|
427
720
|
item: i,
|
|
@@ -433,26 +726,32 @@ var ArrayKeywords = {
|
|
|
433
726
|
}
|
|
434
727
|
return;
|
|
435
728
|
}
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
729
|
+
const validate = schemaItems && schemaItems.$validate;
|
|
730
|
+
if (typeof validate !== "function") {
|
|
731
|
+
return;
|
|
732
|
+
}
|
|
733
|
+
for (let i = 0; i < dataLength; i++) {
|
|
734
|
+
const error = validate(data[i]);
|
|
735
|
+
if (error) {
|
|
736
|
+
return defineError("Array item is invalid", {
|
|
737
|
+
item: i,
|
|
738
|
+
cause: error,
|
|
739
|
+
data: data[i]
|
|
740
|
+
});
|
|
446
741
|
}
|
|
447
742
|
}
|
|
448
|
-
return;
|
|
449
743
|
},
|
|
450
744
|
elements(schema, data, defineError) {
|
|
451
|
-
if (!Array.isArray(data)
|
|
745
|
+
if (!Array.isArray(data)) {
|
|
746
|
+
return;
|
|
747
|
+
}
|
|
748
|
+
const elementsSchema = schema.elements;
|
|
749
|
+
const validate = elementsSchema && elementsSchema.$validate;
|
|
750
|
+
if (typeof validate !== "function") {
|
|
452
751
|
return;
|
|
453
752
|
}
|
|
454
753
|
for (let i = 0; i < data.length; i++) {
|
|
455
|
-
const error =
|
|
754
|
+
const error = validate(data[i]);
|
|
456
755
|
if (error) {
|
|
457
756
|
return defineError("Array item is invalid", {
|
|
458
757
|
item: i,
|
|
@@ -461,7 +760,6 @@ var ArrayKeywords = {
|
|
|
461
760
|
});
|
|
462
761
|
}
|
|
463
762
|
}
|
|
464
|
-
return;
|
|
465
763
|
},
|
|
466
764
|
minItems(schema, data, defineError) {
|
|
467
765
|
if (!Array.isArray(data) || data.length >= schema.minItems) {
|
|
@@ -476,18 +774,28 @@ var ArrayKeywords = {
|
|
|
476
774
|
return defineError("Array is too long", { data });
|
|
477
775
|
},
|
|
478
776
|
additionalItems(schema, data, defineError) {
|
|
479
|
-
if (!
|
|
777
|
+
if (!Array.isArray(data) || !Array.isArray(schema.items)) {
|
|
480
778
|
return;
|
|
481
779
|
}
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
780
|
+
let tupleLength = schema._tupleItemsLength;
|
|
781
|
+
if (tupleLength === void 0) {
|
|
782
|
+
tupleLength = schema.items.length;
|
|
783
|
+
Object.defineProperty(schema, "_tupleItemsLength", {
|
|
784
|
+
value: tupleLength,
|
|
785
|
+
enumerable: false,
|
|
786
|
+
configurable: false,
|
|
787
|
+
writable: false
|
|
788
|
+
});
|
|
789
|
+
}
|
|
790
|
+
if (data.length <= tupleLength) {
|
|
486
791
|
return;
|
|
487
792
|
}
|
|
488
|
-
if (
|
|
793
|
+
if (schema.additionalItems === false) {
|
|
794
|
+
return defineError("Array is too long", { data });
|
|
795
|
+
}
|
|
796
|
+
if (schema.additionalItems && typeof schema.additionalItems === "object" && !Array.isArray(schema.additionalItems)) {
|
|
489
797
|
if (isCompiledSchema(schema.additionalItems)) {
|
|
490
|
-
for (let i =
|
|
798
|
+
for (let i = tupleLength; i < data.length; i++) {
|
|
491
799
|
const error = schema.additionalItems.$validate(data[i]);
|
|
492
800
|
if (error) {
|
|
493
801
|
return defineError("Array item is invalid", {
|
|
@@ -507,28 +815,89 @@ var ArrayKeywords = {
|
|
|
507
815
|
if (!Array.isArray(data) || !schema.uniqueItems) {
|
|
508
816
|
return;
|
|
509
817
|
}
|
|
510
|
-
const
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
)
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
818
|
+
const len = data.length;
|
|
819
|
+
if (len <= 1) {
|
|
820
|
+
return;
|
|
821
|
+
}
|
|
822
|
+
if (len <= 8) {
|
|
823
|
+
for (let i = 0; i < len; i++) {
|
|
824
|
+
const left = data[i];
|
|
825
|
+
for (let j = i + 1; j < len; j++) {
|
|
826
|
+
const right = data[j];
|
|
827
|
+
if (left === right) {
|
|
828
|
+
return defineError("Array items are not unique", { data: right });
|
|
829
|
+
}
|
|
830
|
+
if (typeof left === "number" && typeof right === "number" && Number.isNaN(left) && Number.isNaN(right)) {
|
|
831
|
+
return defineError("Array items are not unique", { data: right });
|
|
832
|
+
}
|
|
833
|
+
if (left && right && typeof left === "object" && typeof right === "object" && !hasChanged(left, right)) {
|
|
834
|
+
return defineError("Array items are not unique", { data: right });
|
|
835
|
+
}
|
|
836
|
+
}
|
|
837
|
+
}
|
|
838
|
+
return;
|
|
839
|
+
}
|
|
840
|
+
const primitiveSeen = /* @__PURE__ */ new Set();
|
|
841
|
+
let primitiveArraySignatures;
|
|
842
|
+
let arrayBuckets;
|
|
843
|
+
let objectBuckets;
|
|
844
|
+
for (let i = 0; i < len; i++) {
|
|
845
|
+
const item = data[i];
|
|
846
|
+
if (isUniquePrimitive(item)) {
|
|
847
|
+
if (primitiveSeen.has(item)) {
|
|
848
|
+
return defineError("Array items are not unique", { data: item });
|
|
849
|
+
}
|
|
850
|
+
primitiveSeen.add(item);
|
|
851
|
+
continue;
|
|
525
852
|
}
|
|
526
|
-
if (
|
|
527
|
-
|
|
853
|
+
if (!item || typeof item !== "object") {
|
|
854
|
+
continue;
|
|
528
855
|
}
|
|
529
|
-
|
|
856
|
+
if (Array.isArray(item)) {
|
|
857
|
+
const signature = getPrimitiveArraySignature(item);
|
|
858
|
+
if (signature !== null) {
|
|
859
|
+
if (!primitiveArraySignatures) {
|
|
860
|
+
primitiveArraySignatures = /* @__PURE__ */ new Set();
|
|
861
|
+
}
|
|
862
|
+
if (primitiveArraySignatures.has(signature)) {
|
|
863
|
+
return defineError("Array items are not unique", { data: item });
|
|
864
|
+
}
|
|
865
|
+
primitiveArraySignatures.add(signature);
|
|
866
|
+
continue;
|
|
867
|
+
}
|
|
868
|
+
if (!arrayBuckets) {
|
|
869
|
+
arrayBuckets = /* @__PURE__ */ new Map();
|
|
870
|
+
}
|
|
871
|
+
const bucketKey2 = getArrayBucketKey(item);
|
|
872
|
+
let candidates2 = arrayBuckets.get(bucketKey2);
|
|
873
|
+
if (!candidates2) {
|
|
874
|
+
candidates2 = [];
|
|
875
|
+
arrayBuckets.set(bucketKey2, candidates2);
|
|
876
|
+
}
|
|
877
|
+
for (let j = 0; j < candidates2.length; j++) {
|
|
878
|
+
if (!hasChanged(candidates2[j], item)) {
|
|
879
|
+
return defineError("Array items are not unique", { data: item });
|
|
880
|
+
}
|
|
881
|
+
}
|
|
882
|
+
candidates2.push(item);
|
|
883
|
+
continue;
|
|
884
|
+
}
|
|
885
|
+
if (!objectBuckets) {
|
|
886
|
+
objectBuckets = /* @__PURE__ */ new Map();
|
|
887
|
+
}
|
|
888
|
+
const bucketKey = getObjectShapeKey(item);
|
|
889
|
+
let candidates = objectBuckets.get(bucketKey);
|
|
890
|
+
if (!candidates) {
|
|
891
|
+
candidates = [];
|
|
892
|
+
objectBuckets.set(bucketKey, candidates);
|
|
893
|
+
}
|
|
894
|
+
for (let j = 0; j < candidates.length; j++) {
|
|
895
|
+
if (!hasChanged(candidates[j], item)) {
|
|
896
|
+
return defineError("Array items are not unique", { data: item });
|
|
897
|
+
}
|
|
898
|
+
}
|
|
899
|
+
candidates.push(item);
|
|
530
900
|
}
|
|
531
|
-
return;
|
|
532
901
|
},
|
|
533
902
|
contains(schema, data, defineError) {
|
|
534
903
|
if (!Array.isArray(data)) {
|
|
@@ -543,8 +912,9 @@ var ArrayKeywords = {
|
|
|
543
912
|
}
|
|
544
913
|
return defineError("Array must not contain any items", { data });
|
|
545
914
|
}
|
|
915
|
+
const containsValidate = schema.contains.$validate;
|
|
546
916
|
for (let i = 0; i < data.length; i++) {
|
|
547
|
-
const error =
|
|
917
|
+
const error = containsValidate(data[i]);
|
|
548
918
|
if (!error) {
|
|
549
919
|
return;
|
|
550
920
|
}
|
|
@@ -554,6 +924,140 @@ var ArrayKeywords = {
|
|
|
554
924
|
}
|
|
555
925
|
};
|
|
556
926
|
|
|
927
|
+
// lib/utils/deep-freeze.ts
|
|
928
|
+
function isPlainObject(value) {
|
|
929
|
+
if (!value || typeof value !== "object") {
|
|
930
|
+
return false;
|
|
931
|
+
}
|
|
932
|
+
const proto = Object.getPrototypeOf(value);
|
|
933
|
+
return proto === Object.prototype || proto === null;
|
|
934
|
+
}
|
|
935
|
+
function canUseStructuredClone(value) {
|
|
936
|
+
if (typeof structuredClone !== "function") {
|
|
937
|
+
return false;
|
|
938
|
+
}
|
|
939
|
+
if (typeof Buffer !== "undefined" && value instanceof Buffer) {
|
|
940
|
+
return false;
|
|
941
|
+
}
|
|
942
|
+
return Array.isArray(value) || isPlainObject(value) || value instanceof Date || value instanceof RegExp || value instanceof Map || value instanceof Set || value instanceof ArrayBuffer || ArrayBuffer.isView(value);
|
|
943
|
+
}
|
|
944
|
+
function deepCloneUnfreeze(obj, cloneClassInstances = false, seen = /* @__PURE__ */ new WeakMap()) {
|
|
945
|
+
if (typeof obj === "undefined" || obj === null || typeof obj !== "object") {
|
|
946
|
+
return obj;
|
|
947
|
+
}
|
|
948
|
+
const source = obj;
|
|
949
|
+
if (seen.has(source)) {
|
|
950
|
+
return seen.get(source);
|
|
951
|
+
}
|
|
952
|
+
if (canUseStructuredClone(source)) {
|
|
953
|
+
const cloned = structuredClone(source);
|
|
954
|
+
seen.set(source, cloned);
|
|
955
|
+
return cloned;
|
|
956
|
+
}
|
|
957
|
+
let clone;
|
|
958
|
+
switch (true) {
|
|
959
|
+
case Array.isArray(source): {
|
|
960
|
+
clone = [];
|
|
961
|
+
seen.set(source, clone);
|
|
962
|
+
for (let i = 0, l = source.length; i < l; i++) {
|
|
963
|
+
clone[i] = deepCloneUnfreeze(source[i], cloneClassInstances, seen);
|
|
964
|
+
}
|
|
965
|
+
return clone;
|
|
966
|
+
}
|
|
967
|
+
case source instanceof Date: {
|
|
968
|
+
clone = new Date(source.getTime());
|
|
969
|
+
seen.set(source, clone);
|
|
970
|
+
return clone;
|
|
971
|
+
}
|
|
972
|
+
case source instanceof RegExp: {
|
|
973
|
+
clone = new RegExp(source.source, source.flags);
|
|
974
|
+
seen.set(source, clone);
|
|
975
|
+
return clone;
|
|
976
|
+
}
|
|
977
|
+
case source instanceof Map: {
|
|
978
|
+
clone = /* @__PURE__ */ new Map();
|
|
979
|
+
seen.set(source, clone);
|
|
980
|
+
for (const [key, value] of source.entries()) {
|
|
981
|
+
clone.set(
|
|
982
|
+
deepCloneUnfreeze(key, cloneClassInstances, seen),
|
|
983
|
+
deepCloneUnfreeze(value, cloneClassInstances, seen)
|
|
984
|
+
);
|
|
985
|
+
}
|
|
986
|
+
return clone;
|
|
987
|
+
}
|
|
988
|
+
case source instanceof Set: {
|
|
989
|
+
clone = /* @__PURE__ */ new Set();
|
|
990
|
+
seen.set(source, clone);
|
|
991
|
+
for (const value of source.values()) {
|
|
992
|
+
clone.add(deepCloneUnfreeze(value, cloneClassInstances, seen));
|
|
993
|
+
}
|
|
994
|
+
return clone;
|
|
995
|
+
}
|
|
996
|
+
case source instanceof ArrayBuffer: {
|
|
997
|
+
clone = source.slice(0);
|
|
998
|
+
seen.set(source, clone);
|
|
999
|
+
return clone;
|
|
1000
|
+
}
|
|
1001
|
+
case ArrayBuffer.isView(source): {
|
|
1002
|
+
clone = new source.constructor(source.buffer.slice(0));
|
|
1003
|
+
seen.set(source, clone);
|
|
1004
|
+
return clone;
|
|
1005
|
+
}
|
|
1006
|
+
case (typeof Buffer !== "undefined" && source instanceof Buffer): {
|
|
1007
|
+
clone = Buffer.from(source);
|
|
1008
|
+
seen.set(source, clone);
|
|
1009
|
+
return clone;
|
|
1010
|
+
}
|
|
1011
|
+
case source instanceof Error: {
|
|
1012
|
+
clone = new source.constructor(source.message);
|
|
1013
|
+
seen.set(source, clone);
|
|
1014
|
+
break;
|
|
1015
|
+
}
|
|
1016
|
+
case (source instanceof Promise || source instanceof WeakMap || source instanceof WeakSet): {
|
|
1017
|
+
clone = source;
|
|
1018
|
+
seen.set(source, clone);
|
|
1019
|
+
return clone;
|
|
1020
|
+
}
|
|
1021
|
+
case (source.constructor && source.constructor !== Object): {
|
|
1022
|
+
if (!cloneClassInstances) {
|
|
1023
|
+
clone = source;
|
|
1024
|
+
seen.set(source, clone);
|
|
1025
|
+
return clone;
|
|
1026
|
+
}
|
|
1027
|
+
clone = Object.create(Object.getPrototypeOf(source));
|
|
1028
|
+
seen.set(source, clone);
|
|
1029
|
+
break;
|
|
1030
|
+
}
|
|
1031
|
+
default: {
|
|
1032
|
+
clone = {};
|
|
1033
|
+
seen.set(source, clone);
|
|
1034
|
+
const keys = Reflect.ownKeys(source);
|
|
1035
|
+
for (let i = 0, l = keys.length; i < l; i++) {
|
|
1036
|
+
const key = keys[i];
|
|
1037
|
+
clone[key] = deepCloneUnfreeze(
|
|
1038
|
+
source[key],
|
|
1039
|
+
cloneClassInstances,
|
|
1040
|
+
seen
|
|
1041
|
+
);
|
|
1042
|
+
}
|
|
1043
|
+
return clone;
|
|
1044
|
+
}
|
|
1045
|
+
}
|
|
1046
|
+
const descriptors = Object.getOwnPropertyDescriptors(source);
|
|
1047
|
+
for (const key of Reflect.ownKeys(descriptors)) {
|
|
1048
|
+
const descriptor = descriptors[key];
|
|
1049
|
+
if ("value" in descriptor) {
|
|
1050
|
+
descriptor.value = deepCloneUnfreeze(
|
|
1051
|
+
descriptor.value,
|
|
1052
|
+
cloneClassInstances,
|
|
1053
|
+
seen
|
|
1054
|
+
);
|
|
1055
|
+
}
|
|
1056
|
+
Object.defineProperty(clone, key, descriptor);
|
|
1057
|
+
}
|
|
1058
|
+
return clone;
|
|
1059
|
+
}
|
|
1060
|
+
|
|
557
1061
|
// lib/keywords/number-keywords.ts
|
|
558
1062
|
var NumberKeywords = {
|
|
559
1063
|
minimum(schema, data, defineError, instance) {
|
|
@@ -622,16 +1126,129 @@ var NumberKeywords = {
|
|
|
622
1126
|
}
|
|
623
1127
|
};
|
|
624
1128
|
|
|
1129
|
+
// lib/utils/pattern-matcher.ts
|
|
1130
|
+
var REGEX_META_CHARS = /[\\.^$*+?()[\]{}|]/;
|
|
1131
|
+
function hasRegexMeta(value) {
|
|
1132
|
+
return REGEX_META_CHARS.test(value);
|
|
1133
|
+
}
|
|
1134
|
+
var PATTERN_CACHE = /* @__PURE__ */ new Map();
|
|
1135
|
+
function compilePatternMatcher(pattern) {
|
|
1136
|
+
const cached = PATTERN_CACHE.get(pattern);
|
|
1137
|
+
if (cached) {
|
|
1138
|
+
return cached;
|
|
1139
|
+
}
|
|
1140
|
+
let compiled;
|
|
1141
|
+
if (pattern.length === 0) {
|
|
1142
|
+
compiled = (_value) => true;
|
|
1143
|
+
} else if (!hasRegexMeta(pattern)) {
|
|
1144
|
+
compiled = (value) => value.includes(pattern);
|
|
1145
|
+
} else {
|
|
1146
|
+
const patternLength = pattern.length;
|
|
1147
|
+
if (patternLength >= 2 && pattern[0] === "^" && pattern[patternLength - 1] === "$") {
|
|
1148
|
+
const inner = pattern.slice(1, -1);
|
|
1149
|
+
if (!hasRegexMeta(inner)) {
|
|
1150
|
+
if (inner.length === 0) {
|
|
1151
|
+
compiled = (value) => value.length === 0;
|
|
1152
|
+
} else {
|
|
1153
|
+
compiled = (value) => value === inner;
|
|
1154
|
+
}
|
|
1155
|
+
} else {
|
|
1156
|
+
compiled = new RegExp(pattern, "u");
|
|
1157
|
+
}
|
|
1158
|
+
} else if (pattern[0] === "^") {
|
|
1159
|
+
const inner = pattern.slice(1);
|
|
1160
|
+
if (!hasRegexMeta(inner)) {
|
|
1161
|
+
if (inner.length === 0) {
|
|
1162
|
+
compiled = (_value) => true;
|
|
1163
|
+
} else {
|
|
1164
|
+
compiled = (value) => value.startsWith(inner);
|
|
1165
|
+
}
|
|
1166
|
+
} else {
|
|
1167
|
+
compiled = new RegExp(pattern, "u");
|
|
1168
|
+
}
|
|
1169
|
+
} else if (pattern[patternLength - 1] === "$") {
|
|
1170
|
+
const inner = pattern.slice(0, -1);
|
|
1171
|
+
if (!hasRegexMeta(inner)) {
|
|
1172
|
+
if (inner.length === 0) {
|
|
1173
|
+
compiled = (_value) => true;
|
|
1174
|
+
} else {
|
|
1175
|
+
compiled = (value) => value.endsWith(inner);
|
|
1176
|
+
}
|
|
1177
|
+
} else {
|
|
1178
|
+
compiled = new RegExp(pattern, "u");
|
|
1179
|
+
}
|
|
1180
|
+
} else {
|
|
1181
|
+
compiled = new RegExp(pattern, "u");
|
|
1182
|
+
}
|
|
1183
|
+
}
|
|
1184
|
+
PATTERN_CACHE.set(pattern, compiled);
|
|
1185
|
+
return compiled;
|
|
1186
|
+
}
|
|
1187
|
+
|
|
625
1188
|
// lib/keywords/object-keywords.ts
|
|
1189
|
+
var PATTERN_KEY_CACHE_LIMIT = 512;
|
|
1190
|
+
function getPatternPropertyEntries(schema) {
|
|
1191
|
+
let entries = schema._patternPropertyEntries;
|
|
1192
|
+
if (entries) {
|
|
1193
|
+
return entries;
|
|
1194
|
+
}
|
|
1195
|
+
if (!schema.patternProperties || typeof schema.patternProperties !== "object" || Array.isArray(schema.patternProperties)) {
|
|
1196
|
+
return void 0;
|
|
1197
|
+
}
|
|
1198
|
+
const patternKeys = Object.keys(schema.patternProperties);
|
|
1199
|
+
entries = new Array(patternKeys.length);
|
|
1200
|
+
for (let i = 0; i < patternKeys.length; i++) {
|
|
1201
|
+
const key = patternKeys[i];
|
|
1202
|
+
const compiledMatcher = compilePatternMatcher(key);
|
|
1203
|
+
const match = compiledMatcher instanceof RegExp ? (value) => compiledMatcher.test(value) : compiledMatcher;
|
|
1204
|
+
entries[i] = {
|
|
1205
|
+
schemaProp: schema.patternProperties[key],
|
|
1206
|
+
match
|
|
1207
|
+
};
|
|
1208
|
+
}
|
|
1209
|
+
Object.defineProperty(schema, "_patternPropertyEntries", {
|
|
1210
|
+
value: entries,
|
|
1211
|
+
enumerable: false,
|
|
1212
|
+
configurable: false,
|
|
1213
|
+
writable: false
|
|
1214
|
+
});
|
|
1215
|
+
return entries;
|
|
1216
|
+
}
|
|
1217
|
+
function getPatternKeyMatchIndexes(schema, key, entries) {
|
|
1218
|
+
let cache = schema._patternKeyMatchIndexCache;
|
|
1219
|
+
if (cache) {
|
|
1220
|
+
const cached = cache.get(key);
|
|
1221
|
+
if (cached) {
|
|
1222
|
+
return cached;
|
|
1223
|
+
}
|
|
1224
|
+
} else {
|
|
1225
|
+
cache = /* @__PURE__ */ new Map();
|
|
1226
|
+
Object.defineProperty(schema, "_patternKeyMatchIndexCache", {
|
|
1227
|
+
value: cache,
|
|
1228
|
+
enumerable: false,
|
|
1229
|
+
configurable: false,
|
|
1230
|
+
writable: false
|
|
1231
|
+
});
|
|
1232
|
+
}
|
|
1233
|
+
const indexes = [];
|
|
1234
|
+
for (let i = 0; i < entries.length; i++) {
|
|
1235
|
+
if (entries[i].match(key)) {
|
|
1236
|
+
indexes.push(i);
|
|
1237
|
+
}
|
|
1238
|
+
}
|
|
1239
|
+
if (cache.size < PATTERN_KEY_CACHE_LIMIT) {
|
|
1240
|
+
cache.set(key, indexes);
|
|
1241
|
+
}
|
|
1242
|
+
return indexes;
|
|
1243
|
+
}
|
|
626
1244
|
var ObjectKeywords = {
|
|
627
|
-
// Object
|
|
628
1245
|
required(schema, data, defineError) {
|
|
629
|
-
if (!
|
|
1246
|
+
if (!data || typeof data !== "object" || Array.isArray(data)) {
|
|
630
1247
|
return;
|
|
631
1248
|
}
|
|
632
1249
|
for (let i = 0; i < schema.required.length; i++) {
|
|
633
1250
|
const key = schema.required[i];
|
|
634
|
-
if (!
|
|
1251
|
+
if (!Object.prototype.hasOwnProperty.call(data, key)) {
|
|
635
1252
|
return defineError("Required property is missing", {
|
|
636
1253
|
item: key,
|
|
637
1254
|
data: data[key]
|
|
@@ -641,19 +1258,48 @@ var ObjectKeywords = {
|
|
|
641
1258
|
return;
|
|
642
1259
|
},
|
|
643
1260
|
properties(schema, data, defineError) {
|
|
644
|
-
if (!
|
|
1261
|
+
if (!data || typeof data !== "object" || Array.isArray(data)) {
|
|
645
1262
|
return;
|
|
646
1263
|
}
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
1264
|
+
let propKeys = schema._propKeys;
|
|
1265
|
+
if (!propKeys) {
|
|
1266
|
+
propKeys = Object.keys(schema.properties || {});
|
|
1267
|
+
Object.defineProperty(schema, "_propKeys", {
|
|
1268
|
+
value: propKeys,
|
|
1269
|
+
enumerable: false,
|
|
1270
|
+
configurable: false,
|
|
1271
|
+
writable: false
|
|
1272
|
+
});
|
|
1273
|
+
}
|
|
1274
|
+
let requiredSet = schema._requiredSet;
|
|
1275
|
+
if (requiredSet === void 0) {
|
|
1276
|
+
requiredSet = Array.isArray(schema.required) ? new Set(schema.required) : null;
|
|
1277
|
+
Object.defineProperty(schema, "_requiredSet", {
|
|
1278
|
+
value: requiredSet,
|
|
1279
|
+
enumerable: false,
|
|
1280
|
+
configurable: false,
|
|
1281
|
+
writable: false
|
|
1282
|
+
});
|
|
1283
|
+
}
|
|
1284
|
+
for (let i = 0; i < propKeys.length; i++) {
|
|
1285
|
+
const key = propKeys[i];
|
|
1286
|
+
const schemaProp = schema.properties[key];
|
|
1287
|
+
if (!Object.prototype.hasOwnProperty.call(data, key)) {
|
|
1288
|
+
if (requiredSet && requiredSet.has(key) && schemaProp && typeof schemaProp === "object" && !Array.isArray(schemaProp) && "default" in schemaProp) {
|
|
1289
|
+
const error = schemaProp.$validate(schemaProp.default);
|
|
1290
|
+
if (error) {
|
|
1291
|
+
return defineError("Default property is invalid", {
|
|
1292
|
+
item: key,
|
|
1293
|
+
cause: error,
|
|
1294
|
+
data: schemaProp.default
|
|
1295
|
+
});
|
|
1296
|
+
}
|
|
1297
|
+
data[key] = deepCloneUnfreeze(schemaProp.default);
|
|
652
1298
|
}
|
|
653
1299
|
continue;
|
|
654
1300
|
}
|
|
655
|
-
if (typeof
|
|
656
|
-
if (
|
|
1301
|
+
if (typeof schemaProp === "boolean") {
|
|
1302
|
+
if (schemaProp === false) {
|
|
657
1303
|
return defineError("Property is not allowed", {
|
|
658
1304
|
item: key,
|
|
659
1305
|
data: data[key]
|
|
@@ -661,8 +1307,8 @@ var ObjectKeywords = {
|
|
|
661
1307
|
}
|
|
662
1308
|
continue;
|
|
663
1309
|
}
|
|
664
|
-
if ("$validate" in
|
|
665
|
-
const error =
|
|
1310
|
+
if (schemaProp && "$validate" in schemaProp) {
|
|
1311
|
+
const error = schemaProp.$validate(data[key]);
|
|
666
1312
|
if (error) {
|
|
667
1313
|
return defineError("Property is invalid", {
|
|
668
1314
|
item: key,
|
|
@@ -675,12 +1321,19 @@ var ObjectKeywords = {
|
|
|
675
1321
|
return;
|
|
676
1322
|
},
|
|
677
1323
|
values(schema, data, defineError) {
|
|
678
|
-
if (!
|
|
1324
|
+
if (!data || typeof data !== "object" || Array.isArray(data)) {
|
|
1325
|
+
return;
|
|
1326
|
+
}
|
|
1327
|
+
const valueSchema = schema.values;
|
|
1328
|
+
const validate = valueSchema && valueSchema.$validate;
|
|
1329
|
+
if (typeof validate !== "function") {
|
|
679
1330
|
return;
|
|
680
1331
|
}
|
|
681
|
-
const
|
|
682
|
-
|
|
683
|
-
|
|
1332
|
+
for (const key in data) {
|
|
1333
|
+
if (!Object.prototype.hasOwnProperty.call(data, key)) {
|
|
1334
|
+
continue;
|
|
1335
|
+
}
|
|
1336
|
+
const error = validate(data[key]);
|
|
684
1337
|
if (error) {
|
|
685
1338
|
return defineError("Property is invalid", {
|
|
686
1339
|
item: key,
|
|
@@ -689,39 +1342,63 @@ var ObjectKeywords = {
|
|
|
689
1342
|
});
|
|
690
1343
|
}
|
|
691
1344
|
}
|
|
692
|
-
return;
|
|
693
1345
|
},
|
|
694
1346
|
maxProperties(schema, data, defineError) {
|
|
695
|
-
if (!
|
|
1347
|
+
if (!data || typeof data !== "object" || Array.isArray(data)) {
|
|
696
1348
|
return;
|
|
697
1349
|
}
|
|
698
|
-
|
|
1350
|
+
let count = 0;
|
|
1351
|
+
for (const key in data) {
|
|
1352
|
+
if (!Object.prototype.hasOwnProperty.call(data, key)) {
|
|
1353
|
+
continue;
|
|
1354
|
+
}
|
|
1355
|
+
count++;
|
|
1356
|
+
if (count > schema.maxProperties) {
|
|
1357
|
+
return defineError("Too many properties", { data });
|
|
1358
|
+
}
|
|
1359
|
+
}
|
|
1360
|
+
return;
|
|
699
1361
|
},
|
|
700
1362
|
minProperties(schema, data, defineError) {
|
|
701
|
-
if (!
|
|
1363
|
+
if (!data || typeof data !== "object" || Array.isArray(data)) {
|
|
702
1364
|
return;
|
|
703
1365
|
}
|
|
1366
|
+
let count = 0;
|
|
1367
|
+
for (const key in data) {
|
|
1368
|
+
if (!Object.prototype.hasOwnProperty.call(data, key)) {
|
|
1369
|
+
continue;
|
|
1370
|
+
}
|
|
1371
|
+
count++;
|
|
1372
|
+
if (count >= schema.minProperties) {
|
|
1373
|
+
return;
|
|
1374
|
+
}
|
|
1375
|
+
}
|
|
704
1376
|
return defineError("Too few properties", { data });
|
|
705
1377
|
},
|
|
706
1378
|
additionalProperties(schema, data, defineError) {
|
|
707
|
-
if (!
|
|
1379
|
+
if (!data || typeof data !== "object" || Array.isArray(data)) {
|
|
708
1380
|
return;
|
|
709
1381
|
}
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
1382
|
+
let apValidate = schema._apValidate;
|
|
1383
|
+
if (apValidate === void 0) {
|
|
1384
|
+
apValidate = isCompiledSchema(schema.additionalProperties) ? schema.additionalProperties.$validate : null;
|
|
1385
|
+
Object.defineProperty(schema, "_apValidate", {
|
|
1386
|
+
value: apValidate,
|
|
1387
|
+
enumerable: false,
|
|
1388
|
+
configurable: false,
|
|
1389
|
+
writable: false
|
|
1390
|
+
});
|
|
1391
|
+
}
|
|
1392
|
+
const patternEntries = getPatternPropertyEntries(schema);
|
|
1393
|
+
for (const key in data) {
|
|
1394
|
+
if (!Object.prototype.hasOwnProperty.call(data, key)) {
|
|
714
1395
|
continue;
|
|
715
1396
|
}
|
|
716
|
-
if (schema.
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
break;
|
|
722
|
-
}
|
|
723
|
-
}
|
|
724
|
-
if (match) {
|
|
1397
|
+
if (schema.properties && Object.prototype.hasOwnProperty.call(schema.properties, key)) {
|
|
1398
|
+
continue;
|
|
1399
|
+
}
|
|
1400
|
+
if (patternEntries && patternEntries.length) {
|
|
1401
|
+
if (getPatternKeyMatchIndexes(schema, key, patternEntries).length > 0) {
|
|
725
1402
|
continue;
|
|
726
1403
|
}
|
|
727
1404
|
}
|
|
@@ -731,8 +1408,8 @@ var ObjectKeywords = {
|
|
|
731
1408
|
data: data[key]
|
|
732
1409
|
});
|
|
733
1410
|
}
|
|
734
|
-
if (
|
|
735
|
-
const error =
|
|
1411
|
+
if (apValidate) {
|
|
1412
|
+
const error = apValidate(data[key]);
|
|
736
1413
|
if (error) {
|
|
737
1414
|
return defineError("Additional properties are invalid", {
|
|
738
1415
|
item: key,
|
|
@@ -745,39 +1422,46 @@ var ObjectKeywords = {
|
|
|
745
1422
|
return;
|
|
746
1423
|
},
|
|
747
1424
|
patternProperties(schema, data, defineError) {
|
|
748
|
-
if (!
|
|
1425
|
+
if (!data || typeof data !== "object" || Array.isArray(data)) {
|
|
749
1426
|
return;
|
|
750
1427
|
}
|
|
751
|
-
const
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
1428
|
+
const patternEntries = getPatternPropertyEntries(schema);
|
|
1429
|
+
if (!patternEntries || patternEntries.length === 0) {
|
|
1430
|
+
return;
|
|
1431
|
+
}
|
|
1432
|
+
for (const key in data) {
|
|
1433
|
+
if (!Object.prototype.hasOwnProperty.call(data, key)) {
|
|
1434
|
+
continue;
|
|
1435
|
+
}
|
|
1436
|
+
const matchingIndexes = getPatternKeyMatchIndexes(schema, key, patternEntries);
|
|
1437
|
+
if (matchingIndexes.length === 0) {
|
|
1438
|
+
if (schema.additionalProperties === false && !(schema.properties && Object.prototype.hasOwnProperty.call(schema.properties, key))) {
|
|
1439
|
+
return defineError("Additional properties are not allowed", {
|
|
1440
|
+
item: key,
|
|
1441
|
+
data: data[key]
|
|
1442
|
+
});
|
|
764
1443
|
}
|
|
765
1444
|
continue;
|
|
766
1445
|
}
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
if (
|
|
770
|
-
if (
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
1446
|
+
for (let j = 0; j < matchingIndexes.length; j++) {
|
|
1447
|
+
const schemaProp = patternEntries[matchingIndexes[j]].schemaProp;
|
|
1448
|
+
if (typeof schemaProp === "boolean") {
|
|
1449
|
+
if (schemaProp === false) {
|
|
1450
|
+
return defineError("Property is not allowed", {
|
|
1451
|
+
item: key,
|
|
1452
|
+
data: data[key]
|
|
1453
|
+
});
|
|
1454
|
+
}
|
|
1455
|
+
continue;
|
|
1456
|
+
}
|
|
1457
|
+
if ("$validate" in schemaProp) {
|
|
1458
|
+
const error = schemaProp.$validate(data[key]);
|
|
1459
|
+
if (error) {
|
|
1460
|
+
return defineError("Property is invalid", {
|
|
1461
|
+
item: key,
|
|
1462
|
+
cause: error,
|
|
1463
|
+
data: data[key]
|
|
1464
|
+
});
|
|
781
1465
|
}
|
|
782
1466
|
}
|
|
783
1467
|
}
|
|
@@ -785,30 +1469,40 @@ var ObjectKeywords = {
|
|
|
785
1469
|
return;
|
|
786
1470
|
},
|
|
787
1471
|
propertyNames(schema, data, defineError) {
|
|
788
|
-
if (!
|
|
1472
|
+
if (!data || typeof data !== "object" || Array.isArray(data)) {
|
|
789
1473
|
return;
|
|
790
1474
|
}
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
1475
|
+
const pn = schema.propertyNames;
|
|
1476
|
+
if (typeof pn === "boolean") {
|
|
1477
|
+
if (pn === false) {
|
|
1478
|
+
for (const key in data) {
|
|
1479
|
+
if (Object.prototype.hasOwnProperty.call(data, key)) {
|
|
1480
|
+
return defineError("Properties are not allowed", { data });
|
|
1481
|
+
}
|
|
1482
|
+
}
|
|
794
1483
|
}
|
|
1484
|
+
return;
|
|
795
1485
|
}
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
1486
|
+
const validate = pn && pn.$validate;
|
|
1487
|
+
if (typeof validate !== "function") {
|
|
1488
|
+
return;
|
|
1489
|
+
}
|
|
1490
|
+
for (const key in data) {
|
|
1491
|
+
if (!Object.prototype.hasOwnProperty.call(data, key)) {
|
|
1492
|
+
continue;
|
|
1493
|
+
}
|
|
1494
|
+
const error = validate(key);
|
|
1495
|
+
if (error) {
|
|
1496
|
+
return defineError("Property name is invalid", {
|
|
1497
|
+
item: key,
|
|
1498
|
+
cause: error,
|
|
1499
|
+
data: data[key]
|
|
1500
|
+
});
|
|
806
1501
|
}
|
|
807
1502
|
}
|
|
808
|
-
return;
|
|
809
1503
|
},
|
|
810
1504
|
dependencies(schema, data, defineError) {
|
|
811
|
-
if (!
|
|
1505
|
+
if (!data || typeof data !== "object" || Array.isArray(data)) {
|
|
812
1506
|
return;
|
|
813
1507
|
}
|
|
814
1508
|
for (const key in schema.dependencies) {
|
|
@@ -854,7 +1548,6 @@ var ObjectKeywords = {
|
|
|
854
1548
|
else: false,
|
|
855
1549
|
default: false,
|
|
856
1550
|
// Not implemented yet
|
|
857
|
-
$ref: false,
|
|
858
1551
|
definitions: false,
|
|
859
1552
|
$id: false,
|
|
860
1553
|
$schema: false,
|
|
@@ -871,17 +1564,66 @@ var ObjectKeywords = {
|
|
|
871
1564
|
};
|
|
872
1565
|
|
|
873
1566
|
// lib/keywords/other-keywords.ts
|
|
1567
|
+
function toBranchEntry(item) {
|
|
1568
|
+
if (item && typeof item === "object" && !Array.isArray(item)) {
|
|
1569
|
+
if ("$validate" in item && typeof item.$validate === "function") {
|
|
1570
|
+
return { kind: "validate", validate: item.$validate };
|
|
1571
|
+
}
|
|
1572
|
+
return { kind: "alwaysValid" };
|
|
1573
|
+
}
|
|
1574
|
+
if (typeof item === "boolean") {
|
|
1575
|
+
return { kind: item ? "alwaysValid" : "alwaysInvalid" };
|
|
1576
|
+
}
|
|
1577
|
+
return { kind: "literal", value: item };
|
|
1578
|
+
}
|
|
1579
|
+
function getBranchEntries(schema, key) {
|
|
1580
|
+
const cacheKey = `_${key}BranchEntries`;
|
|
1581
|
+
let entries = schema[cacheKey];
|
|
1582
|
+
if (entries) {
|
|
1583
|
+
return entries;
|
|
1584
|
+
}
|
|
1585
|
+
const source = schema[key] || [];
|
|
1586
|
+
entries = [];
|
|
1587
|
+
for (let i = 0; i < source.length; i++) {
|
|
1588
|
+
entries.push(toBranchEntry(source[i]));
|
|
1589
|
+
}
|
|
1590
|
+
Object.defineProperty(schema, cacheKey, {
|
|
1591
|
+
value: entries,
|
|
1592
|
+
enumerable: false,
|
|
1593
|
+
configurable: false,
|
|
1594
|
+
writable: false
|
|
1595
|
+
});
|
|
1596
|
+
return entries;
|
|
1597
|
+
}
|
|
874
1598
|
var OtherKeywords = {
|
|
875
1599
|
enum(schema, data, defineError) {
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
const
|
|
880
|
-
|
|
881
|
-
|
|
1600
|
+
let enumCache = schema._enumCache;
|
|
1601
|
+
if (!enumCache) {
|
|
1602
|
+
const primitiveSet = /* @__PURE__ */ new Set();
|
|
1603
|
+
const objectValues = [];
|
|
1604
|
+
const list = schema.enum;
|
|
1605
|
+
for (let i = 0; i < list.length; i++) {
|
|
1606
|
+
const enumItem = list[i];
|
|
1607
|
+
if (enumItem !== null && typeof enumItem === "object") {
|
|
1608
|
+
objectValues.push(enumItem);
|
|
1609
|
+
} else {
|
|
1610
|
+
primitiveSet.add(enumItem);
|
|
1611
|
+
}
|
|
882
1612
|
}
|
|
883
|
-
|
|
884
|
-
|
|
1613
|
+
enumCache = { primitiveSet, objectValues };
|
|
1614
|
+
Object.defineProperty(schema, "_enumCache", {
|
|
1615
|
+
value: enumCache,
|
|
1616
|
+
enumerable: false,
|
|
1617
|
+
configurable: false,
|
|
1618
|
+
writable: false
|
|
1619
|
+
});
|
|
1620
|
+
}
|
|
1621
|
+
if (!(typeof data === "number" && Number.isNaN(data)) && enumCache.primitiveSet.has(data)) {
|
|
1622
|
+
return;
|
|
1623
|
+
}
|
|
1624
|
+
if (data !== null && typeof data === "object") {
|
|
1625
|
+
for (let i = 0; i < enumCache.objectValues.length; i++) {
|
|
1626
|
+
if (!hasChanged(enumCache.objectValues[i], data)) {
|
|
885
1627
|
return;
|
|
886
1628
|
}
|
|
887
1629
|
}
|
|
@@ -889,74 +1631,130 @@ var OtherKeywords = {
|
|
|
889
1631
|
return defineError("Value is not one of the allowed values", { data });
|
|
890
1632
|
},
|
|
891
1633
|
allOf(schema, data, defineError) {
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
}
|
|
1634
|
+
const branches = getBranchEntries(schema, "allOf");
|
|
1635
|
+
if (branches.length === 1) {
|
|
1636
|
+
const onlyBranch = branches[0];
|
|
1637
|
+
if (onlyBranch.kind === "validate") {
|
|
1638
|
+
const error = onlyBranch.validate(data);
|
|
1639
|
+
if (error) {
|
|
1640
|
+
return defineError("Value is not valid", { cause: error, data });
|
|
899
1641
|
}
|
|
900
|
-
|
|
1642
|
+
return;
|
|
901
1643
|
}
|
|
902
|
-
if (
|
|
903
|
-
|
|
904
|
-
|
|
1644
|
+
if (onlyBranch.kind === "alwaysValid") {
|
|
1645
|
+
return;
|
|
1646
|
+
}
|
|
1647
|
+
if (onlyBranch.kind === "alwaysInvalid") {
|
|
1648
|
+
return defineError("Value is not valid", { data });
|
|
1649
|
+
}
|
|
1650
|
+
if (data !== onlyBranch.value) {
|
|
1651
|
+
return defineError("Value is not valid", { data });
|
|
1652
|
+
}
|
|
1653
|
+
return;
|
|
1654
|
+
}
|
|
1655
|
+
for (let i = 0; i < branches.length; i++) {
|
|
1656
|
+
const branch = branches[i];
|
|
1657
|
+
if (branch.kind === "validate") {
|
|
1658
|
+
const error = branch.validate(data);
|
|
1659
|
+
if (error) {
|
|
1660
|
+
return defineError("Value is not valid", { cause: error, data });
|
|
905
1661
|
}
|
|
906
1662
|
continue;
|
|
907
1663
|
}
|
|
908
|
-
if (
|
|
1664
|
+
if (branch.kind === "alwaysValid") {
|
|
1665
|
+
continue;
|
|
1666
|
+
}
|
|
1667
|
+
if (branch.kind === "alwaysInvalid") {
|
|
1668
|
+
return defineError("Value is not valid", { data });
|
|
1669
|
+
}
|
|
1670
|
+
if (data !== branch.value) {
|
|
909
1671
|
return defineError("Value is not valid", { data });
|
|
910
1672
|
}
|
|
911
1673
|
}
|
|
912
1674
|
return;
|
|
913
1675
|
},
|
|
914
1676
|
anyOf(schema, data, defineError) {
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
continue;
|
|
1677
|
+
const branches = getBranchEntries(schema, "anyOf");
|
|
1678
|
+
if (branches.length === 1) {
|
|
1679
|
+
const onlyBranch = branches[0];
|
|
1680
|
+
if (onlyBranch.kind === "validate") {
|
|
1681
|
+
const error = onlyBranch.validate(data);
|
|
1682
|
+
if (!error) {
|
|
1683
|
+
return;
|
|
923
1684
|
}
|
|
1685
|
+
return defineError("Value is not valid", { data });
|
|
1686
|
+
}
|
|
1687
|
+
if (onlyBranch.kind === "alwaysValid") {
|
|
924
1688
|
return;
|
|
925
|
-
}
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
1689
|
+
}
|
|
1690
|
+
if (onlyBranch.kind === "alwaysInvalid") {
|
|
1691
|
+
return defineError("Value is not valid", { data });
|
|
1692
|
+
}
|
|
1693
|
+
if (data === onlyBranch.value) {
|
|
1694
|
+
return;
|
|
1695
|
+
}
|
|
1696
|
+
return defineError("Value is not valid", { data });
|
|
1697
|
+
}
|
|
1698
|
+
for (let i = 0; i < branches.length; i++) {
|
|
1699
|
+
const branch = branches[i];
|
|
1700
|
+
if (branch.kind === "validate") {
|
|
1701
|
+
const error = branch.validate(data);
|
|
1702
|
+
if (!error) {
|
|
932
1703
|
return;
|
|
933
1704
|
}
|
|
1705
|
+
continue;
|
|
1706
|
+
}
|
|
1707
|
+
if (branch.kind === "alwaysValid") {
|
|
1708
|
+
return;
|
|
1709
|
+
}
|
|
1710
|
+
if (branch.kind === "alwaysInvalid") {
|
|
1711
|
+
continue;
|
|
1712
|
+
}
|
|
1713
|
+
if (data === branch.value) {
|
|
1714
|
+
return;
|
|
934
1715
|
}
|
|
935
1716
|
}
|
|
936
1717
|
return defineError("Value is not valid", { data });
|
|
937
1718
|
},
|
|
938
1719
|
oneOf(schema, data, defineError) {
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
}
|
|
947
|
-
continue;
|
|
1720
|
+
const branches = getBranchEntries(schema, "oneOf");
|
|
1721
|
+
if (branches.length === 1) {
|
|
1722
|
+
const onlyBranch = branches[0];
|
|
1723
|
+
if (onlyBranch.kind === "validate") {
|
|
1724
|
+
const error = onlyBranch.validate(data);
|
|
1725
|
+
if (!error) {
|
|
1726
|
+
return;
|
|
948
1727
|
}
|
|
949
|
-
|
|
950
|
-
|
|
1728
|
+
return defineError("Value is not valid", { data });
|
|
1729
|
+
}
|
|
1730
|
+
if (onlyBranch.kind === "alwaysValid") {
|
|
1731
|
+
return;
|
|
1732
|
+
}
|
|
1733
|
+
if (onlyBranch.kind === "alwaysInvalid") {
|
|
1734
|
+
return defineError("Value is not valid", { data });
|
|
1735
|
+
}
|
|
1736
|
+
if (data === onlyBranch.value) {
|
|
1737
|
+
return;
|
|
1738
|
+
}
|
|
1739
|
+
return defineError("Value is not valid", { data });
|
|
1740
|
+
}
|
|
1741
|
+
let validCount = 0;
|
|
1742
|
+
for (let i = 0; i < branches.length; i++) {
|
|
1743
|
+
const branch = branches[i];
|
|
1744
|
+
let isValid = false;
|
|
1745
|
+
if (branch.kind === "validate") {
|
|
1746
|
+
isValid = !branch.validate(data);
|
|
1747
|
+
} else if (branch.kind === "alwaysValid") {
|
|
1748
|
+
isValid = true;
|
|
1749
|
+
} else if (branch.kind === "alwaysInvalid") {
|
|
1750
|
+
isValid = false;
|
|
951
1751
|
} else {
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
if (data === schema.oneOf[i]) {
|
|
959
|
-
validCount++;
|
|
1752
|
+
isValid = data === branch.value;
|
|
1753
|
+
}
|
|
1754
|
+
if (isValid) {
|
|
1755
|
+
validCount++;
|
|
1756
|
+
if (validCount > 1) {
|
|
1757
|
+
return defineError("Value is not valid", { data });
|
|
960
1758
|
}
|
|
961
1759
|
}
|
|
962
1760
|
}
|
|
@@ -966,12 +1764,15 @@ var OtherKeywords = {
|
|
|
966
1764
|
return defineError("Value is not valid", { data });
|
|
967
1765
|
},
|
|
968
1766
|
const(schema, data, defineError) {
|
|
969
|
-
if (data === schema.const
|
|
1767
|
+
if (data === schema.const) {
|
|
1768
|
+
return;
|
|
1769
|
+
}
|
|
1770
|
+
if (data && typeof data === "object" && !Array.isArray(data) && schema.const && typeof schema.const === "object" && !Array.isArray(schema.const) && !hasChanged(data, schema.const) || Array.isArray(data) && Array.isArray(schema.const) && !hasChanged(data, schema.const)) {
|
|
970
1771
|
return;
|
|
971
1772
|
}
|
|
972
1773
|
return defineError("Value is not valid", { data });
|
|
973
1774
|
},
|
|
974
|
-
if(schema, data
|
|
1775
|
+
if(schema, data) {
|
|
975
1776
|
if ("then" in schema === false && "else" in schema === false) {
|
|
976
1777
|
return;
|
|
977
1778
|
}
|
|
@@ -1008,21 +1809,45 @@ var OtherKeywords = {
|
|
|
1008
1809
|
}
|
|
1009
1810
|
return;
|
|
1010
1811
|
}
|
|
1011
|
-
if (
|
|
1812
|
+
if (schema.not && typeof schema.not === "object" && !Array.isArray(schema.not)) {
|
|
1012
1813
|
if ("$validate" in schema.not) {
|
|
1013
1814
|
const error = schema.not.$validate(data);
|
|
1014
1815
|
if (!error) {
|
|
1015
|
-
return defineError("Value is not valid", {
|
|
1816
|
+
return defineError("Value is not valid", { data });
|
|
1016
1817
|
}
|
|
1017
1818
|
return;
|
|
1018
1819
|
}
|
|
1019
1820
|
return defineError("Value is not valid", { data });
|
|
1020
1821
|
}
|
|
1021
1822
|
return defineError("Value is not valid", { data });
|
|
1823
|
+
},
|
|
1824
|
+
$ref(schema, data, defineError, instance) {
|
|
1825
|
+
if (schema._resolvedRef) {
|
|
1826
|
+
if (schema.$validate !== schema._resolvedRef) {
|
|
1827
|
+
schema.$validate = schema._resolvedRef;
|
|
1828
|
+
}
|
|
1829
|
+
return schema._resolvedRef(data);
|
|
1830
|
+
}
|
|
1831
|
+
const refPath = schema.$ref;
|
|
1832
|
+
let targetSchema = instance.getSchemaRef(refPath);
|
|
1833
|
+
if (!targetSchema) {
|
|
1834
|
+
targetSchema = instance.getSchemaById(refPath);
|
|
1835
|
+
}
|
|
1836
|
+
if (!targetSchema) {
|
|
1837
|
+
return defineError(`Missing reference: ${refPath}`);
|
|
1838
|
+
}
|
|
1839
|
+
if (!targetSchema.$validate) {
|
|
1840
|
+
return;
|
|
1841
|
+
}
|
|
1842
|
+
schema._resolvedRef = targetSchema.$validate;
|
|
1843
|
+
schema.$validate = schema._resolvedRef;
|
|
1844
|
+
return schema._resolvedRef(data);
|
|
1022
1845
|
}
|
|
1023
1846
|
};
|
|
1024
1847
|
|
|
1025
1848
|
// lib/keywords/string-keywords.ts
|
|
1849
|
+
var PATTERN_MATCH_CACHE_LIMIT = 512;
|
|
1850
|
+
var FORMAT_RESULT_CACHE_LIMIT = 512;
|
|
1026
1851
|
var StringKeywords = {
|
|
1027
1852
|
minLength(schema, data, defineError) {
|
|
1028
1853
|
if (typeof data !== "string" || data.length >= schema.minLength) {
|
|
@@ -1040,11 +1865,44 @@ var StringKeywords = {
|
|
|
1040
1865
|
if (typeof data !== "string") {
|
|
1041
1866
|
return;
|
|
1042
1867
|
}
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1868
|
+
let patternMatch = schema._patternMatch;
|
|
1869
|
+
let patternMatchCache = schema._patternMatchCache;
|
|
1870
|
+
if (!patternMatch) {
|
|
1871
|
+
try {
|
|
1872
|
+
const compiled = compilePatternMatcher(schema.pattern);
|
|
1873
|
+
patternMatch = compiled instanceof RegExp ? (value) => compiled.test(value) : compiled;
|
|
1874
|
+
Object.defineProperty(schema, "_patternMatch", {
|
|
1875
|
+
value: patternMatch,
|
|
1876
|
+
enumerable: false,
|
|
1877
|
+
configurable: false,
|
|
1878
|
+
writable: false
|
|
1879
|
+
});
|
|
1880
|
+
} catch (error) {
|
|
1881
|
+
return defineError("Invalid regular expression", {
|
|
1882
|
+
data,
|
|
1883
|
+
cause: error
|
|
1884
|
+
});
|
|
1885
|
+
}
|
|
1886
|
+
}
|
|
1887
|
+
if (!patternMatchCache) {
|
|
1888
|
+
patternMatchCache = /* @__PURE__ */ new Map();
|
|
1889
|
+
Object.defineProperty(schema, "_patternMatchCache", {
|
|
1890
|
+
value: patternMatchCache,
|
|
1891
|
+
enumerable: false,
|
|
1892
|
+
configurable: false,
|
|
1893
|
+
writable: false
|
|
1894
|
+
});
|
|
1895
|
+
} else if (patternMatchCache.has(data)) {
|
|
1896
|
+
if (patternMatchCache.get(data)) {
|
|
1897
|
+
return;
|
|
1898
|
+
}
|
|
1899
|
+
return defineError("Value does not match the pattern", { data });
|
|
1900
|
+
}
|
|
1901
|
+
const isMatch = patternMatch(data);
|
|
1902
|
+
if (patternMatchCache.size < PATTERN_MATCH_CACHE_LIMIT) {
|
|
1903
|
+
patternMatchCache.set(data, isMatch);
|
|
1046
1904
|
}
|
|
1047
|
-
if (
|
|
1905
|
+
if (isMatch) {
|
|
1048
1906
|
return;
|
|
1049
1907
|
}
|
|
1050
1908
|
return defineError("Value does not match the pattern", { data });
|
|
@@ -1055,8 +1913,58 @@ var StringKeywords = {
|
|
|
1055
1913
|
if (typeof data !== "string") {
|
|
1056
1914
|
return;
|
|
1057
1915
|
}
|
|
1058
|
-
|
|
1059
|
-
|
|
1916
|
+
let formatValidate = schema._formatValidate;
|
|
1917
|
+
let formatResultCacheEnabled = schema._formatResultCacheEnabled;
|
|
1918
|
+
let formatResultCache = schema._formatResultCache;
|
|
1919
|
+
if (formatValidate === void 0) {
|
|
1920
|
+
formatValidate = instance.getFormat(schema.format);
|
|
1921
|
+
Object.defineProperty(schema, "_formatValidate", {
|
|
1922
|
+
value: formatValidate,
|
|
1923
|
+
enumerable: false,
|
|
1924
|
+
configurable: false,
|
|
1925
|
+
writable: false
|
|
1926
|
+
});
|
|
1927
|
+
}
|
|
1928
|
+
if (!formatValidate) {
|
|
1929
|
+
return;
|
|
1930
|
+
}
|
|
1931
|
+
if (formatResultCacheEnabled === void 0) {
|
|
1932
|
+
formatResultCacheEnabled = instance.isDefaultFormatValidator(
|
|
1933
|
+
schema.format,
|
|
1934
|
+
formatValidate
|
|
1935
|
+
);
|
|
1936
|
+
Object.defineProperty(schema, "_formatResultCacheEnabled", {
|
|
1937
|
+
value: formatResultCacheEnabled,
|
|
1938
|
+
enumerable: false,
|
|
1939
|
+
configurable: false,
|
|
1940
|
+
writable: false
|
|
1941
|
+
});
|
|
1942
|
+
}
|
|
1943
|
+
if (!formatResultCacheEnabled) {
|
|
1944
|
+
if (formatValidate(data)) {
|
|
1945
|
+
return;
|
|
1946
|
+
}
|
|
1947
|
+
return defineError("Value does not match the format", { data });
|
|
1948
|
+
}
|
|
1949
|
+
if (!formatResultCache) {
|
|
1950
|
+
formatResultCache = /* @__PURE__ */ new Map();
|
|
1951
|
+
Object.defineProperty(schema, "_formatResultCache", {
|
|
1952
|
+
value: formatResultCache,
|
|
1953
|
+
enumerable: false,
|
|
1954
|
+
configurable: false,
|
|
1955
|
+
writable: false
|
|
1956
|
+
});
|
|
1957
|
+
} else if (formatResultCache.has(data)) {
|
|
1958
|
+
if (formatResultCache.get(data)) {
|
|
1959
|
+
return;
|
|
1960
|
+
}
|
|
1961
|
+
return defineError("Value does not match the format", { data });
|
|
1962
|
+
}
|
|
1963
|
+
const isValid = formatValidate(data);
|
|
1964
|
+
if (formatResultCache.size < FORMAT_RESULT_CACHE_LIMIT) {
|
|
1965
|
+
formatResultCache.set(data, isValid);
|
|
1966
|
+
}
|
|
1967
|
+
if (isValid) {
|
|
1060
1968
|
return;
|
|
1061
1969
|
}
|
|
1062
1970
|
return defineError("Value does not match the format", { data });
|
|
@@ -1078,10 +1986,15 @@ var SchemaShield = class {
|
|
|
1078
1986
|
formats = {};
|
|
1079
1987
|
keywords = {};
|
|
1080
1988
|
immutable = false;
|
|
1989
|
+
rootSchema = null;
|
|
1990
|
+
idRegistry = /* @__PURE__ */ new Map();
|
|
1991
|
+
failFast = true;
|
|
1081
1992
|
constructor({
|
|
1082
|
-
immutable = false
|
|
1993
|
+
immutable = false,
|
|
1994
|
+
failFast = true
|
|
1083
1995
|
} = {}) {
|
|
1084
1996
|
this.immutable = immutable;
|
|
1997
|
+
this.failFast = failFast;
|
|
1085
1998
|
for (const [type, validator] of Object.entries(Types)) {
|
|
1086
1999
|
if (validator) {
|
|
1087
2000
|
this.addType(type, validator);
|
|
@@ -1114,6 +2027,9 @@ var SchemaShield = class {
|
|
|
1114
2027
|
getFormat(format) {
|
|
1115
2028
|
return this.formats[format];
|
|
1116
2029
|
}
|
|
2030
|
+
isDefaultFormatValidator(format, validator) {
|
|
2031
|
+
return Formats[format] === validator;
|
|
2032
|
+
}
|
|
1117
2033
|
addKeyword(name, validator, overwrite = false) {
|
|
1118
2034
|
if (this.keywords[name] && !overwrite) {
|
|
1119
2035
|
throw new ValidationError(`Keyword "${name}" already exists`);
|
|
@@ -1123,150 +2039,537 @@ var SchemaShield = class {
|
|
|
1123
2039
|
getKeyword(keyword) {
|
|
1124
2040
|
return this.keywords[keyword];
|
|
1125
2041
|
}
|
|
2042
|
+
getSchemaRef(path) {
|
|
2043
|
+
if (!this.rootSchema) {
|
|
2044
|
+
return;
|
|
2045
|
+
}
|
|
2046
|
+
return resolvePath(this.rootSchema, path);
|
|
2047
|
+
}
|
|
2048
|
+
getSchemaById(id) {
|
|
2049
|
+
return this.idRegistry.get(id);
|
|
2050
|
+
}
|
|
1126
2051
|
compile(schema) {
|
|
2052
|
+
this.idRegistry.clear();
|
|
1127
2053
|
const compiledSchema = this.compileSchema(schema);
|
|
2054
|
+
this.rootSchema = compiledSchema;
|
|
2055
|
+
if (compiledSchema._hasRef === true) {
|
|
2056
|
+
this.linkReferences(compiledSchema);
|
|
2057
|
+
}
|
|
1128
2058
|
if (!compiledSchema.$validate) {
|
|
1129
|
-
if (
|
|
2059
|
+
if (schema === false) {
|
|
2060
|
+
const defineError = getDefinedErrorFunctionForKey(
|
|
2061
|
+
"oneOf",
|
|
2062
|
+
compiledSchema,
|
|
2063
|
+
this.failFast
|
|
2064
|
+
);
|
|
2065
|
+
compiledSchema.$validate = getNamedFunction(
|
|
2066
|
+
"Validate_False",
|
|
2067
|
+
(data) => defineError("Value is not valid", { data })
|
|
2068
|
+
);
|
|
2069
|
+
} else if (schema === true) {
|
|
2070
|
+
compiledSchema.$validate = getNamedFunction(
|
|
2071
|
+
"Validate_Any",
|
|
2072
|
+
() => {
|
|
2073
|
+
}
|
|
2074
|
+
);
|
|
2075
|
+
} else if (this.isSchemaLike(schema) === false) {
|
|
1130
2076
|
throw new ValidationError("Invalid schema");
|
|
2077
|
+
} else {
|
|
2078
|
+
compiledSchema.$validate = getNamedFunction(
|
|
2079
|
+
"Validate_Any",
|
|
2080
|
+
() => {
|
|
2081
|
+
}
|
|
2082
|
+
);
|
|
1131
2083
|
}
|
|
1132
|
-
compiledSchema.$validate = getNamedFunction(
|
|
1133
|
-
"any",
|
|
1134
|
-
() => {
|
|
1135
|
-
}
|
|
1136
|
-
);
|
|
1137
2084
|
}
|
|
1138
2085
|
const validate = (data) => {
|
|
1139
|
-
|
|
1140
|
-
const
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
};
|
|
2086
|
+
this.rootSchema = compiledSchema;
|
|
2087
|
+
const clonedData = this.immutable ? deepCloneUnfreeze(data) : data;
|
|
2088
|
+
const res = compiledSchema.$validate(clonedData);
|
|
2089
|
+
if (res) {
|
|
2090
|
+
return { data: clonedData, error: res, valid: false };
|
|
2091
|
+
}
|
|
2092
|
+
return { data: clonedData, error: null, valid: true };
|
|
1146
2093
|
};
|
|
1147
2094
|
validate.compiledSchema = compiledSchema;
|
|
1148
2095
|
return validate;
|
|
1149
2096
|
}
|
|
2097
|
+
isPlainObject(value) {
|
|
2098
|
+
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
2099
|
+
}
|
|
2100
|
+
isTrivialAlwaysValidSubschema(value) {
|
|
2101
|
+
return value === true || this.isPlainObject(value) && Object.keys(value).length === 0;
|
|
2102
|
+
}
|
|
2103
|
+
shallowArrayEquals(a, b) {
|
|
2104
|
+
if (a === b) {
|
|
2105
|
+
return true;
|
|
2106
|
+
}
|
|
2107
|
+
if (a.length !== b.length) {
|
|
2108
|
+
return false;
|
|
2109
|
+
}
|
|
2110
|
+
for (let i = 0; i < a.length; i++) {
|
|
2111
|
+
if (a[i] !== b[i]) {
|
|
2112
|
+
return false;
|
|
2113
|
+
}
|
|
2114
|
+
}
|
|
2115
|
+
return true;
|
|
2116
|
+
}
|
|
2117
|
+
flattenAssociativeBranches(key, branches) {
|
|
2118
|
+
const out = [];
|
|
2119
|
+
for (let i = 0; i < branches.length; i++) {
|
|
2120
|
+
const item = branches[i];
|
|
2121
|
+
if (this.isPlainObject(item) && Object.keys(item).length === 1 && Array.isArray(item[key])) {
|
|
2122
|
+
const nested = this.flattenAssociativeBranches(key, item[key]);
|
|
2123
|
+
for (let j = 0; j < nested.length; j++) {
|
|
2124
|
+
out.push(nested[j]);
|
|
2125
|
+
}
|
|
2126
|
+
continue;
|
|
2127
|
+
}
|
|
2128
|
+
out.push(item);
|
|
2129
|
+
}
|
|
2130
|
+
return out;
|
|
2131
|
+
}
|
|
2132
|
+
flattenSingleWrapperOneOf(branches) {
|
|
2133
|
+
let current = branches;
|
|
2134
|
+
while (current.length === 1) {
|
|
2135
|
+
const item = current[0];
|
|
2136
|
+
if (this.isPlainObject(item) && Object.keys(item).length === 1 && Array.isArray(item.oneOf)) {
|
|
2137
|
+
current = item.oneOf;
|
|
2138
|
+
continue;
|
|
2139
|
+
}
|
|
2140
|
+
break;
|
|
2141
|
+
}
|
|
2142
|
+
return current;
|
|
2143
|
+
}
|
|
2144
|
+
normalizeSchemaForCompile(schema) {
|
|
2145
|
+
let normalized = schema;
|
|
2146
|
+
const schemaKeys = Object.keys(schema);
|
|
2147
|
+
const hasOnlyKey = (key) => schemaKeys.length === 1 && schemaKeys[0] === key;
|
|
2148
|
+
const setNormalized = (key, value) => {
|
|
2149
|
+
if (normalized === schema) {
|
|
2150
|
+
normalized = { ...schema };
|
|
2151
|
+
}
|
|
2152
|
+
normalized[key] = value;
|
|
2153
|
+
};
|
|
2154
|
+
if (Array.isArray(schema.allOf)) {
|
|
2155
|
+
const flattenedAllOf = this.flattenAssociativeBranches(
|
|
2156
|
+
"allOf",
|
|
2157
|
+
schema.allOf
|
|
2158
|
+
).filter(
|
|
2159
|
+
(item) => !(this.isPlainObject(item) && Object.keys(item).length === 0)
|
|
2160
|
+
);
|
|
2161
|
+
if (hasOnlyKey("allOf") && flattenedAllOf.length === 1 && this.isPlainObject(flattenedAllOf[0])) {
|
|
2162
|
+
return flattenedAllOf[0];
|
|
2163
|
+
}
|
|
2164
|
+
if (!this.shallowArrayEquals(flattenedAllOf, schema.allOf)) {
|
|
2165
|
+
setNormalized("allOf", flattenedAllOf);
|
|
2166
|
+
}
|
|
2167
|
+
}
|
|
2168
|
+
if (Array.isArray(schema.anyOf)) {
|
|
2169
|
+
const flattenedAnyOf = this.flattenAssociativeBranches(
|
|
2170
|
+
"anyOf",
|
|
2171
|
+
schema.anyOf
|
|
2172
|
+
);
|
|
2173
|
+
if (hasOnlyKey("anyOf") && flattenedAnyOf.length === 1 && this.isPlainObject(flattenedAnyOf[0])) {
|
|
2174
|
+
return flattenedAnyOf[0];
|
|
2175
|
+
}
|
|
2176
|
+
if (!this.shallowArrayEquals(flattenedAnyOf, schema.anyOf)) {
|
|
2177
|
+
setNormalized("anyOf", flattenedAnyOf);
|
|
2178
|
+
}
|
|
2179
|
+
}
|
|
2180
|
+
if (Array.isArray(schema.oneOf)) {
|
|
2181
|
+
const flattenedOneOf = this.flattenSingleWrapperOneOf(schema.oneOf);
|
|
2182
|
+
if (hasOnlyKey("oneOf") && flattenedOneOf.length === 1 && this.isPlainObject(flattenedOneOf[0])) {
|
|
2183
|
+
return flattenedOneOf[0];
|
|
2184
|
+
}
|
|
2185
|
+
if (!this.shallowArrayEquals(flattenedOneOf, schema.oneOf)) {
|
|
2186
|
+
setNormalized("oneOf", flattenedOneOf);
|
|
2187
|
+
}
|
|
2188
|
+
}
|
|
2189
|
+
return normalized;
|
|
2190
|
+
}
|
|
2191
|
+
markSchemaHasRef(schema) {
|
|
2192
|
+
if (schema._hasRef === true) {
|
|
2193
|
+
return;
|
|
2194
|
+
}
|
|
2195
|
+
Object.defineProperty(schema, "_hasRef", {
|
|
2196
|
+
value: true,
|
|
2197
|
+
enumerable: false,
|
|
2198
|
+
configurable: false,
|
|
2199
|
+
writable: false
|
|
2200
|
+
});
|
|
2201
|
+
}
|
|
2202
|
+
shouldSkipKeyword(schema, key) {
|
|
2203
|
+
const value = schema[key];
|
|
2204
|
+
switch (key) {
|
|
2205
|
+
case "required":
|
|
2206
|
+
return Array.isArray(value) && value.length === 0;
|
|
2207
|
+
case "uniqueItems":
|
|
2208
|
+
return value === false;
|
|
2209
|
+
case "properties":
|
|
2210
|
+
case "patternProperties":
|
|
2211
|
+
case "dependencies":
|
|
2212
|
+
return this.isPlainObject(value) && Object.keys(value).length === 0;
|
|
2213
|
+
case "propertyNames":
|
|
2214
|
+
case "items":
|
|
2215
|
+
return value === true;
|
|
2216
|
+
case "additionalProperties":
|
|
2217
|
+
if (value === true) {
|
|
2218
|
+
return true;
|
|
2219
|
+
}
|
|
2220
|
+
return value === false && this.isPlainObject(schema.patternProperties) && Object.keys(schema.patternProperties).length > 0;
|
|
2221
|
+
case "additionalItems":
|
|
2222
|
+
return value === true || !Array.isArray(schema.items);
|
|
2223
|
+
case "allOf": {
|
|
2224
|
+
if (!Array.isArray(value)) {
|
|
2225
|
+
return false;
|
|
2226
|
+
}
|
|
2227
|
+
if (value.length === 0) {
|
|
2228
|
+
return true;
|
|
2229
|
+
}
|
|
2230
|
+
for (let i = 0; i < value.length; i++) {
|
|
2231
|
+
if (this.isTrivialAlwaysValidSubschema(value[i])) {
|
|
2232
|
+
continue;
|
|
2233
|
+
}
|
|
2234
|
+
return false;
|
|
2235
|
+
}
|
|
2236
|
+
return true;
|
|
2237
|
+
}
|
|
2238
|
+
case "anyOf": {
|
|
2239
|
+
if (!Array.isArray(value)) {
|
|
2240
|
+
return false;
|
|
2241
|
+
}
|
|
2242
|
+
for (let i = 0; i < value.length; i++) {
|
|
2243
|
+
if (this.isTrivialAlwaysValidSubschema(value[i])) {
|
|
2244
|
+
return true;
|
|
2245
|
+
}
|
|
2246
|
+
}
|
|
2247
|
+
return false;
|
|
2248
|
+
}
|
|
2249
|
+
default:
|
|
2250
|
+
return false;
|
|
2251
|
+
}
|
|
2252
|
+
}
|
|
2253
|
+
hasRequiredDefaults(schema) {
|
|
2254
|
+
const properties = schema.properties;
|
|
2255
|
+
if (!this.isPlainObject(properties)) {
|
|
2256
|
+
return false;
|
|
2257
|
+
}
|
|
2258
|
+
const keys = Object.keys(properties);
|
|
2259
|
+
for (let i = 0; i < keys.length; i++) {
|
|
2260
|
+
const subSchema = properties[keys[i]];
|
|
2261
|
+
if (this.isPlainObject(subSchema) && "default" in subSchema) {
|
|
2262
|
+
return true;
|
|
2263
|
+
}
|
|
2264
|
+
}
|
|
2265
|
+
return false;
|
|
2266
|
+
}
|
|
2267
|
+
isDefaultTypeValidator(type, validator) {
|
|
2268
|
+
return Types[type] === validator;
|
|
2269
|
+
}
|
|
1150
2270
|
compileSchema(schema) {
|
|
1151
|
-
if (!
|
|
2271
|
+
if (!schema || typeof schema !== "object" || Array.isArray(schema)) {
|
|
1152
2272
|
if (schema === true) {
|
|
1153
|
-
schema = {
|
|
1154
|
-
anyOf: [{}]
|
|
1155
|
-
};
|
|
2273
|
+
schema = { anyOf: [{}] };
|
|
1156
2274
|
} else if (schema === false) {
|
|
1157
|
-
schema = {
|
|
1158
|
-
oneOf: []
|
|
1159
|
-
};
|
|
2275
|
+
schema = { oneOf: [] };
|
|
1160
2276
|
} else {
|
|
1161
|
-
schema = {
|
|
1162
|
-
oneOf: [schema]
|
|
1163
|
-
};
|
|
2277
|
+
schema = { oneOf: [schema] };
|
|
1164
2278
|
}
|
|
1165
2279
|
}
|
|
1166
|
-
|
|
1167
|
-
const
|
|
1168
|
-
|
|
1169
|
-
|
|
2280
|
+
schema = this.normalizeSchemaForCompile(schema);
|
|
2281
|
+
const compiledSchema = deepCloneUnfreeze(
|
|
2282
|
+
schema
|
|
2283
|
+
);
|
|
2284
|
+
let schemaHasRef = false;
|
|
2285
|
+
if (typeof schema.$id === "string") {
|
|
2286
|
+
this.idRegistry.set(schema.$id, compiledSchema);
|
|
2287
|
+
}
|
|
2288
|
+
if ("$ref" in schema) {
|
|
2289
|
+
schemaHasRef = true;
|
|
2290
|
+
const refValidator = this.getKeyword("$ref");
|
|
2291
|
+
if (refValidator) {
|
|
2292
|
+
const defineError = getDefinedErrorFunctionForKey(
|
|
2293
|
+
"$ref",
|
|
2294
|
+
schema["$ref"],
|
|
2295
|
+
this.failFast
|
|
2296
|
+
);
|
|
2297
|
+
compiledSchema.$validate = getNamedFunction(
|
|
2298
|
+
"Validate_Reference",
|
|
2299
|
+
(data) => refValidator(
|
|
2300
|
+
compiledSchema,
|
|
2301
|
+
data,
|
|
2302
|
+
defineError,
|
|
2303
|
+
this
|
|
2304
|
+
)
|
|
2305
|
+
);
|
|
2306
|
+
}
|
|
2307
|
+
this.markSchemaHasRef(compiledSchema);
|
|
2308
|
+
return compiledSchema;
|
|
2309
|
+
}
|
|
2310
|
+
const validators = [];
|
|
2311
|
+
const activeNames = [];
|
|
1170
2312
|
if ("type" in schema) {
|
|
2313
|
+
const defineTypeError = getDefinedErrorFunctionForKey(
|
|
2314
|
+
"type",
|
|
2315
|
+
schema,
|
|
2316
|
+
this.failFast
|
|
2317
|
+
);
|
|
1171
2318
|
const types = Array.isArray(schema.type) ? schema.type : schema.type.split(",").map((t) => t.trim());
|
|
1172
|
-
|
|
1173
|
-
|
|
2319
|
+
const typeFunctions = [];
|
|
2320
|
+
const typeNames = [];
|
|
2321
|
+
const defaultTypeNames = [];
|
|
2322
|
+
let allTypesDefault = true;
|
|
2323
|
+
for (const type2 of types) {
|
|
2324
|
+
const validator = this.getType(type2);
|
|
1174
2325
|
if (validator) {
|
|
1175
|
-
|
|
1176
|
-
|
|
2326
|
+
typeFunctions.push(validator);
|
|
2327
|
+
typeNames.push(validator.name);
|
|
2328
|
+
if (this.isDefaultTypeValidator(type2, validator)) {
|
|
2329
|
+
defaultTypeNames.push(type2);
|
|
2330
|
+
} else {
|
|
2331
|
+
allTypesDefault = false;
|
|
2332
|
+
}
|
|
1177
2333
|
}
|
|
1178
2334
|
}
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
2335
|
+
if (typeFunctions.length === 0) {
|
|
2336
|
+
throw getDefinedErrorFunctionForKey(
|
|
2337
|
+
"type",
|
|
2338
|
+
schema,
|
|
2339
|
+
this.failFast
|
|
2340
|
+
)("Invalid type for schema", { data: schema.type });
|
|
2341
|
+
}
|
|
2342
|
+
let combinedTypeValidator;
|
|
2343
|
+
let typeMethodName = "";
|
|
2344
|
+
if (typeFunctions.length === 1 && allTypesDefault) {
|
|
2345
|
+
const singleTypeName = defaultTypeNames[0];
|
|
2346
|
+
typeMethodName = singleTypeName;
|
|
2347
|
+
switch (singleTypeName) {
|
|
2348
|
+
case "object":
|
|
2349
|
+
combinedTypeValidator = (data) => {
|
|
2350
|
+
if (data === null || typeof data !== "object" || Array.isArray(data)) {
|
|
2351
|
+
return defineTypeError("Invalid type", { data });
|
|
2352
|
+
}
|
|
2353
|
+
};
|
|
2354
|
+
break;
|
|
2355
|
+
case "array":
|
|
2356
|
+
combinedTypeValidator = (data) => {
|
|
2357
|
+
if (!Array.isArray(data)) {
|
|
2358
|
+
return defineTypeError("Invalid type", { data });
|
|
2359
|
+
}
|
|
2360
|
+
};
|
|
2361
|
+
break;
|
|
2362
|
+
case "string":
|
|
2363
|
+
combinedTypeValidator = (data) => {
|
|
2364
|
+
if (typeof data !== "string") {
|
|
2365
|
+
return defineTypeError("Invalid type", { data });
|
|
2366
|
+
}
|
|
2367
|
+
};
|
|
2368
|
+
break;
|
|
2369
|
+
case "number":
|
|
2370
|
+
combinedTypeValidator = (data) => {
|
|
2371
|
+
if (typeof data !== "number") {
|
|
2372
|
+
return defineTypeError("Invalid type", { data });
|
|
2373
|
+
}
|
|
2374
|
+
};
|
|
2375
|
+
break;
|
|
2376
|
+
case "integer":
|
|
2377
|
+
combinedTypeValidator = (data) => {
|
|
2378
|
+
if (typeof data !== "number" || !Number.isInteger(data)) {
|
|
2379
|
+
return defineTypeError("Invalid type", { data });
|
|
2380
|
+
}
|
|
2381
|
+
};
|
|
2382
|
+
break;
|
|
2383
|
+
case "boolean":
|
|
2384
|
+
combinedTypeValidator = (data) => {
|
|
2385
|
+
if (typeof data !== "boolean") {
|
|
2386
|
+
return defineTypeError("Invalid type", { data });
|
|
2387
|
+
}
|
|
2388
|
+
};
|
|
2389
|
+
break;
|
|
2390
|
+
case "null":
|
|
2391
|
+
combinedTypeValidator = (data) => {
|
|
2392
|
+
if (data !== null) {
|
|
2393
|
+
return defineTypeError("Invalid type", { data });
|
|
2394
|
+
}
|
|
2395
|
+
};
|
|
2396
|
+
break;
|
|
2397
|
+
default: {
|
|
2398
|
+
const singleTypeFn = typeFunctions[0];
|
|
2399
|
+
combinedTypeValidator = (data) => {
|
|
2400
|
+
if (!singleTypeFn(data)) {
|
|
2401
|
+
return defineTypeError("Invalid type", { data });
|
|
2402
|
+
}
|
|
2403
|
+
};
|
|
2404
|
+
}
|
|
2405
|
+
}
|
|
2406
|
+
} else if (typeFunctions.length > 1 && allTypesDefault) {
|
|
2407
|
+
typeMethodName = defaultTypeNames.join("_OR_");
|
|
2408
|
+
const allowsObject = defaultTypeNames.includes("object");
|
|
2409
|
+
const allowsArray = defaultTypeNames.includes("array");
|
|
2410
|
+
const allowsString = defaultTypeNames.includes("string");
|
|
2411
|
+
const allowsNumber = defaultTypeNames.includes("number");
|
|
2412
|
+
const allowsInteger = defaultTypeNames.includes("integer");
|
|
2413
|
+
const allowsBoolean = defaultTypeNames.includes("boolean");
|
|
2414
|
+
const allowsNull = defaultTypeNames.includes("null");
|
|
2415
|
+
combinedTypeValidator = (data) => {
|
|
2416
|
+
const dataType = typeof data;
|
|
2417
|
+
if (dataType === "number") {
|
|
2418
|
+
if (allowsNumber || allowsInteger && Number.isInteger(data)) {
|
|
2419
|
+
return;
|
|
1190
2420
|
}
|
|
2421
|
+
return defineTypeError("Invalid type", { data });
|
|
1191
2422
|
}
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
2423
|
+
if (dataType === "string") {
|
|
2424
|
+
if (allowsString) {
|
|
2425
|
+
return;
|
|
2426
|
+
}
|
|
2427
|
+
return defineTypeError("Invalid type", { data });
|
|
2428
|
+
}
|
|
2429
|
+
if (dataType === "boolean") {
|
|
2430
|
+
if (allowsBoolean) {
|
|
2431
|
+
return;
|
|
2432
|
+
}
|
|
2433
|
+
return defineTypeError("Invalid type", { data });
|
|
2434
|
+
}
|
|
2435
|
+
if (dataType === "object") {
|
|
2436
|
+
if (data === null) {
|
|
2437
|
+
if (allowsNull) {
|
|
2438
|
+
return;
|
|
2439
|
+
}
|
|
2440
|
+
return defineTypeError("Invalid type", { data });
|
|
2441
|
+
}
|
|
2442
|
+
if (Array.isArray(data)) {
|
|
2443
|
+
if (allowsArray) {
|
|
1199
2444
|
return;
|
|
1200
2445
|
}
|
|
2446
|
+
return defineTypeError("Invalid type", { data });
|
|
2447
|
+
}
|
|
2448
|
+
if (allowsObject) {
|
|
2449
|
+
return;
|
|
1201
2450
|
}
|
|
1202
2451
|
return defineTypeError("Invalid type", { data });
|
|
1203
2452
|
}
|
|
1204
|
-
|
|
2453
|
+
return defineTypeError("Invalid type", { data });
|
|
2454
|
+
};
|
|
2455
|
+
} else if (typeFunctions.length === 1) {
|
|
2456
|
+
typeMethodName = typeNames[0];
|
|
2457
|
+
const singleTypeFn = typeFunctions[0];
|
|
2458
|
+
combinedTypeValidator = (data) => {
|
|
2459
|
+
if (!singleTypeFn(data)) {
|
|
2460
|
+
return defineTypeError("Invalid type", { data });
|
|
2461
|
+
}
|
|
2462
|
+
};
|
|
2463
|
+
} else {
|
|
2464
|
+
typeMethodName = typeNames.join("_OR_");
|
|
2465
|
+
combinedTypeValidator = (data) => {
|
|
2466
|
+
for (let i = 0; i < typeFunctions.length; i++) {
|
|
2467
|
+
if (typeFunctions[i](data)) {
|
|
2468
|
+
return;
|
|
2469
|
+
}
|
|
2470
|
+
}
|
|
2471
|
+
return defineTypeError("Invalid type", { data });
|
|
2472
|
+
};
|
|
1205
2473
|
}
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
2474
|
+
validators.push({
|
|
2475
|
+
name: typeMethodName,
|
|
2476
|
+
validate: getNamedFunction(typeMethodName, combinedTypeValidator)
|
|
2477
|
+
});
|
|
2478
|
+
activeNames.push(typeMethodName);
|
|
2479
|
+
}
|
|
2480
|
+
const { type, $id, $ref, $validate, required, ...otherKeys } = schema;
|
|
2481
|
+
const keyOrder = required ? this.hasRequiredDefaults(schema) ? [...Object.keys(otherKeys), "required"] : ["required", ...Object.keys(otherKeys)] : Object.keys(otherKeys);
|
|
2482
|
+
for (const key of keyOrder) {
|
|
2483
|
+
const keywordFn = this.getKeyword(key);
|
|
2484
|
+
if (!keywordFn) {
|
|
1210
2485
|
continue;
|
|
1211
2486
|
}
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
methodName = keywordValidator.name;
|
|
1235
|
-
compiledSchema.$validate = getNamedFunction(
|
|
1236
|
-
methodName,
|
|
1237
|
-
(data) => keywordValidator(
|
|
1238
|
-
compiledSchema,
|
|
1239
|
-
data,
|
|
1240
|
-
defineError,
|
|
1241
|
-
this
|
|
1242
|
-
)
|
|
1243
|
-
);
|
|
1244
|
-
}
|
|
2487
|
+
if (this.shouldSkipKeyword(schema, key)) {
|
|
2488
|
+
continue;
|
|
2489
|
+
}
|
|
2490
|
+
const defineError = getDefinedErrorFunctionForKey(
|
|
2491
|
+
key,
|
|
2492
|
+
schema[key],
|
|
2493
|
+
this.failFast
|
|
2494
|
+
);
|
|
2495
|
+
const fnName = keywordFn.name || key;
|
|
2496
|
+
validators.push({
|
|
2497
|
+
name: fnName,
|
|
2498
|
+
validate: getNamedFunction(
|
|
2499
|
+
fnName,
|
|
2500
|
+
(data) => keywordFn(compiledSchema, data, defineError, this)
|
|
2501
|
+
)
|
|
2502
|
+
});
|
|
2503
|
+
activeNames.push(fnName);
|
|
2504
|
+
}
|
|
2505
|
+
const literalKeywords = ["enum", "const", "default", "examples"];
|
|
2506
|
+
for (const key of keyOrder) {
|
|
2507
|
+
if (literalKeywords.includes(key)) {
|
|
2508
|
+
continue;
|
|
1245
2509
|
}
|
|
1246
|
-
if (
|
|
2510
|
+
if (schema[key] && typeof schema[key] === "object" && !Array.isArray(schema[key])) {
|
|
1247
2511
|
if (key === "properties") {
|
|
1248
2512
|
for (const subKey of Object.keys(schema[key])) {
|
|
1249
|
-
|
|
2513
|
+
const compiledSubSchema2 = this.compileSchema(
|
|
1250
2514
|
schema[key][subKey]
|
|
1251
2515
|
);
|
|
2516
|
+
if (compiledSubSchema2._hasRef === true) {
|
|
2517
|
+
schemaHasRef = true;
|
|
2518
|
+
}
|
|
2519
|
+
compiledSchema[key][subKey] = compiledSubSchema2;
|
|
1252
2520
|
}
|
|
1253
2521
|
continue;
|
|
1254
2522
|
}
|
|
1255
|
-
|
|
2523
|
+
const compiledSubSchema = this.compileSchema(schema[key]);
|
|
2524
|
+
if (compiledSubSchema._hasRef === true) {
|
|
2525
|
+
schemaHasRef = true;
|
|
2526
|
+
}
|
|
2527
|
+
compiledSchema[key] = compiledSubSchema;
|
|
1256
2528
|
continue;
|
|
1257
2529
|
}
|
|
1258
2530
|
if (Array.isArray(schema[key])) {
|
|
1259
|
-
|
|
1260
|
-
(
|
|
1261
|
-
|
|
2531
|
+
for (let i = 0; i < schema[key].length; i++) {
|
|
2532
|
+
if (this.isSchemaLike(schema[key][i])) {
|
|
2533
|
+
const compiledSubSchema = this.compileSchema(schema[key][i]);
|
|
2534
|
+
if (compiledSubSchema._hasRef === true) {
|
|
2535
|
+
schemaHasRef = true;
|
|
2536
|
+
}
|
|
2537
|
+
compiledSchema[key][i] = compiledSubSchema;
|
|
2538
|
+
}
|
|
2539
|
+
}
|
|
1262
2540
|
continue;
|
|
1263
2541
|
}
|
|
1264
|
-
|
|
2542
|
+
}
|
|
2543
|
+
if (schemaHasRef) {
|
|
2544
|
+
this.markSchemaHasRef(compiledSchema);
|
|
2545
|
+
}
|
|
2546
|
+
if (validators.length === 0) {
|
|
2547
|
+
return compiledSchema;
|
|
2548
|
+
}
|
|
2549
|
+
if (validators.length === 1) {
|
|
2550
|
+
const v = validators[0];
|
|
2551
|
+
compiledSchema.$validate = getNamedFunction(v.name, v.validate);
|
|
2552
|
+
} else {
|
|
2553
|
+
const compositeName = "Validate_" + activeNames.join("_AND_");
|
|
2554
|
+
const masterValidator = (data) => {
|
|
2555
|
+
for (let i = 0; i < validators.length; i++) {
|
|
2556
|
+
const v = validators[i];
|
|
2557
|
+
const error = v.validate(data);
|
|
2558
|
+
if (error) {
|
|
2559
|
+
return error;
|
|
2560
|
+
}
|
|
2561
|
+
}
|
|
2562
|
+
return;
|
|
2563
|
+
};
|
|
2564
|
+
compiledSchema.$validate = getNamedFunction(
|
|
2565
|
+
compositeName,
|
|
2566
|
+
masterValidator
|
|
2567
|
+
);
|
|
1265
2568
|
}
|
|
1266
2569
|
return compiledSchema;
|
|
1267
2570
|
}
|
|
1268
2571
|
isSchemaLike(subSchema) {
|
|
1269
|
-
if (
|
|
2572
|
+
if (subSchema && typeof subSchema === "object" && !Array.isArray(subSchema)) {
|
|
1270
2573
|
if ("type" in subSchema) {
|
|
1271
2574
|
return true;
|
|
1272
2575
|
}
|
|
@@ -1278,4 +2581,54 @@ var SchemaShield = class {
|
|
|
1278
2581
|
}
|
|
1279
2582
|
return false;
|
|
1280
2583
|
}
|
|
2584
|
+
linkReferences(root) {
|
|
2585
|
+
const stack = [root];
|
|
2586
|
+
while (stack.length > 0) {
|
|
2587
|
+
const node = stack.pop();
|
|
2588
|
+
if (!node || typeof node !== "object")
|
|
2589
|
+
continue;
|
|
2590
|
+
if (typeof node.$ref === "string" && typeof node.$validate === "function" && node.$validate.name === "Validate_Reference") {
|
|
2591
|
+
const refPath = node.$ref;
|
|
2592
|
+
let target = this.getSchemaRef(refPath);
|
|
2593
|
+
if (typeof target === "undefined") {
|
|
2594
|
+
target = this.getSchemaById(refPath);
|
|
2595
|
+
}
|
|
2596
|
+
if (typeof target === "boolean") {
|
|
2597
|
+
if (target === true) {
|
|
2598
|
+
node.$validate = getNamedFunction("Validate_Ref_True", () => {
|
|
2599
|
+
});
|
|
2600
|
+
} else {
|
|
2601
|
+
const defineError = getDefinedErrorFunctionForKey(
|
|
2602
|
+
"$ref",
|
|
2603
|
+
node,
|
|
2604
|
+
this.failFast
|
|
2605
|
+
);
|
|
2606
|
+
node.$validate = getNamedFunction(
|
|
2607
|
+
"Validate_Ref_False",
|
|
2608
|
+
(_data) => defineError("Value is not valid")
|
|
2609
|
+
);
|
|
2610
|
+
}
|
|
2611
|
+
continue;
|
|
2612
|
+
}
|
|
2613
|
+
if (target && typeof target.$validate === "function") {
|
|
2614
|
+
node.$validate = target.$validate;
|
|
2615
|
+
}
|
|
2616
|
+
}
|
|
2617
|
+
for (const key in node) {
|
|
2618
|
+
const value = node[key];
|
|
2619
|
+
if (!value)
|
|
2620
|
+
continue;
|
|
2621
|
+
if (Array.isArray(value)) {
|
|
2622
|
+
for (let i = 0; i < value.length; i++) {
|
|
2623
|
+
const v = value[i];
|
|
2624
|
+
if (v && typeof v === "object") {
|
|
2625
|
+
stack.push(v);
|
|
2626
|
+
}
|
|
2627
|
+
}
|
|
2628
|
+
} else if (typeof value === "object") {
|
|
2629
|
+
stack.push(value);
|
|
2630
|
+
}
|
|
2631
|
+
}
|
|
2632
|
+
}
|
|
2633
|
+
}
|
|
1281
2634
|
};
|