schema-shield 1.0.0 → 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.
Files changed (39) hide show
  1. package/README.md +38 -12
  2. package/dist/formats.d.ts.map +1 -1
  3. package/dist/index.d.ts +14 -3
  4. package/dist/index.d.ts.map +1 -1
  5. package/dist/index.js +1445 -447
  6. package/dist/index.min.js +1 -1
  7. package/dist/index.min.js.map +1 -1
  8. package/dist/index.mjs +1445 -447
  9. package/dist/keywords/array-keywords.d.ts.map +1 -1
  10. package/dist/keywords/object-keywords.d.ts.map +1 -1
  11. package/dist/keywords/other-keywords.d.ts.map +1 -1
  12. package/dist/keywords/string-keywords.d.ts.map +1 -1
  13. package/dist/types.d.ts.map +1 -1
  14. package/dist/utils/deep-freeze.d.ts +5 -0
  15. package/dist/utils/deep-freeze.d.ts.map +1 -0
  16. package/dist/utils/has-changed.d.ts +2 -0
  17. package/dist/utils/has-changed.d.ts.map +1 -0
  18. package/dist/utils/index.d.ts +5 -0
  19. package/dist/utils/index.d.ts.map +1 -0
  20. package/dist/{utils.d.ts → utils/main-utils.d.ts} +3 -6
  21. package/dist/utils/main-utils.d.ts.map +1 -0
  22. package/dist/utils/pattern-matcher.d.ts +3 -0
  23. package/dist/utils/pattern-matcher.d.ts.map +1 -0
  24. package/lib/formats.ts +402 -84
  25. package/lib/index.ts +494 -46
  26. package/lib/keywords/array-keywords.ts +215 -21
  27. package/lib/keywords/number-keywords.ts +1 -1
  28. package/lib/keywords/object-keywords.ts +218 -113
  29. package/lib/keywords/other-keywords.ts +229 -76
  30. package/lib/keywords/string-keywords.ts +97 -7
  31. package/lib/types.ts +4 -5
  32. package/lib/utils/deep-freeze.ts +208 -0
  33. package/lib/utils/has-changed.ts +51 -0
  34. package/lib/utils/index.ts +4 -0
  35. package/lib/utils/main-utils.ts +190 -0
  36. package/lib/utils/pattern-matcher.ts +66 -0
  37. package/package.json +1 -1
  38. package/dist/utils.d.ts.map +0 -1
  39. package/lib/utils.ts +0 -362
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: () => 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;
@@ -100,158 +100,8 @@ function getDefinedErrorFunctionForKey(key, schema, failFast) {
100
100
  defineError
101
101
  );
102
102
  }
103
- function hasChanged(prev, current) {
104
- if (Array.isArray(prev)) {
105
- if (Array.isArray(current) === false) {
106
- return true;
107
- }
108
- if (prev.length !== current.length) {
109
- return true;
110
- }
111
- for (let i = 0; i < current.length; i++) {
112
- if (hasChanged(prev[i], current[i])) {
113
- return true;
114
- }
115
- }
116
- return false;
117
- }
118
- if (typeof prev === "object" && prev !== null) {
119
- if (typeof current !== "object" || current === null) {
120
- return true;
121
- }
122
- for (const key in current) {
123
- if (hasChanged(prev[key], current[key])) {
124
- return true;
125
- }
126
- }
127
- for (const key in prev) {
128
- if (hasChanged(prev[key], current[key])) {
129
- return true;
130
- }
131
- }
132
- return false;
133
- }
134
- return Object.is(prev, current) === false;
135
- }
136
- function isObject(data) {
137
- return typeof data === "object" && data !== null && !Array.isArray(data);
138
- }
139
- function areCloseEnough(a, b, epsilon = 1e-15) {
140
- return Math.abs(a - b) <= epsilon * Math.max(Math.abs(a), Math.abs(b));
141
- }
142
- function deepClone(obj, cloneClassInstances = false, seen = /* @__PURE__ */ new WeakMap()) {
143
- if (typeof obj === "undefined" || obj === null || typeof obj !== "object") {
144
- return obj;
145
- }
146
- if (seen.has(obj)) {
147
- return seen.get(obj);
148
- }
149
- let clone;
150
- if (typeof structuredClone === "function") {
151
- clone = structuredClone(obj);
152
- seen.set(obj, clone);
153
- return clone;
154
- }
155
- switch (true) {
156
- case Array.isArray(obj): {
157
- clone = [];
158
- seen.set(obj, clone);
159
- for (let i = 0, l = obj.length; i < l; i++) {
160
- clone[i] = deepClone(obj[i], cloneClassInstances, seen);
161
- }
162
- return clone;
163
- }
164
- case obj instanceof Date: {
165
- clone = new Date(obj.getTime());
166
- seen.set(obj, clone);
167
- return clone;
168
- }
169
- case obj instanceof RegExp: {
170
- clone = new RegExp(obj.source, obj.flags);
171
- seen.set(obj, clone);
172
- return clone;
173
- }
174
- case obj instanceof Map: {
175
- clone = /* @__PURE__ */ new Map();
176
- seen.set(obj, clone);
177
- for (const [key, value] of obj.entries()) {
178
- clone.set(
179
- deepClone(key, cloneClassInstances, seen),
180
- deepClone(value, cloneClassInstances, seen)
181
- );
182
- }
183
- return clone;
184
- }
185
- case obj instanceof Set: {
186
- clone = /* @__PURE__ */ new Set();
187
- seen.set(obj, clone);
188
- for (const value of obj.values()) {
189
- clone.add(deepClone(value, cloneClassInstances, seen));
190
- }
191
- return clone;
192
- }
193
- case obj instanceof ArrayBuffer: {
194
- clone = obj.slice(0);
195
- seen.set(obj, clone);
196
- return clone;
197
- }
198
- case ArrayBuffer.isView(obj): {
199
- clone = new obj.constructor(obj.buffer.slice(0));
200
- seen.set(obj, clone);
201
- return clone;
202
- }
203
- case (typeof Buffer !== "undefined" && obj instanceof Buffer): {
204
- clone = Buffer.from(obj);
205
- seen.set(obj, clone);
206
- return clone;
207
- }
208
- case obj instanceof Error: {
209
- clone = new obj.constructor(obj.message);
210
- seen.set(obj, clone);
211
- break;
212
- }
213
- case (obj instanceof Promise || obj instanceof WeakMap || obj instanceof WeakSet): {
214
- clone = obj;
215
- seen.set(obj, clone);
216
- return clone;
217
- }
218
- case (obj.constructor && obj.constructor !== Object): {
219
- if (!cloneClassInstances) {
220
- clone = obj;
221
- seen.set(obj, clone);
222
- return clone;
223
- }
224
- clone = Object.create(Object.getPrototypeOf(obj));
225
- seen.set(obj, clone);
226
- break;
227
- }
228
- default: {
229
- clone = {};
230
- seen.set(obj, clone);
231
- const keys = Reflect.ownKeys(obj);
232
- for (let i = 0, l = keys.length; i < l; i++) {
233
- const key = keys[i];
234
- clone[key] = deepClone(
235
- obj[key],
236
- cloneClassInstances,
237
- seen
238
- );
239
- }
240
- return clone;
241
- }
242
- }
243
- const descriptors = Object.getOwnPropertyDescriptors(obj);
244
- for (const key of Reflect.ownKeys(descriptors)) {
245
- const descriptor = descriptors[key];
246
- if ("value" in descriptor) {
247
- descriptor.value = deepClone(descriptor.value, cloneClassInstances, seen);
248
- }
249
- Object.defineProperty(clone, key, descriptor);
250
- }
251
- return clone;
252
- }
253
103
  function isCompiledSchema(subSchema) {
254
- return isObject(subSchema) && "$validate" in subSchema;
104
+ return !!subSchema && typeof subSchema === "object" && !Array.isArray(subSchema) && "$validate" in subSchema;
255
105
  }
256
106
  function getNamedFunction(name, fn) {
257
107
  return Object.defineProperty(fn, "name", { value: name });
@@ -289,45 +139,297 @@ function resolvePath(root, path) {
289
139
  }
290
140
  return;
291
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
+ }
292
145
 
293
146
  // lib/formats.ts
294
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;
295
148
  var DURATION_REGEX = /^P(?!$)((\d+Y)?(\d+M)?(\d+W)?(\d+D)?)(T(?=\d)(\d+H)?(\d+M)?(\d+S)?)?$/;
296
- var DATE_TIME_REGEX = /^(\d{4})-(0[0-9]|1[0-2])-(\d{2})T(0[0-9]|1\d|2[0-3]):([0-5]\d):((?:[0-5]\d|60))(?:.\d+)?(?:([+-])(0[0-9]|1\d|2[0-3]):([0-5]\d)|Z)?$/i;
297
149
  var URI_REGEX = /^[a-zA-Z][a-zA-Z0-9+\-.]*:[^\s]*$/;
298
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;
299
- var IPV4_REGEX = /^(?:(?: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])$/;
300
- var IPV6_REGEX = /(?:\s+|:::+|^\w{5,}|\w{5}$|^:{1}\w|\w:{1}$)/;
301
- var IPV6_SHORT_REGEX = /^[0-9a-fA-F:.]*$/;
302
- var IPV6_FULL_REGEX = /^(?:(?:[0-9a-fA-F]{1,4}:){7}(?:[0-9a-fA-F]{1,4}|:))$/;
303
- var IPV6_INVALID_CHAR_REGEX = /(?:[0-9a-fA-F]{5,}|\D[0-9a-fA-F]{3}:)/;
304
- var IPV6_FAST_FAIL_REGEX = /^(?:(?:(?:[0-9a-fA-F]{1,4}(?::|$)){1,6}))|(?:::(?:[0-9a-fA-F]{1,4})){0,5}$/;
305
151
  var HOSTNAME_REGEX = /^[a-z0-9][a-z0-9-]{0,62}(?:\.[a-z0-9][a-z0-9-]{0,62})*[a-z0-9]$/i;
306
152
  var DATE_REGEX = /^(\d{4})-(\d{2})-(\d{2})$/;
307
- var JSON_POINTER_REGEX = /^\/(?:[^~]|~0|~1)*$/;
308
- var RELATIVE_JSON_POINTER_REGEX = /^([0-9]+)(#|\/(?:[^~]|~0|~1)*)?$/;
309
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))$/;
310
154
  var URI_REFERENCE_REGEX = /^(([^:/?#]+):)?(\/\/([^/?#]*))?([^?#]*)(\?([^#]*))?(#((?![^#]*\\)[^#]*))?/i;
311
- var URI_TEMPLATE_REGEX = /^(?:[^{}]|\{[^}]+\})*$/;
312
155
  var IRI_REGEX = /^[a-zA-Z][a-zA-Z0-9+\-.]*:[^\s]*$/;
313
156
  var IRI_REFERENCE_REGEX = /^(([^:/?#]+):)?(\/\/([^/?#]*))?([^?#]*)(\?([^#]*))?(#((?![^#]*\\)[^#]*))?/i;
314
157
  var IDN_EMAIL_REGEX = /^[^@\s]+@[^@\s]+\.[^@\s]+$/;
315
158
  var IDN_HOSTNAME_REGEX = /^[^\s!@#$%^&*()_+\=\[\]{};':"\\|,<>\/?]+$/;
316
- var BACK_SLASH_REGEX = /\\/;
317
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;
191
+ }
192
+ if (segmentLength > 1 && data.charCodeAt(segmentStart) === 48) {
193
+ return false;
194
+ }
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) {
199
+ return false;
200
+ }
201
+ value = value * 10 + digit;
202
+ }
203
+ if (value > 255) {
204
+ return false;
205
+ }
206
+ segmentCount++;
207
+ segmentStart = i + 1;
208
+ }
209
+ return segmentCount === 4;
210
+ }
211
+ function isValidIpv4(data) {
212
+ return isValidIpv4Range(data, 0, data.length);
213
+ }
214
+ function isHexCharCode(code) {
215
+ return code >= 48 && code <= 57 || code >= 65 && code <= 70 || code >= 97 && code <= 102;
216
+ }
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
+ }
290
+ }
291
+ }
292
+ if (!hasColon) {
293
+ return false;
294
+ }
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;
314
+ }
315
+ i++;
316
+ }
317
+ return true;
318
+ }
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;
354
+ }
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;
371
+ }
318
372
  var Formats = {
319
373
  ["date-time"](data) {
320
- const match = data.match(DATE_TIME_REGEX);
321
- if (!match) {
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) {
383
+ return false;
384
+ }
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) {
392
+ return false;
393
+ }
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 {
427
+ return false;
428
+ }
429
+ }
430
+ if (cursor !== length) {
322
431
  return false;
323
432
  }
324
- const [, yearStr, monthStr, dayStr, hourStr, minuteStr, secondStr] = match;
325
- const year = Number(yearStr);
326
- const month = Number(monthStr);
327
- const day = Number(dayStr);
328
- const hour = Number(hourStr);
329
- const minute = Number(minuteStr);
330
- const second = Number(secondStr);
331
433
  if (month < 1 || month > 12) {
332
434
  return false;
333
435
  }
@@ -338,8 +440,19 @@ var Formats = {
338
440
  if (!maxDays || day > maxDays) {
339
441
  return false;
340
442
  }
341
- if (second === 60 && (minute !== 59 || hour !== 23)) {
342
- return false;
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
+ }
343
456
  }
344
457
  return true;
345
458
  },
@@ -350,42 +463,10 @@ var Formats = {
350
463
  return EMAIL_REGEX.test(data);
351
464
  },
352
465
  ipv4(data) {
353
- return IPV4_REGEX.test(data);
466
+ return isValidIpv4(data);
354
467
  },
355
- // ipv6: isMyIpValid({ version: 6 }),
356
468
  ipv6(data) {
357
- if (data === "::") {
358
- return true;
359
- }
360
- if (data.indexOf(":") === -1 || IPV6_REGEX.test(data)) {
361
- return false;
362
- }
363
- const hasIpv4 = data.indexOf(".") !== -1;
364
- let addressParts = data;
365
- if (hasIpv4) {
366
- addressParts = data.split(":");
367
- const ipv4Part = addressParts.pop();
368
- if (!IPV4_REGEX.test(ipv4Part)) {
369
- return false;
370
- }
371
- }
372
- const isShortened = data.indexOf("::") !== -1;
373
- const ipv6Part = hasIpv4 ? addressParts.join(":") : data;
374
- if (isShortened) {
375
- if (ipv6Part.split("::").length - 1 > 1) {
376
- return false;
377
- }
378
- if (!IPV6_SHORT_REGEX.test(ipv6Part)) {
379
- return false;
380
- }
381
- return IPV6_FAST_FAIL_REGEX.test(ipv6Part);
382
- }
383
- const isIpv6Valid = IPV6_FULL_REGEX.test(ipv6Part);
384
- const hasInvalidChar = IPV6_INVALID_CHAR_REGEX.test(ipv6Part);
385
- if (hasIpv4) {
386
- return isIpv6Valid || !hasInvalidChar;
387
- }
388
- return isIpv6Valid && !hasInvalidChar;
469
+ return isValidIpv6(data);
389
470
  },
390
471
  hostname(data) {
391
472
  return HOSTNAME_REGEX.test(data);
@@ -417,28 +498,22 @@ var Formats = {
417
498
  }
418
499
  },
419
500
  "json-pointer"(data) {
420
- if (data === "") {
421
- return true;
422
- }
423
- return JSON_POINTER_REGEX.test(data);
501
+ return isValidJsonPointer(data);
424
502
  },
425
503
  "relative-json-pointer"(data) {
426
- if (data === "") {
427
- return true;
428
- }
429
- return RELATIVE_JSON_POINTER_REGEX.test(data);
504
+ return isValidRelativeJsonPointer(data);
430
505
  },
431
506
  time(data) {
432
507
  return TIME_REGEX.test(data);
433
508
  },
434
509
  "uri-reference"(data) {
435
- if (BACK_SLASH_REGEX.test(data)) {
510
+ if (data.includes("\\")) {
436
511
  return false;
437
512
  }
438
513
  return URI_REFERENCE_REGEX.test(data);
439
514
  },
440
515
  "uri-template"(data) {
441
- return URI_TEMPLATE_REGEX.test(data);
516
+ return isValidUriTemplate(data);
442
517
  },
443
518
  duration(data) {
444
519
  return DURATION_REGEX.test(data);
@@ -451,7 +526,7 @@ var Formats = {
451
526
  return IRI_REGEX.test(data);
452
527
  },
453
528
  "iri-reference"(data) {
454
- if (BACK_SLASH_REGEX.test(data)) {
529
+ if (data.includes("\\")) {
455
530
  return false;
456
531
  }
457
532
  return IRI_REFERENCE_REGEX.test(data);
@@ -468,7 +543,7 @@ var Formats = {
468
543
  // lib/types.ts
469
544
  var Types = {
470
545
  object(data) {
471
- return isObject(data);
546
+ return data !== null && typeof data === "object" && !Array.isArray(data);
472
547
  },
473
548
  array(data) {
474
549
  return Array.isArray(data);
@@ -491,16 +566,124 @@ var Types = {
491
566
  // Not implemented yet
492
567
  timestamp: false,
493
568
  int8: false,
494
- unit8: false,
569
+ uint8: false,
495
570
  int16: false,
496
- unit16: false,
571
+ uint16: false,
497
572
  int32: false,
498
- unit32: false,
573
+ uint32: false,
499
574
  float32: false,
500
575
  float64: false
501
576
  };
502
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
+
503
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
+ }
504
687
  var ArrayKeywords = {
505
688
  // lib/keywords/array-keywords.ts
506
689
  items(schema, data, defineError) {
@@ -591,18 +774,28 @@ var ArrayKeywords = {
591
774
  return defineError("Array is too long", { data });
592
775
  },
593
776
  additionalItems(schema, data, defineError) {
594
- if (!schema.items || isObject(schema.items)) {
777
+ if (!Array.isArray(data) || !Array.isArray(schema.items)) {
595
778
  return;
596
779
  }
597
- if (schema.additionalItems === false) {
598
- if (data.length > schema.items.length) {
599
- return defineError("Array is too long", { data });
600
- }
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) {
601
791
  return;
602
792
  }
603
- if (isObject(schema.additionalItems)) {
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)) {
604
797
  if (isCompiledSchema(schema.additionalItems)) {
605
- for (let i = schema.items.length; i < data.length; i++) {
798
+ for (let i = tupleLength; i < data.length; i++) {
606
799
  const error = schema.additionalItems.$validate(data[i]);
607
800
  if (error) {
608
801
  return defineError("Array item is invalid", {
@@ -626,25 +819,84 @@ var ArrayKeywords = {
626
819
  if (len <= 1) {
627
820
  return;
628
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
+ }
629
840
  const primitiveSeen = /* @__PURE__ */ new Set();
841
+ let primitiveArraySignatures;
842
+ let arrayBuckets;
843
+ let objectBuckets;
630
844
  for (let i = 0; i < len; i++) {
631
845
  const item = data[i];
632
- const type = typeof item;
633
- if (item === null || type === "string" || type === "number" || type === "boolean") {
846
+ if (isUniquePrimitive(item)) {
634
847
  if (primitiveSeen.has(item)) {
635
848
  return defineError("Array items are not unique", { data: item });
636
849
  }
637
850
  primitiveSeen.add(item);
638
851
  continue;
639
852
  }
640
- if (item && typeof item === "object") {
641
- for (let j = 0; j < i; j++) {
642
- const prev = data[j];
643
- if (prev && typeof prev === "object" && !hasChanged(prev, item)) {
853
+ if (!item || typeof item !== "object") {
854
+ continue;
855
+ }
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)) {
644
863
  return defineError("Array items are not unique", { data: item });
645
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 });
646
897
  }
647
898
  }
899
+ candidates.push(item);
648
900
  }
649
901
  },
650
902
  contains(schema, data, defineError) {
@@ -660,8 +912,9 @@ var ArrayKeywords = {
660
912
  }
661
913
  return defineError("Array must not contain any items", { data });
662
914
  }
915
+ const containsValidate = schema.contains.$validate;
663
916
  for (let i = 0; i < data.length; i++) {
664
- const error = schema.contains.$validate(data[i]);
917
+ const error = containsValidate(data[i]);
665
918
  if (!error) {
666
919
  return;
667
920
  }
@@ -671,6 +924,140 @@ var ArrayKeywords = {
671
924
  }
672
925
  };
673
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
+
674
1061
  // lib/keywords/number-keywords.ts
675
1062
  var NumberKeywords = {
676
1063
  minimum(schema, data, defineError, instance) {
@@ -739,15 +1126,129 @@ var NumberKeywords = {
739
1126
  }
740
1127
  };
741
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
+
742
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
+ }
743
1244
  var ObjectKeywords = {
744
1245
  required(schema, data, defineError) {
745
- if (!isObject(data)) {
1246
+ if (!data || typeof data !== "object" || Array.isArray(data)) {
746
1247
  return;
747
1248
  }
748
1249
  for (let i = 0; i < schema.required.length; i++) {
749
1250
  const key = schema.required[i];
750
- if (!data.hasOwnProperty(key)) {
1251
+ if (!Object.prototype.hasOwnProperty.call(data, key)) {
751
1252
  return defineError("Required property is missing", {
752
1253
  item: key,
753
1254
  data: data[key]
@@ -757,7 +1258,7 @@ var ObjectKeywords = {
757
1258
  return;
758
1259
  },
759
1260
  properties(schema, data, defineError) {
760
- if (!isObject(data)) {
1261
+ if (!data || typeof data !== "object" || Array.isArray(data)) {
761
1262
  return;
762
1263
  }
763
1264
  let propKeys = schema._propKeys;
@@ -770,22 +1271,21 @@ var ObjectKeywords = {
770
1271
  writable: false
771
1272
  });
772
1273
  }
773
- let requiredKeys = schema._requiredKeys;
774
- if (requiredKeys === void 0) {
775
- requiredKeys = Array.isArray(schema.required) ? schema.required : null;
776
- Object.defineProperty(schema, "_requiredKeys", {
777
- value: requiredKeys,
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,
778
1279
  enumerable: false,
779
1280
  configurable: false,
780
1281
  writable: false
781
1282
  });
782
1283
  }
783
- const required = requiredKeys || [];
784
1284
  for (let i = 0; i < propKeys.length; i++) {
785
1285
  const key = propKeys[i];
786
1286
  const schemaProp = schema.properties[key];
787
1287
  if (!Object.prototype.hasOwnProperty.call(data, key)) {
788
- if (required.length && required.indexOf(key) !== -1 && isObject(schemaProp) && "default" in schemaProp) {
1288
+ if (requiredSet && requiredSet.has(key) && schemaProp && typeof schemaProp === "object" && !Array.isArray(schemaProp) && "default" in schemaProp) {
789
1289
  const error = schemaProp.$validate(schemaProp.default);
790
1290
  if (error) {
791
1291
  return defineError("Default property is invalid", {
@@ -794,7 +1294,7 @@ var ObjectKeywords = {
794
1294
  data: schemaProp.default
795
1295
  });
796
1296
  }
797
- data[key] = deepClone(schemaProp.default);
1297
+ data[key] = deepCloneUnfreeze(schemaProp.default);
798
1298
  }
799
1299
  continue;
800
1300
  }
@@ -821,7 +1321,7 @@ var ObjectKeywords = {
821
1321
  return;
822
1322
  },
823
1323
  values(schema, data, defineError) {
824
- if (!isObject(data)) {
1324
+ if (!data || typeof data !== "object" || Array.isArray(data)) {
825
1325
  return;
826
1326
  }
827
1327
  const valueSchema = schema.values;
@@ -829,9 +1329,10 @@ var ObjectKeywords = {
829
1329
  if (typeof validate !== "function") {
830
1330
  return;
831
1331
  }
832
- const keys = Object.keys(data);
833
- for (let i = 0; i < keys.length; i++) {
834
- const key = keys[i];
1332
+ for (const key in data) {
1333
+ if (!Object.prototype.hasOwnProperty.call(data, key)) {
1334
+ continue;
1335
+ }
835
1336
  const error = validate(data[key]);
836
1337
  if (error) {
837
1338
  return defineError("Property is invalid", {
@@ -843,58 +1344,61 @@ var ObjectKeywords = {
843
1344
  }
844
1345
  },
845
1346
  maxProperties(schema, data, defineError) {
846
- if (!isObject(data) || Object.keys(data).length <= schema.maxProperties) {
1347
+ if (!data || typeof data !== "object" || Array.isArray(data)) {
847
1348
  return;
848
1349
  }
849
- return defineError("Too many properties", { data });
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;
850
1361
  },
851
1362
  minProperties(schema, data, defineError) {
852
- if (!isObject(data) || Object.keys(data).length >= schema.minProperties) {
1363
+ if (!data || typeof data !== "object" || Array.isArray(data)) {
853
1364
  return;
854
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
+ }
855
1376
  return defineError("Too few properties", { data });
856
1377
  },
857
1378
  additionalProperties(schema, data, defineError) {
858
- if (!isObject(data)) {
1379
+ if (!data || typeof data !== "object" || Array.isArray(data)) {
859
1380
  return;
860
1381
  }
861
- const keys = Object.keys(data);
862
- let apIsCompiled = schema._apIsCompiled;
863
- if (apIsCompiled === void 0) {
864
- apIsCompiled = isCompiledSchema(schema.additionalProperties);
865
- Object.defineProperty(schema, "_apIsCompiled", {
866
- value: apIsCompiled,
867
- enumerable: false
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
868
1390
  });
869
1391
  }
870
- let patternList = schema._patternPropertiesList;
871
- if (schema.patternProperties && !patternList) {
872
- patternList = [];
873
- for (const pattern in schema.patternProperties) {
874
- patternList.push({
875
- regex: new RegExp(pattern, "u"),
876
- key: pattern
877
- });
1392
+ const patternEntries = getPatternPropertyEntries(schema);
1393
+ for (const key in data) {
1394
+ if (!Object.prototype.hasOwnProperty.call(data, key)) {
1395
+ continue;
878
1396
  }
879
- Object.defineProperty(schema, "_patternPropertiesList", {
880
- value: patternList,
881
- enumerable: false
882
- });
883
- }
884
- for (let i = 0; i < keys.length; i++) {
885
- const key = keys[i];
886
- if (schema.properties && schema.properties.hasOwnProperty(key)) {
1397
+ if (schema.properties && Object.prototype.hasOwnProperty.call(schema.properties, key)) {
887
1398
  continue;
888
1399
  }
889
- if (patternList && patternList.length) {
890
- let match = false;
891
- for (let j = 0; j < patternList.length; j++) {
892
- if (patternList[j].regex.test(key)) {
893
- match = true;
894
- break;
895
- }
896
- }
897
- if (match) {
1400
+ if (patternEntries && patternEntries.length) {
1401
+ if (getPatternKeyMatchIndexes(schema, key, patternEntries).length > 0) {
898
1402
  continue;
899
1403
  }
900
1404
  }
@@ -904,8 +1408,8 @@ var ObjectKeywords = {
904
1408
  data: data[key]
905
1409
  });
906
1410
  }
907
- if (apIsCompiled && isCompiledSchema(schema.additionalProperties)) {
908
- const error = schema.additionalProperties.$validate(data[key]);
1411
+ if (apValidate) {
1412
+ const error = apValidate(data[key]);
909
1413
  if (error) {
910
1414
  return defineError("Additional properties are invalid", {
911
1415
  item: key,
@@ -918,55 +1422,46 @@ var ObjectKeywords = {
918
1422
  return;
919
1423
  },
920
1424
  patternProperties(schema, data, defineError) {
921
- if (!isObject(data)) {
1425
+ if (!data || typeof data !== "object" || Array.isArray(data)) {
922
1426
  return;
923
1427
  }
924
- let patternList = schema._patternPropertiesList;
925
- if (!patternList) {
926
- patternList = [];
927
- const patterns = Object.keys(schema.patternProperties || {});
928
- for (let i = 0; i < patterns.length; i++) {
929
- const pattern = patterns[i];
930
- patternList.push({
931
- regex: new RegExp(pattern, "u"),
932
- key: pattern
933
- });
934
- }
935
- Object.defineProperty(schema, "_patternPropertiesList", {
936
- value: patternList,
937
- enumerable: false
938
- });
1428
+ const patternEntries = getPatternPropertyEntries(schema);
1429
+ if (!patternEntries || patternEntries.length === 0) {
1430
+ return;
939
1431
  }
940
- const dataKeys = Object.keys(data);
941
- for (let p = 0; p < patternList.length; p++) {
942
- const { regex, key: patternKey } = patternList[p];
943
- const schemaProp = schema.patternProperties[patternKey];
944
- if (typeof schemaProp === "boolean") {
945
- if (schemaProp === false) {
946
- for (let i = 0; i < dataKeys.length; i++) {
947
- const key = dataKeys[i];
948
- if (regex.test(key)) {
949
- return defineError("Property is not allowed", {
950
- item: key,
951
- data: data[key]
952
- });
953
- }
954
- }
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
+ });
955
1443
  }
956
1444
  continue;
957
1445
  }
958
- if ("$validate" in schemaProp) {
959
- for (let i = 0; i < dataKeys.length; i++) {
960
- const key = dataKeys[i];
961
- if (regex.test(key)) {
962
- const error = schemaProp.$validate(data[key]);
963
- if (error) {
964
- return defineError("Property is invalid", {
965
- item: key,
966
- cause: error,
967
- data: data[key]
968
- });
969
- }
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
+ });
970
1465
  }
971
1466
  }
972
1467
  }
@@ -974,13 +1469,17 @@ var ObjectKeywords = {
974
1469
  return;
975
1470
  },
976
1471
  propertyNames(schema, data, defineError) {
977
- if (!isObject(data)) {
1472
+ if (!data || typeof data !== "object" || Array.isArray(data)) {
978
1473
  return;
979
1474
  }
980
1475
  const pn = schema.propertyNames;
981
1476
  if (typeof pn === "boolean") {
982
- if (pn === false && Object.keys(data).length > 0) {
983
- return defineError("Properties are not allowed", { data });
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
+ }
984
1483
  }
985
1484
  return;
986
1485
  }
@@ -1003,7 +1502,7 @@ var ObjectKeywords = {
1003
1502
  }
1004
1503
  },
1005
1504
  dependencies(schema, data, defineError) {
1006
- if (!isObject(data)) {
1505
+ if (!data || typeof data !== "object" || Array.isArray(data)) {
1007
1506
  return;
1008
1507
  }
1009
1508
  for (const key in schema.dependencies) {
@@ -1065,99 +1564,194 @@ var ObjectKeywords = {
1065
1564
  };
1066
1565
 
1067
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
+ }
1068
1598
  var OtherKeywords = {
1069
1599
  enum(schema, data, defineError) {
1070
- const list = schema.enum;
1071
- for (let i = 0; i < list.length; i++) {
1072
- const enumItem = list[i];
1073
- if (enumItem === data) {
1074
- return;
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
+ }
1075
1612
  }
1076
- if (enumItem !== null && data !== null && typeof enumItem === "object" && typeof data === "object" && !hasChanged(enumItem, data)) {
1077
- return;
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)) {
1627
+ return;
1628
+ }
1078
1629
  }
1079
1630
  }
1080
1631
  return defineError("Value is not one of the allowed values", { data });
1081
1632
  },
1082
1633
  allOf(schema, data, defineError) {
1083
- for (let i = 0; i < schema.allOf.length; i++) {
1084
- if (isObject(schema.allOf[i])) {
1085
- if ("$validate" in schema.allOf[i]) {
1086
- const error = schema.allOf[i].$validate(data);
1087
- if (error) {
1088
- return defineError("Value is not valid", { cause: error, data });
1089
- }
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 });
1090
1641
  }
1091
- continue;
1642
+ return;
1092
1643
  }
1093
- if (typeof schema.allOf[i] === "boolean") {
1094
- if (Boolean(data) !== schema.allOf[i]) {
1095
- return defineError("Value is not valid", { data });
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 });
1096
1661
  }
1097
1662
  continue;
1098
1663
  }
1099
- if (data !== schema.allOf[i]) {
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) {
1100
1671
  return defineError("Value is not valid", { data });
1101
1672
  }
1102
1673
  }
1103
1674
  return;
1104
1675
  },
1105
1676
  anyOf(schema, data, defineError) {
1106
- for (let i = 0; i < schema.anyOf.length; i++) {
1107
- if (isObject(schema.anyOf[i])) {
1108
- if ("$validate" in schema.anyOf[i]) {
1109
- const error = schema.anyOf[i].$validate(data);
1110
- if (!error) {
1111
- return;
1112
- }
1113
- 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;
1114
1684
  }
1685
+ return defineError("Value is not valid", { data });
1686
+ }
1687
+ if (onlyBranch.kind === "alwaysValid") {
1115
1688
  return;
1116
- } else {
1117
- if (typeof schema.anyOf[i] === "boolean") {
1118
- if (Boolean(data) === schema.anyOf[i]) {
1119
- return;
1120
- }
1121
- }
1122
- if (data === schema.anyOf[i]) {
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) {
1123
1703
  return;
1124
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;
1125
1715
  }
1126
1716
  }
1127
1717
  return defineError("Value is not valid", { data });
1128
1718
  },
1129
1719
  oneOf(schema, data, defineError) {
1130
- const list = schema.oneOf;
1131
- let validCount = 0;
1132
- for (let i = 0; i < list.length; i++) {
1133
- const sub = list[i];
1134
- if (isObject(sub)) {
1135
- if ("$validate" in sub) {
1136
- const error = sub.$validate(data);
1137
- if (!error) {
1138
- validCount++;
1139
- if (validCount > 1) {
1140
- return defineError("Value is not valid", { data });
1141
- }
1142
- }
1143
- continue;
1144
- }
1145
- validCount++;
1146
- if (validCount > 1) {
1147
- return defineError("Value is not valid", { data });
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;
1148
1727
  }
1149
- continue;
1728
+ return defineError("Value is not valid", { data });
1150
1729
  }
1151
- if (typeof sub === "boolean") {
1152
- if (Boolean(data) === sub) {
1153
- validCount++;
1154
- if (validCount > 1) {
1155
- return defineError("Value is not valid", { data });
1156
- }
1157
- }
1158
- continue;
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;
1751
+ } else {
1752
+ isValid = data === branch.value;
1159
1753
  }
1160
- if (data === sub) {
1754
+ if (isValid) {
1161
1755
  validCount++;
1162
1756
  if (validCount > 1) {
1163
1757
  return defineError("Value is not valid", { data });
@@ -1173,7 +1767,7 @@ var OtherKeywords = {
1173
1767
  if (data === schema.const) {
1174
1768
  return;
1175
1769
  }
1176
- if (isObject(data) && isObject(schema.const) && !hasChanged(data, schema.const) || Array.isArray(data) && Array.isArray(schema.const) && !hasChanged(data, schema.const)) {
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)) {
1177
1771
  return;
1178
1772
  }
1179
1773
  return defineError("Value is not valid", { data });
@@ -1215,11 +1809,11 @@ var OtherKeywords = {
1215
1809
  }
1216
1810
  return;
1217
1811
  }
1218
- if (isObject(schema.not)) {
1812
+ if (schema.not && typeof schema.not === "object" && !Array.isArray(schema.not)) {
1219
1813
  if ("$validate" in schema.not) {
1220
1814
  const error = schema.not.$validate(data);
1221
1815
  if (!error) {
1222
- return defineError("Value is not valid", { cause: error, data });
1816
+ return defineError("Value is not valid", { data });
1223
1817
  }
1224
1818
  return;
1225
1819
  }
@@ -1229,6 +1823,9 @@ var OtherKeywords = {
1229
1823
  },
1230
1824
  $ref(schema, data, defineError, instance) {
1231
1825
  if (schema._resolvedRef) {
1826
+ if (schema.$validate !== schema._resolvedRef) {
1827
+ schema.$validate = schema._resolvedRef;
1828
+ }
1232
1829
  return schema._resolvedRef(data);
1233
1830
  }
1234
1831
  const refPath = schema.$ref;
@@ -1243,11 +1840,14 @@ var OtherKeywords = {
1243
1840
  return;
1244
1841
  }
1245
1842
  schema._resolvedRef = targetSchema.$validate;
1843
+ schema.$validate = schema._resolvedRef;
1246
1844
  return schema._resolvedRef(data);
1247
1845
  }
1248
1846
  };
1249
1847
 
1250
1848
  // lib/keywords/string-keywords.ts
1849
+ var PATTERN_MATCH_CACHE_LIMIT = 512;
1850
+ var FORMAT_RESULT_CACHE_LIMIT = 512;
1251
1851
  var StringKeywords = {
1252
1852
  minLength(schema, data, defineError) {
1253
1853
  if (typeof data !== "string" || data.length >= schema.minLength) {
@@ -1265,12 +1865,14 @@ var StringKeywords = {
1265
1865
  if (typeof data !== "string") {
1266
1866
  return;
1267
1867
  }
1268
- let patternRegexp = schema._patternRegexp;
1269
- if (!patternRegexp) {
1868
+ let patternMatch = schema._patternMatch;
1869
+ let patternMatchCache = schema._patternMatchCache;
1870
+ if (!patternMatch) {
1270
1871
  try {
1271
- patternRegexp = new RegExp(schema.pattern, "u");
1272
- Object.defineProperty(schema, "_patternRegexp", {
1273
- value: patternRegexp,
1872
+ const compiled = compilePatternMatcher(schema.pattern);
1873
+ patternMatch = compiled instanceof RegExp ? (value) => compiled.test(value) : compiled;
1874
+ Object.defineProperty(schema, "_patternMatch", {
1875
+ value: patternMatch,
1274
1876
  enumerable: false,
1275
1877
  configurable: false,
1276
1878
  writable: false
@@ -1282,7 +1884,25 @@ var StringKeywords = {
1282
1884
  });
1283
1885
  }
1284
1886
  }
1285
- if (patternRegexp.test(data)) {
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);
1904
+ }
1905
+ if (isMatch) {
1286
1906
  return;
1287
1907
  }
1288
1908
  return defineError("Value does not match the pattern", { data });
@@ -1294,6 +1914,8 @@ var StringKeywords = {
1294
1914
  return;
1295
1915
  }
1296
1916
  let formatValidate = schema._formatValidate;
1917
+ let formatResultCacheEnabled = schema._formatResultCacheEnabled;
1918
+ let formatResultCache = schema._formatResultCache;
1297
1919
  if (formatValidate === void 0) {
1298
1920
  formatValidate = instance.getFormat(schema.format);
1299
1921
  Object.defineProperty(schema, "_formatValidate", {
@@ -1303,7 +1925,46 @@ var StringKeywords = {
1303
1925
  writable: false
1304
1926
  });
1305
1927
  }
1306
- if (!formatValidate || formatValidate(data)) {
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) {
1307
1968
  return;
1308
1969
  }
1309
1970
  return defineError("Value does not match the format", { data });
@@ -1366,6 +2027,9 @@ var SchemaShield = class {
1366
2027
  getFormat(format) {
1367
2028
  return this.formats[format];
1368
2029
  }
2030
+ isDefaultFormatValidator(format, validator) {
2031
+ return Formats[format] === validator;
2032
+ }
1369
2033
  addKeyword(name, validator, overwrite = false) {
1370
2034
  if (this.keywords[name] && !overwrite) {
1371
2035
  throw new ValidationError(`Keyword "${name}" already exists`);
@@ -1388,20 +2052,39 @@ var SchemaShield = class {
1388
2052
  this.idRegistry.clear();
1389
2053
  const compiledSchema = this.compileSchema(schema);
1390
2054
  this.rootSchema = compiledSchema;
1391
- this.linkReferences(compiledSchema);
2055
+ if (compiledSchema._hasRef === true) {
2056
+ this.linkReferences(compiledSchema);
2057
+ }
1392
2058
  if (!compiledSchema.$validate) {
1393
- if (this.isSchemaLike(schema) === false) {
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) {
1394
2076
  throw new ValidationError("Invalid schema");
2077
+ } else {
2078
+ compiledSchema.$validate = getNamedFunction(
2079
+ "Validate_Any",
2080
+ () => {
2081
+ }
2082
+ );
1395
2083
  }
1396
- compiledSchema.$validate = getNamedFunction(
1397
- "Validate_Any",
1398
- () => {
1399
- }
1400
- );
1401
2084
  }
1402
2085
  const validate = (data) => {
1403
2086
  this.rootSchema = compiledSchema;
1404
- const clonedData = this.immutable ? deepClone(data) : data;
2087
+ const clonedData = this.immutable ? deepCloneUnfreeze(data) : data;
1405
2088
  const res = compiledSchema.$validate(clonedData);
1406
2089
  if (res) {
1407
2090
  return { data: clonedData, error: res, valid: false };
@@ -1411,8 +2094,181 @@ var SchemaShield = class {
1411
2094
  validate.compiledSchema = compiledSchema;
1412
2095
  return validate;
1413
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
+ }
1414
2270
  compileSchema(schema) {
1415
- if (!isObject(schema)) {
2271
+ if (!schema || typeof schema !== "object" || Array.isArray(schema)) {
1416
2272
  if (schema === true) {
1417
2273
  schema = { anyOf: [{}] };
1418
2274
  } else if (schema === false) {
@@ -1421,11 +2277,16 @@ var SchemaShield = class {
1421
2277
  schema = { oneOf: [schema] };
1422
2278
  }
1423
2279
  }
1424
- const compiledSchema = deepClone(schema);
2280
+ schema = this.normalizeSchemaForCompile(schema);
2281
+ const compiledSchema = deepCloneUnfreeze(
2282
+ schema
2283
+ );
2284
+ let schemaHasRef = false;
1425
2285
  if (typeof schema.$id === "string") {
1426
2286
  this.idRegistry.set(schema.$id, compiledSchema);
1427
2287
  }
1428
2288
  if ("$ref" in schema) {
2289
+ schemaHasRef = true;
1429
2290
  const refValidator = this.getKeyword("$ref");
1430
2291
  if (refValidator) {
1431
2292
  const defineError = getDefinedErrorFunctionForKey(
@@ -1443,6 +2304,7 @@ var SchemaShield = class {
1443
2304
  )
1444
2305
  );
1445
2306
  }
2307
+ this.markSchemaHasRef(compiledSchema);
1446
2308
  return compiledSchema;
1447
2309
  }
1448
2310
  const validators = [];
@@ -1456,11 +2318,18 @@ var SchemaShield = class {
1456
2318
  const types = Array.isArray(schema.type) ? schema.type : schema.type.split(",").map((t) => t.trim());
1457
2319
  const typeFunctions = [];
1458
2320
  const typeNames = [];
2321
+ const defaultTypeNames = [];
2322
+ let allTypesDefault = true;
1459
2323
  for (const type2 of types) {
1460
2324
  const validator = this.getType(type2);
1461
2325
  if (validator) {
1462
2326
  typeFunctions.push(validator);
1463
2327
  typeNames.push(validator.name);
2328
+ if (this.isDefaultTypeValidator(type2, validator)) {
2329
+ defaultTypeNames.push(type2);
2330
+ } else {
2331
+ allTypesDefault = false;
2332
+ }
1464
2333
  }
1465
2334
  }
1466
2335
  if (typeFunctions.length === 0) {
@@ -1472,7 +2341,118 @@ var SchemaShield = class {
1472
2341
  }
1473
2342
  let combinedTypeValidator;
1474
2343
  let typeMethodName = "";
1475
- if (typeFunctions.length === 1) {
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;
2420
+ }
2421
+ return defineTypeError("Invalid type", { data });
2422
+ }
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) {
2444
+ return;
2445
+ }
2446
+ return defineTypeError("Invalid type", { data });
2447
+ }
2448
+ if (allowsObject) {
2449
+ return;
2450
+ }
2451
+ return defineTypeError("Invalid type", { data });
2452
+ }
2453
+ return defineTypeError("Invalid type", { data });
2454
+ };
2455
+ } else if (typeFunctions.length === 1) {
1476
2456
  typeMethodName = typeNames[0];
1477
2457
  const singleTypeFn = typeFunctions[0];
1478
2458
  combinedTypeValidator = (data) => {
@@ -1491,72 +2471,90 @@ var SchemaShield = class {
1491
2471
  return defineTypeError("Invalid type", { data });
1492
2472
  };
1493
2473
  }
1494
- const typeAdapter = (_s, data) => combinedTypeValidator(data);
1495
2474
  validators.push({
1496
- fn: getNamedFunction(typeMethodName, typeAdapter),
1497
- defineError: defineTypeError
2475
+ name: typeMethodName,
2476
+ validate: getNamedFunction(typeMethodName, combinedTypeValidator)
1498
2477
  });
1499
2478
  activeNames.push(typeMethodName);
1500
2479
  }
1501
2480
  const { type, $id, $ref, $validate, required, ...otherKeys } = schema;
1502
- const keyOrder = required ? [...Object.keys(otherKeys), "required"] : Object.keys(otherKeys);
2481
+ const keyOrder = required ? this.hasRequiredDefaults(schema) ? [...Object.keys(otherKeys), "required"] : ["required", ...Object.keys(otherKeys)] : Object.keys(otherKeys);
1503
2482
  for (const key of keyOrder) {
1504
2483
  const keywordFn = this.getKeyword(key);
1505
- if (keywordFn) {
1506
- const defineError = getDefinedErrorFunctionForKey(
1507
- key,
1508
- schema[key],
1509
- this.failFast
1510
- );
1511
- const fnName = keywordFn.name || key;
1512
- validators.push({
1513
- fn: keywordFn,
1514
- defineError
1515
- });
1516
- activeNames.push(fnName);
2484
+ if (!keywordFn) {
2485
+ continue;
1517
2486
  }
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);
1518
2504
  }
1519
2505
  const literalKeywords = ["enum", "const", "default", "examples"];
1520
2506
  for (const key of keyOrder) {
1521
2507
  if (literalKeywords.includes(key)) {
1522
2508
  continue;
1523
2509
  }
1524
- if (isObject(schema[key])) {
2510
+ if (schema[key] && typeof schema[key] === "object" && !Array.isArray(schema[key])) {
1525
2511
  if (key === "properties") {
1526
2512
  for (const subKey of Object.keys(schema[key])) {
1527
- compiledSchema[key][subKey] = this.compileSchema(
2513
+ const compiledSubSchema2 = this.compileSchema(
1528
2514
  schema[key][subKey]
1529
2515
  );
2516
+ if (compiledSubSchema2._hasRef === true) {
2517
+ schemaHasRef = true;
2518
+ }
2519
+ compiledSchema[key][subKey] = compiledSubSchema2;
1530
2520
  }
1531
2521
  continue;
1532
2522
  }
1533
- compiledSchema[key] = this.compileSchema(schema[key]);
2523
+ const compiledSubSchema = this.compileSchema(schema[key]);
2524
+ if (compiledSubSchema._hasRef === true) {
2525
+ schemaHasRef = true;
2526
+ }
2527
+ compiledSchema[key] = compiledSubSchema;
1534
2528
  continue;
1535
2529
  }
1536
2530
  if (Array.isArray(schema[key])) {
1537
2531
  for (let i = 0; i < schema[key].length; i++) {
1538
2532
  if (this.isSchemaLike(schema[key][i])) {
1539
- compiledSchema[key][i] = this.compileSchema(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;
1540
2538
  }
1541
2539
  }
1542
2540
  continue;
1543
2541
  }
1544
2542
  }
2543
+ if (schemaHasRef) {
2544
+ this.markSchemaHasRef(compiledSchema);
2545
+ }
1545
2546
  if (validators.length === 0) {
1546
2547
  return compiledSchema;
1547
2548
  }
1548
2549
  if (validators.length === 1) {
1549
2550
  const v = validators[0];
1550
- compiledSchema.$validate = getNamedFunction(
1551
- activeNames[0],
1552
- (data) => v.fn(compiledSchema, data, v.defineError, this)
1553
- );
2551
+ compiledSchema.$validate = getNamedFunction(v.name, v.validate);
1554
2552
  } else {
1555
2553
  const compositeName = "Validate_" + activeNames.join("_AND_");
1556
2554
  const masterValidator = (data) => {
1557
2555
  for (let i = 0; i < validators.length; i++) {
1558
2556
  const v = validators[i];
1559
- const error = v.fn(compiledSchema, data, v.defineError, this);
2557
+ const error = v.validate(data);
1560
2558
  if (error) {
1561
2559
  return error;
1562
2560
  }
@@ -1571,7 +2569,7 @@ var SchemaShield = class {
1571
2569
  return compiledSchema;
1572
2570
  }
1573
2571
  isSchemaLike(subSchema) {
1574
- if (isObject(subSchema)) {
2572
+ if (subSchema && typeof subSchema === "object" && !Array.isArray(subSchema)) {
1575
2573
  if ("type" in subSchema) {
1576
2574
  return true;
1577
2575
  }