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.mjs CHANGED
@@ -1,4 +1,4 @@
1
- // lib/utils.ts
1
+ // lib/utils/main-utils.ts
2
2
  var ValidationError = class extends Error {
3
3
  message;
4
4
  item;
@@ -73,158 +73,8 @@ function getDefinedErrorFunctionForKey(key, schema, failFast) {
73
73
  defineError
74
74
  );
75
75
  }
76
- function hasChanged(prev, current) {
77
- if (Array.isArray(prev)) {
78
- if (Array.isArray(current) === false) {
79
- return true;
80
- }
81
- if (prev.length !== current.length) {
82
- return true;
83
- }
84
- for (let i = 0; i < current.length; i++) {
85
- if (hasChanged(prev[i], current[i])) {
86
- return true;
87
- }
88
- }
89
- return false;
90
- }
91
- if (typeof prev === "object" && prev !== null) {
92
- if (typeof current !== "object" || current === null) {
93
- return true;
94
- }
95
- for (const key in current) {
96
- if (hasChanged(prev[key], current[key])) {
97
- return true;
98
- }
99
- }
100
- for (const key in prev) {
101
- if (hasChanged(prev[key], current[key])) {
102
- return true;
103
- }
104
- }
105
- return false;
106
- }
107
- return Object.is(prev, current) === false;
108
- }
109
- function isObject(data) {
110
- return typeof data === "object" && data !== null && !Array.isArray(data);
111
- }
112
- function areCloseEnough(a, b, epsilon = 1e-15) {
113
- return Math.abs(a - b) <= epsilon * Math.max(Math.abs(a), Math.abs(b));
114
- }
115
- function deepClone(obj, cloneClassInstances = false, seen = /* @__PURE__ */ new WeakMap()) {
116
- if (typeof obj === "undefined" || obj === null || typeof obj !== "object") {
117
- return obj;
118
- }
119
- if (seen.has(obj)) {
120
- return seen.get(obj);
121
- }
122
- let clone;
123
- if (typeof structuredClone === "function") {
124
- clone = structuredClone(obj);
125
- seen.set(obj, clone);
126
- return clone;
127
- }
128
- switch (true) {
129
- case Array.isArray(obj): {
130
- clone = [];
131
- seen.set(obj, clone);
132
- for (let i = 0, l = obj.length; i < l; i++) {
133
- clone[i] = deepClone(obj[i], cloneClassInstances, seen);
134
- }
135
- return clone;
136
- }
137
- case obj instanceof Date: {
138
- clone = new Date(obj.getTime());
139
- seen.set(obj, clone);
140
- return clone;
141
- }
142
- case obj instanceof RegExp: {
143
- clone = new RegExp(obj.source, obj.flags);
144
- seen.set(obj, clone);
145
- return clone;
146
- }
147
- case obj instanceof Map: {
148
- clone = /* @__PURE__ */ new Map();
149
- seen.set(obj, clone);
150
- for (const [key, value] of obj.entries()) {
151
- clone.set(
152
- deepClone(key, cloneClassInstances, seen),
153
- deepClone(value, cloneClassInstances, seen)
154
- );
155
- }
156
- return clone;
157
- }
158
- case obj instanceof Set: {
159
- clone = /* @__PURE__ */ new Set();
160
- seen.set(obj, clone);
161
- for (const value of obj.values()) {
162
- clone.add(deepClone(value, cloneClassInstances, seen));
163
- }
164
- return clone;
165
- }
166
- case obj instanceof ArrayBuffer: {
167
- clone = obj.slice(0);
168
- seen.set(obj, clone);
169
- return clone;
170
- }
171
- case ArrayBuffer.isView(obj): {
172
- clone = new obj.constructor(obj.buffer.slice(0));
173
- seen.set(obj, clone);
174
- return clone;
175
- }
176
- case (typeof Buffer !== "undefined" && obj instanceof Buffer): {
177
- clone = Buffer.from(obj);
178
- seen.set(obj, clone);
179
- return clone;
180
- }
181
- case obj instanceof Error: {
182
- clone = new obj.constructor(obj.message);
183
- seen.set(obj, clone);
184
- break;
185
- }
186
- case (obj instanceof Promise || obj instanceof WeakMap || obj instanceof WeakSet): {
187
- clone = obj;
188
- seen.set(obj, clone);
189
- return clone;
190
- }
191
- case (obj.constructor && obj.constructor !== Object): {
192
- if (!cloneClassInstances) {
193
- clone = obj;
194
- seen.set(obj, clone);
195
- return clone;
196
- }
197
- clone = Object.create(Object.getPrototypeOf(obj));
198
- seen.set(obj, clone);
199
- break;
200
- }
201
- default: {
202
- clone = {};
203
- seen.set(obj, clone);
204
- const keys = Reflect.ownKeys(obj);
205
- for (let i = 0, l = keys.length; i < l; i++) {
206
- const key = keys[i];
207
- clone[key] = deepClone(
208
- obj[key],
209
- cloneClassInstances,
210
- seen
211
- );
212
- }
213
- return clone;
214
- }
215
- }
216
- const descriptors = Object.getOwnPropertyDescriptors(obj);
217
- for (const key of Reflect.ownKeys(descriptors)) {
218
- const descriptor = descriptors[key];
219
- if ("value" in descriptor) {
220
- descriptor.value = deepClone(descriptor.value, cloneClassInstances, seen);
221
- }
222
- Object.defineProperty(clone, key, descriptor);
223
- }
224
- return clone;
225
- }
226
76
  function isCompiledSchema(subSchema) {
227
- return isObject(subSchema) && "$validate" in subSchema;
77
+ return !!subSchema && typeof subSchema === "object" && !Array.isArray(subSchema) && "$validate" in subSchema;
228
78
  }
229
79
  function getNamedFunction(name, fn) {
230
80
  return Object.defineProperty(fn, "name", { value: name });
@@ -262,45 +112,297 @@ function resolvePath(root, path) {
262
112
  }
263
113
  return;
264
114
  }
115
+ function areCloseEnough(a, b, epsilon = 1e-15) {
116
+ return Math.abs(a - b) <= epsilon * Math.max(Math.abs(a), Math.abs(b));
117
+ }
265
118
 
266
119
  // lib/formats.ts
267
120
  var UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
268
121
  var DURATION_REGEX = /^P(?!$)((\d+Y)?(\d+M)?(\d+W)?(\d+D)?)(T(?=\d)(\d+H)?(\d+M)?(\d+S)?)?$/;
269
- 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;
270
122
  var URI_REGEX = /^[a-zA-Z][a-zA-Z0-9+\-.]*:[^\s]*$/;
271
123
  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;
272
- 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])$/;
273
- var IPV6_REGEX = /(?:\s+|:::+|^\w{5,}|\w{5}$|^:{1}\w|\w:{1}$)/;
274
- var IPV6_SHORT_REGEX = /^[0-9a-fA-F:.]*$/;
275
- var IPV6_FULL_REGEX = /^(?:(?:[0-9a-fA-F]{1,4}:){7}(?:[0-9a-fA-F]{1,4}|:))$/;
276
- var IPV6_INVALID_CHAR_REGEX = /(?:[0-9a-fA-F]{5,}|\D[0-9a-fA-F]{3}:)/;
277
- var IPV6_FAST_FAIL_REGEX = /^(?:(?:(?:[0-9a-fA-F]{1,4}(?::|$)){1,6}))|(?:::(?:[0-9a-fA-F]{1,4})){0,5}$/;
278
124
  var HOSTNAME_REGEX = /^[a-z0-9][a-z0-9-]{0,62}(?:\.[a-z0-9][a-z0-9-]{0,62})*[a-z0-9]$/i;
279
125
  var DATE_REGEX = /^(\d{4})-(\d{2})-(\d{2})$/;
280
- var JSON_POINTER_REGEX = /^\/(?:[^~]|~0|~1)*$/;
281
- var RELATIVE_JSON_POINTER_REGEX = /^([0-9]+)(#|\/(?:[^~]|~0|~1)*)?$/;
282
126
  var TIME_REGEX = /^([01]\d|2[0-3]):([0-5]\d):([0-5]\d)(\.\d+)?(Z|([+-])([01]\d|2[0-3]):([0-5]\d))$/;
283
127
  var URI_REFERENCE_REGEX = /^(([^:/?#]+):)?(\/\/([^/?#]*))?([^?#]*)(\?([^#]*))?(#((?![^#]*\\)[^#]*))?/i;
284
- var URI_TEMPLATE_REGEX = /^(?:[^{}]|\{[^}]+\})*$/;
285
128
  var IRI_REGEX = /^[a-zA-Z][a-zA-Z0-9+\-.]*:[^\s]*$/;
286
129
  var IRI_REFERENCE_REGEX = /^(([^:/?#]+):)?(\/\/([^/?#]*))?([^?#]*)(\?([^#]*))?(#((?![^#]*\\)[^#]*))?/i;
287
130
  var IDN_EMAIL_REGEX = /^[^@\s]+@[^@\s]+\.[^@\s]+$/;
288
131
  var IDN_HOSTNAME_REGEX = /^[^\s!@#$%^&*()_+\=\[\]{};':"\\|,<>\/?]+$/;
289
- var BACK_SLASH_REGEX = /\\/;
290
132
  var DAYS_IN_MONTH = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
133
+ function isDigitCharCode(code) {
134
+ return code >= 48 && code <= 57;
135
+ }
136
+ function parseTwoDigits(data, index) {
137
+ const first = data.charCodeAt(index) - 48;
138
+ const second = data.charCodeAt(index + 1) - 48;
139
+ if (first < 0 || first > 9 || second < 0 || second > 9) {
140
+ return -1;
141
+ }
142
+ return first * 10 + second;
143
+ }
144
+ function parseFourDigits(data, index) {
145
+ const a = data.charCodeAt(index) - 48;
146
+ const b = data.charCodeAt(index + 1) - 48;
147
+ const c = data.charCodeAt(index + 2) - 48;
148
+ const d = data.charCodeAt(index + 3) - 48;
149
+ if (a < 0 || a > 9 || b < 0 || b > 9 || c < 0 || c > 9 || d < 0 || d > 9) {
150
+ return -1;
151
+ }
152
+ return a * 1e3 + b * 100 + c * 10 + d;
153
+ }
154
+ function isValidIpv4Range(data, start, end) {
155
+ let segmentCount = 0;
156
+ let segmentStart = start;
157
+ for (let i = start; i <= end; i++) {
158
+ if (i !== end && data.charCodeAt(i) !== 46) {
159
+ continue;
160
+ }
161
+ const segmentLength = i - segmentStart;
162
+ if (segmentLength < 1 || segmentLength > 3) {
163
+ return false;
164
+ }
165
+ if (segmentLength > 1 && data.charCodeAt(segmentStart) === 48) {
166
+ return false;
167
+ }
168
+ let value = 0;
169
+ for (let j = segmentStart; j < i; j++) {
170
+ const digit = data.charCodeAt(j) - 48;
171
+ if (digit < 0 || digit > 9) {
172
+ return false;
173
+ }
174
+ value = value * 10 + digit;
175
+ }
176
+ if (value > 255) {
177
+ return false;
178
+ }
179
+ segmentCount++;
180
+ segmentStart = i + 1;
181
+ }
182
+ return segmentCount === 4;
183
+ }
184
+ function isValidIpv4(data) {
185
+ return isValidIpv4Range(data, 0, data.length);
186
+ }
187
+ function isHexCharCode(code) {
188
+ return code >= 48 && code <= 57 || code >= 65 && code <= 70 || code >= 97 && code <= 102;
189
+ }
190
+ function isValidIpv6(data) {
191
+ const length = data.length;
192
+ if (length === 0) {
193
+ return false;
194
+ }
195
+ let hasColon = false;
196
+ let hasDoubleColon = false;
197
+ let hextetCount = 0;
198
+ let i = 0;
199
+ while (i < length) {
200
+ if (data.charCodeAt(i) === 58) {
201
+ hasColon = true;
202
+ if (i + 1 < length && data.charCodeAt(i + 1) === 58) {
203
+ if (hasDoubleColon) {
204
+ return false;
205
+ }
206
+ hasDoubleColon = true;
207
+ i += 2;
208
+ if (i === length) {
209
+ break;
210
+ }
211
+ continue;
212
+ }
213
+ return false;
214
+ }
215
+ const segmentStart = i;
216
+ let segmentLength = 0;
217
+ while (i < length && isHexCharCode(data.charCodeAt(i))) {
218
+ segmentLength++;
219
+ if (segmentLength > 4) {
220
+ return false;
221
+ }
222
+ i++;
223
+ }
224
+ if (segmentLength === 0) {
225
+ return false;
226
+ }
227
+ if (i < length && data.charCodeAt(i) === 46) {
228
+ if (!hasColon) {
229
+ return false;
230
+ }
231
+ if (!isValidIpv4Range(data, segmentStart, length)) {
232
+ return false;
233
+ }
234
+ if (hasDoubleColon) {
235
+ return hextetCount < 6;
236
+ }
237
+ return hextetCount === 6;
238
+ }
239
+ hextetCount++;
240
+ if (hextetCount > 8) {
241
+ return false;
242
+ }
243
+ if (i === length) {
244
+ break;
245
+ }
246
+ if (data.charCodeAt(i) !== 58) {
247
+ return false;
248
+ }
249
+ hasColon = true;
250
+ i++;
251
+ if (i === length) {
252
+ return false;
253
+ }
254
+ if (data.charCodeAt(i) === 58) {
255
+ if (hasDoubleColon) {
256
+ return false;
257
+ }
258
+ hasDoubleColon = true;
259
+ i++;
260
+ if (i === length) {
261
+ break;
262
+ }
263
+ }
264
+ }
265
+ if (!hasColon) {
266
+ return false;
267
+ }
268
+ if (hasDoubleColon) {
269
+ return hextetCount < 8;
270
+ }
271
+ return hextetCount === 8;
272
+ }
273
+ function isValidJsonPointer(data) {
274
+ if (data === "") {
275
+ return true;
276
+ }
277
+ if (data.charCodeAt(0) !== 47) {
278
+ return false;
279
+ }
280
+ for (let i = 1; i < data.length; i++) {
281
+ if (data.charCodeAt(i) !== 126) {
282
+ continue;
283
+ }
284
+ const next = data.charCodeAt(i + 1);
285
+ if (next !== 48 && next !== 49) {
286
+ return false;
287
+ }
288
+ i++;
289
+ }
290
+ return true;
291
+ }
292
+ function isValidRelativeJsonPointer(data) {
293
+ if (data.length === 0) {
294
+ return true;
295
+ }
296
+ let i = 0;
297
+ while (i < data.length) {
298
+ const code = data.charCodeAt(i);
299
+ if (code < 48 || code > 57) {
300
+ break;
301
+ }
302
+ i++;
303
+ }
304
+ if (i === 0) {
305
+ return false;
306
+ }
307
+ if (i === data.length) {
308
+ return true;
309
+ }
310
+ if (data.charCodeAt(i) === 35) {
311
+ return i + 1 === data.length;
312
+ }
313
+ if (data.charCodeAt(i) !== 47) {
314
+ return false;
315
+ }
316
+ for (i = i + 1; i < data.length; i++) {
317
+ if (data.charCodeAt(i) !== 126) {
318
+ continue;
319
+ }
320
+ const next = data.charCodeAt(i + 1);
321
+ if (next !== 48 && next !== 49) {
322
+ return false;
323
+ }
324
+ i++;
325
+ }
326
+ return true;
327
+ }
328
+ function isValidUriTemplate(data) {
329
+ for (let i = 0; i < data.length; i++) {
330
+ const code = data.charCodeAt(i);
331
+ if (code === 125) {
332
+ return false;
333
+ }
334
+ if (code !== 123) {
335
+ continue;
336
+ }
337
+ const closeIndex = data.indexOf("}", i + 1);
338
+ if (closeIndex === -1 || closeIndex === i + 1) {
339
+ return false;
340
+ }
341
+ i = closeIndex;
342
+ }
343
+ return true;
344
+ }
291
345
  var Formats = {
292
346
  ["date-time"](data) {
293
- const match = data.match(DATE_TIME_REGEX);
294
- if (!match) {
347
+ const length = data.length;
348
+ if (length < 19) {
349
+ return false;
350
+ }
351
+ if (data.charCodeAt(4) !== 45 || data.charCodeAt(7) !== 45 || data.charCodeAt(13) !== 58 || data.charCodeAt(16) !== 58) {
352
+ return false;
353
+ }
354
+ const tCode = data.charCodeAt(10);
355
+ if (tCode !== 84 && tCode !== 116) {
356
+ return false;
357
+ }
358
+ const year = parseFourDigits(data, 0);
359
+ const month = parseTwoDigits(data, 5);
360
+ const day = parseTwoDigits(data, 8);
361
+ const hour = parseTwoDigits(data, 11);
362
+ const minute = parseTwoDigits(data, 14);
363
+ const second = parseTwoDigits(data, 17);
364
+ if (year < 0 || month < 0 || day < 0 || hour < 0 || minute < 0 || second < 0) {
365
+ return false;
366
+ }
367
+ if (hour > 23 || minute > 59 || second > 60) {
368
+ return false;
369
+ }
370
+ let cursor = 19;
371
+ let offsetSign = null;
372
+ let offsetHour = 0;
373
+ let offsetMinute = 0;
374
+ if (cursor < length && data.charCodeAt(cursor) === 46) {
375
+ cursor++;
376
+ const fracStart = cursor;
377
+ while (cursor < length && isDigitCharCode(data.charCodeAt(cursor))) {
378
+ cursor++;
379
+ }
380
+ if (cursor === fracStart) {
381
+ return false;
382
+ }
383
+ }
384
+ if (cursor < length) {
385
+ const tzCode = data.charCodeAt(cursor);
386
+ if (tzCode === 90 || tzCode === 122) {
387
+ cursor++;
388
+ } else if (tzCode === 43 || tzCode === 45) {
389
+ offsetSign = tzCode === 43 ? "+" : "-";
390
+ if (cursor + 6 > length || data.charCodeAt(cursor + 3) !== 58) {
391
+ return false;
392
+ }
393
+ offsetHour = parseTwoDigits(data, cursor + 1);
394
+ offsetMinute = parseTwoDigits(data, cursor + 4);
395
+ if (offsetHour < 0 || offsetMinute < 0 || offsetHour > 23 || offsetMinute > 59) {
396
+ return false;
397
+ }
398
+ cursor += 6;
399
+ } else {
400
+ return false;
401
+ }
402
+ }
403
+ if (cursor !== length) {
295
404
  return false;
296
405
  }
297
- const [, yearStr, monthStr, dayStr, hourStr, minuteStr, secondStr] = match;
298
- const year = Number(yearStr);
299
- const month = Number(monthStr);
300
- const day = Number(dayStr);
301
- const hour = Number(hourStr);
302
- const minute = Number(minuteStr);
303
- const second = Number(secondStr);
304
406
  if (month < 1 || month > 12) {
305
407
  return false;
306
408
  }
@@ -311,8 +413,19 @@ var Formats = {
311
413
  if (!maxDays || day > maxDays) {
312
414
  return false;
313
415
  }
314
- if (second === 60 && (minute !== 59 || hour !== 23)) {
315
- return false;
416
+ if (second === 60) {
417
+ let utcTotalMinutes = hour * 60 + minute;
418
+ if (offsetSign) {
419
+ const offsetTotalMinutes = offsetHour * 60 + offsetMinute;
420
+ utcTotalMinutes += offsetSign === "+" ? -offsetTotalMinutes : offsetTotalMinutes;
421
+ utcTotalMinutes %= 24 * 60;
422
+ if (utcTotalMinutes < 0) {
423
+ utcTotalMinutes += 24 * 60;
424
+ }
425
+ }
426
+ if (utcTotalMinutes !== 23 * 60 + 59) {
427
+ return false;
428
+ }
316
429
  }
317
430
  return true;
318
431
  },
@@ -323,42 +436,10 @@ var Formats = {
323
436
  return EMAIL_REGEX.test(data);
324
437
  },
325
438
  ipv4(data) {
326
- return IPV4_REGEX.test(data);
439
+ return isValidIpv4(data);
327
440
  },
328
- // ipv6: isMyIpValid({ version: 6 }),
329
441
  ipv6(data) {
330
- if (data === "::") {
331
- return true;
332
- }
333
- if (data.indexOf(":") === -1 || IPV6_REGEX.test(data)) {
334
- return false;
335
- }
336
- const hasIpv4 = data.indexOf(".") !== -1;
337
- let addressParts = data;
338
- if (hasIpv4) {
339
- addressParts = data.split(":");
340
- const ipv4Part = addressParts.pop();
341
- if (!IPV4_REGEX.test(ipv4Part)) {
342
- return false;
343
- }
344
- }
345
- const isShortened = data.indexOf("::") !== -1;
346
- const ipv6Part = hasIpv4 ? addressParts.join(":") : data;
347
- if (isShortened) {
348
- if (ipv6Part.split("::").length - 1 > 1) {
349
- return false;
350
- }
351
- if (!IPV6_SHORT_REGEX.test(ipv6Part)) {
352
- return false;
353
- }
354
- return IPV6_FAST_FAIL_REGEX.test(ipv6Part);
355
- }
356
- const isIpv6Valid = IPV6_FULL_REGEX.test(ipv6Part);
357
- const hasInvalidChar = IPV6_INVALID_CHAR_REGEX.test(ipv6Part);
358
- if (hasIpv4) {
359
- return isIpv6Valid || !hasInvalidChar;
360
- }
361
- return isIpv6Valid && !hasInvalidChar;
442
+ return isValidIpv6(data);
362
443
  },
363
444
  hostname(data) {
364
445
  return HOSTNAME_REGEX.test(data);
@@ -390,28 +471,22 @@ var Formats = {
390
471
  }
391
472
  },
392
473
  "json-pointer"(data) {
393
- if (data === "") {
394
- return true;
395
- }
396
- return JSON_POINTER_REGEX.test(data);
474
+ return isValidJsonPointer(data);
397
475
  },
398
476
  "relative-json-pointer"(data) {
399
- if (data === "") {
400
- return true;
401
- }
402
- return RELATIVE_JSON_POINTER_REGEX.test(data);
477
+ return isValidRelativeJsonPointer(data);
403
478
  },
404
479
  time(data) {
405
480
  return TIME_REGEX.test(data);
406
481
  },
407
482
  "uri-reference"(data) {
408
- if (BACK_SLASH_REGEX.test(data)) {
483
+ if (data.includes("\\")) {
409
484
  return false;
410
485
  }
411
486
  return URI_REFERENCE_REGEX.test(data);
412
487
  },
413
488
  "uri-template"(data) {
414
- return URI_TEMPLATE_REGEX.test(data);
489
+ return isValidUriTemplate(data);
415
490
  },
416
491
  duration(data) {
417
492
  return DURATION_REGEX.test(data);
@@ -424,7 +499,7 @@ var Formats = {
424
499
  return IRI_REGEX.test(data);
425
500
  },
426
501
  "iri-reference"(data) {
427
- if (BACK_SLASH_REGEX.test(data)) {
502
+ if (data.includes("\\")) {
428
503
  return false;
429
504
  }
430
505
  return IRI_REFERENCE_REGEX.test(data);
@@ -441,7 +516,7 @@ var Formats = {
441
516
  // lib/types.ts
442
517
  var Types = {
443
518
  object(data) {
444
- return isObject(data);
519
+ return data !== null && typeof data === "object" && !Array.isArray(data);
445
520
  },
446
521
  array(data) {
447
522
  return Array.isArray(data);
@@ -464,16 +539,124 @@ var Types = {
464
539
  // Not implemented yet
465
540
  timestamp: false,
466
541
  int8: false,
467
- unit8: false,
542
+ uint8: false,
468
543
  int16: false,
469
- unit16: false,
544
+ uint16: false,
470
545
  int32: false,
471
- unit32: false,
546
+ uint32: false,
472
547
  float32: false,
473
548
  float64: false
474
549
  };
475
550
 
551
+ // lib/utils/has-changed.ts
552
+ function hasChanged(prev, current) {
553
+ if (Object.is(prev, current)) {
554
+ return false;
555
+ }
556
+ if (Array.isArray(prev)) {
557
+ if (Array.isArray(current) === false) {
558
+ return true;
559
+ }
560
+ if (prev.length !== current.length) {
561
+ return true;
562
+ }
563
+ for (let i = 0; i < current.length; i++) {
564
+ if (hasChanged(prev[i], current[i])) {
565
+ return true;
566
+ }
567
+ }
568
+ return false;
569
+ }
570
+ if (typeof prev === "object" && prev !== null) {
571
+ if (typeof current !== "object" || current === null) {
572
+ return true;
573
+ }
574
+ for (const key in current) {
575
+ if (hasChanged(prev[key], current[key])) {
576
+ return true;
577
+ }
578
+ }
579
+ for (const key in prev) {
580
+ if (key in current) {
581
+ continue;
582
+ }
583
+ if (hasChanged(prev[key], void 0)) {
584
+ return true;
585
+ }
586
+ }
587
+ return false;
588
+ }
589
+ return true;
590
+ }
591
+
476
592
  // lib/keywords/array-keywords.ts
593
+ function isUniquePrimitive(value) {
594
+ return value === null || typeof value === "string" || typeof value === "number" || typeof value === "boolean";
595
+ }
596
+ function getArrayBucketKey(value) {
597
+ const length = value.length;
598
+ if (length === 0) {
599
+ return "0";
600
+ }
601
+ const first = value[0];
602
+ const last = value[length - 1];
603
+ const firstType = first === null ? "null" : typeof first;
604
+ const lastType = last === null ? "null" : typeof last;
605
+ let firstArrayMarker = "";
606
+ if (Array.isArray(first)) {
607
+ const firstSignature = getPrimitiveArraySignature(first);
608
+ firstArrayMarker = firstSignature === null ? `a:${first.length}` : firstSignature;
609
+ }
610
+ let lastArrayMarker = "";
611
+ if (Array.isArray(last)) {
612
+ const lastSignature = getPrimitiveArraySignature(last);
613
+ lastArrayMarker = lastSignature === null ? `a:${last.length}` : lastSignature;
614
+ }
615
+ return `${length}:${firstType}:${firstArrayMarker}:${lastType}:${lastArrayMarker}`;
616
+ }
617
+ function getObjectShapeKey(value) {
618
+ const keys = Object.keys(value).sort();
619
+ return `${keys.length}:${keys.join("")}`;
620
+ }
621
+ function getPrimitiveArraySignature(value) {
622
+ const length = value.length;
623
+ if (length === 0) {
624
+ return "a:0";
625
+ }
626
+ if (!isUniquePrimitive(value[0]) || !isUniquePrimitive(value[length - 1])) {
627
+ return null;
628
+ }
629
+ let signature = `a:${length}:`;
630
+ for (let i = 0; i < length; i++) {
631
+ const item = value[i];
632
+ if (item === null) {
633
+ signature += "l;";
634
+ continue;
635
+ }
636
+ if (typeof item === "string") {
637
+ signature += `s${item.length}:${item};`;
638
+ continue;
639
+ }
640
+ if (typeof item === "number") {
641
+ if (Number.isNaN(item)) {
642
+ signature += "n:NaN;";
643
+ continue;
644
+ }
645
+ if (Object.is(item, -0)) {
646
+ signature += "n:-0;";
647
+ continue;
648
+ }
649
+ signature += `n:${item};`;
650
+ continue;
651
+ }
652
+ if (typeof item === "boolean") {
653
+ signature += item ? "b:1;" : "b:0;";
654
+ continue;
655
+ }
656
+ return null;
657
+ }
658
+ return signature;
659
+ }
477
660
  var ArrayKeywords = {
478
661
  // lib/keywords/array-keywords.ts
479
662
  items(schema, data, defineError) {
@@ -564,18 +747,28 @@ var ArrayKeywords = {
564
747
  return defineError("Array is too long", { data });
565
748
  },
566
749
  additionalItems(schema, data, defineError) {
567
- if (!schema.items || isObject(schema.items)) {
750
+ if (!Array.isArray(data) || !Array.isArray(schema.items)) {
568
751
  return;
569
752
  }
570
- if (schema.additionalItems === false) {
571
- if (data.length > schema.items.length) {
572
- return defineError("Array is too long", { data });
573
- }
753
+ let tupleLength = schema._tupleItemsLength;
754
+ if (tupleLength === void 0) {
755
+ tupleLength = schema.items.length;
756
+ Object.defineProperty(schema, "_tupleItemsLength", {
757
+ value: tupleLength,
758
+ enumerable: false,
759
+ configurable: false,
760
+ writable: false
761
+ });
762
+ }
763
+ if (data.length <= tupleLength) {
574
764
  return;
575
765
  }
576
- if (isObject(schema.additionalItems)) {
766
+ if (schema.additionalItems === false) {
767
+ return defineError("Array is too long", { data });
768
+ }
769
+ if (schema.additionalItems && typeof schema.additionalItems === "object" && !Array.isArray(schema.additionalItems)) {
577
770
  if (isCompiledSchema(schema.additionalItems)) {
578
- for (let i = schema.items.length; i < data.length; i++) {
771
+ for (let i = tupleLength; i < data.length; i++) {
579
772
  const error = schema.additionalItems.$validate(data[i]);
580
773
  if (error) {
581
774
  return defineError("Array item is invalid", {
@@ -599,25 +792,84 @@ var ArrayKeywords = {
599
792
  if (len <= 1) {
600
793
  return;
601
794
  }
795
+ if (len <= 8) {
796
+ for (let i = 0; i < len; i++) {
797
+ const left = data[i];
798
+ for (let j = i + 1; j < len; j++) {
799
+ const right = data[j];
800
+ if (left === right) {
801
+ return defineError("Array items are not unique", { data: right });
802
+ }
803
+ if (typeof left === "number" && typeof right === "number" && Number.isNaN(left) && Number.isNaN(right)) {
804
+ return defineError("Array items are not unique", { data: right });
805
+ }
806
+ if (left && right && typeof left === "object" && typeof right === "object" && !hasChanged(left, right)) {
807
+ return defineError("Array items are not unique", { data: right });
808
+ }
809
+ }
810
+ }
811
+ return;
812
+ }
602
813
  const primitiveSeen = /* @__PURE__ */ new Set();
814
+ let primitiveArraySignatures;
815
+ let arrayBuckets;
816
+ let objectBuckets;
603
817
  for (let i = 0; i < len; i++) {
604
818
  const item = data[i];
605
- const type = typeof item;
606
- if (item === null || type === "string" || type === "number" || type === "boolean") {
819
+ if (isUniquePrimitive(item)) {
607
820
  if (primitiveSeen.has(item)) {
608
821
  return defineError("Array items are not unique", { data: item });
609
822
  }
610
823
  primitiveSeen.add(item);
611
824
  continue;
612
825
  }
613
- if (item && typeof item === "object") {
614
- for (let j = 0; j < i; j++) {
615
- const prev = data[j];
616
- if (prev && typeof prev === "object" && !hasChanged(prev, item)) {
826
+ if (!item || typeof item !== "object") {
827
+ continue;
828
+ }
829
+ if (Array.isArray(item)) {
830
+ const signature = getPrimitiveArraySignature(item);
831
+ if (signature !== null) {
832
+ if (!primitiveArraySignatures) {
833
+ primitiveArraySignatures = /* @__PURE__ */ new Set();
834
+ }
835
+ if (primitiveArraySignatures.has(signature)) {
617
836
  return defineError("Array items are not unique", { data: item });
618
837
  }
838
+ primitiveArraySignatures.add(signature);
839
+ continue;
840
+ }
841
+ if (!arrayBuckets) {
842
+ arrayBuckets = /* @__PURE__ */ new Map();
843
+ }
844
+ const bucketKey2 = getArrayBucketKey(item);
845
+ let candidates2 = arrayBuckets.get(bucketKey2);
846
+ if (!candidates2) {
847
+ candidates2 = [];
848
+ arrayBuckets.set(bucketKey2, candidates2);
849
+ }
850
+ for (let j = 0; j < candidates2.length; j++) {
851
+ if (!hasChanged(candidates2[j], item)) {
852
+ return defineError("Array items are not unique", { data: item });
853
+ }
854
+ }
855
+ candidates2.push(item);
856
+ continue;
857
+ }
858
+ if (!objectBuckets) {
859
+ objectBuckets = /* @__PURE__ */ new Map();
860
+ }
861
+ const bucketKey = getObjectShapeKey(item);
862
+ let candidates = objectBuckets.get(bucketKey);
863
+ if (!candidates) {
864
+ candidates = [];
865
+ objectBuckets.set(bucketKey, candidates);
866
+ }
867
+ for (let j = 0; j < candidates.length; j++) {
868
+ if (!hasChanged(candidates[j], item)) {
869
+ return defineError("Array items are not unique", { data: item });
619
870
  }
620
871
  }
872
+ candidates.push(item);
621
873
  }
622
874
  },
623
875
  contains(schema, data, defineError) {
@@ -633,8 +885,9 @@ var ArrayKeywords = {
633
885
  }
634
886
  return defineError("Array must not contain any items", { data });
635
887
  }
888
+ const containsValidate = schema.contains.$validate;
636
889
  for (let i = 0; i < data.length; i++) {
637
- const error = schema.contains.$validate(data[i]);
890
+ const error = containsValidate(data[i]);
638
891
  if (!error) {
639
892
  return;
640
893
  }
@@ -644,6 +897,140 @@ var ArrayKeywords = {
644
897
  }
645
898
  };
646
899
 
900
+ // lib/utils/deep-freeze.ts
901
+ function isPlainObject(value) {
902
+ if (!value || typeof value !== "object") {
903
+ return false;
904
+ }
905
+ const proto = Object.getPrototypeOf(value);
906
+ return proto === Object.prototype || proto === null;
907
+ }
908
+ function canUseStructuredClone(value) {
909
+ if (typeof structuredClone !== "function") {
910
+ return false;
911
+ }
912
+ if (typeof Buffer !== "undefined" && value instanceof Buffer) {
913
+ return false;
914
+ }
915
+ return Array.isArray(value) || isPlainObject(value) || value instanceof Date || value instanceof RegExp || value instanceof Map || value instanceof Set || value instanceof ArrayBuffer || ArrayBuffer.isView(value);
916
+ }
917
+ function deepCloneUnfreeze(obj, cloneClassInstances = false, seen = /* @__PURE__ */ new WeakMap()) {
918
+ if (typeof obj === "undefined" || obj === null || typeof obj !== "object") {
919
+ return obj;
920
+ }
921
+ const source = obj;
922
+ if (seen.has(source)) {
923
+ return seen.get(source);
924
+ }
925
+ if (canUseStructuredClone(source)) {
926
+ const cloned = structuredClone(source);
927
+ seen.set(source, cloned);
928
+ return cloned;
929
+ }
930
+ let clone;
931
+ switch (true) {
932
+ case Array.isArray(source): {
933
+ clone = [];
934
+ seen.set(source, clone);
935
+ for (let i = 0, l = source.length; i < l; i++) {
936
+ clone[i] = deepCloneUnfreeze(source[i], cloneClassInstances, seen);
937
+ }
938
+ return clone;
939
+ }
940
+ case source instanceof Date: {
941
+ clone = new Date(source.getTime());
942
+ seen.set(source, clone);
943
+ return clone;
944
+ }
945
+ case source instanceof RegExp: {
946
+ clone = new RegExp(source.source, source.flags);
947
+ seen.set(source, clone);
948
+ return clone;
949
+ }
950
+ case source instanceof Map: {
951
+ clone = /* @__PURE__ */ new Map();
952
+ seen.set(source, clone);
953
+ for (const [key, value] of source.entries()) {
954
+ clone.set(
955
+ deepCloneUnfreeze(key, cloneClassInstances, seen),
956
+ deepCloneUnfreeze(value, cloneClassInstances, seen)
957
+ );
958
+ }
959
+ return clone;
960
+ }
961
+ case source instanceof Set: {
962
+ clone = /* @__PURE__ */ new Set();
963
+ seen.set(source, clone);
964
+ for (const value of source.values()) {
965
+ clone.add(deepCloneUnfreeze(value, cloneClassInstances, seen));
966
+ }
967
+ return clone;
968
+ }
969
+ case source instanceof ArrayBuffer: {
970
+ clone = source.slice(0);
971
+ seen.set(source, clone);
972
+ return clone;
973
+ }
974
+ case ArrayBuffer.isView(source): {
975
+ clone = new source.constructor(source.buffer.slice(0));
976
+ seen.set(source, clone);
977
+ return clone;
978
+ }
979
+ case (typeof Buffer !== "undefined" && source instanceof Buffer): {
980
+ clone = Buffer.from(source);
981
+ seen.set(source, clone);
982
+ return clone;
983
+ }
984
+ case source instanceof Error: {
985
+ clone = new source.constructor(source.message);
986
+ seen.set(source, clone);
987
+ break;
988
+ }
989
+ case (source instanceof Promise || source instanceof WeakMap || source instanceof WeakSet): {
990
+ clone = source;
991
+ seen.set(source, clone);
992
+ return clone;
993
+ }
994
+ case (source.constructor && source.constructor !== Object): {
995
+ if (!cloneClassInstances) {
996
+ clone = source;
997
+ seen.set(source, clone);
998
+ return clone;
999
+ }
1000
+ clone = Object.create(Object.getPrototypeOf(source));
1001
+ seen.set(source, clone);
1002
+ break;
1003
+ }
1004
+ default: {
1005
+ clone = {};
1006
+ seen.set(source, clone);
1007
+ const keys = Reflect.ownKeys(source);
1008
+ for (let i = 0, l = keys.length; i < l; i++) {
1009
+ const key = keys[i];
1010
+ clone[key] = deepCloneUnfreeze(
1011
+ source[key],
1012
+ cloneClassInstances,
1013
+ seen
1014
+ );
1015
+ }
1016
+ return clone;
1017
+ }
1018
+ }
1019
+ const descriptors = Object.getOwnPropertyDescriptors(source);
1020
+ for (const key of Reflect.ownKeys(descriptors)) {
1021
+ const descriptor = descriptors[key];
1022
+ if ("value" in descriptor) {
1023
+ descriptor.value = deepCloneUnfreeze(
1024
+ descriptor.value,
1025
+ cloneClassInstances,
1026
+ seen
1027
+ );
1028
+ }
1029
+ Object.defineProperty(clone, key, descriptor);
1030
+ }
1031
+ return clone;
1032
+ }
1033
+
647
1034
  // lib/keywords/number-keywords.ts
648
1035
  var NumberKeywords = {
649
1036
  minimum(schema, data, defineError, instance) {
@@ -712,15 +1099,129 @@ var NumberKeywords = {
712
1099
  }
713
1100
  };
714
1101
 
1102
+ // lib/utils/pattern-matcher.ts
1103
+ var REGEX_META_CHARS = /[\\.^$*+?()[\]{}|]/;
1104
+ function hasRegexMeta(value) {
1105
+ return REGEX_META_CHARS.test(value);
1106
+ }
1107
+ var PATTERN_CACHE = /* @__PURE__ */ new Map();
1108
+ function compilePatternMatcher(pattern) {
1109
+ const cached = PATTERN_CACHE.get(pattern);
1110
+ if (cached) {
1111
+ return cached;
1112
+ }
1113
+ let compiled;
1114
+ if (pattern.length === 0) {
1115
+ compiled = (_value) => true;
1116
+ } else if (!hasRegexMeta(pattern)) {
1117
+ compiled = (value) => value.includes(pattern);
1118
+ } else {
1119
+ const patternLength = pattern.length;
1120
+ if (patternLength >= 2 && pattern[0] === "^" && pattern[patternLength - 1] === "$") {
1121
+ const inner = pattern.slice(1, -1);
1122
+ if (!hasRegexMeta(inner)) {
1123
+ if (inner.length === 0) {
1124
+ compiled = (value) => value.length === 0;
1125
+ } else {
1126
+ compiled = (value) => value === inner;
1127
+ }
1128
+ } else {
1129
+ compiled = new RegExp(pattern, "u");
1130
+ }
1131
+ } else if (pattern[0] === "^") {
1132
+ const inner = pattern.slice(1);
1133
+ if (!hasRegexMeta(inner)) {
1134
+ if (inner.length === 0) {
1135
+ compiled = (_value) => true;
1136
+ } else {
1137
+ compiled = (value) => value.startsWith(inner);
1138
+ }
1139
+ } else {
1140
+ compiled = new RegExp(pattern, "u");
1141
+ }
1142
+ } else if (pattern[patternLength - 1] === "$") {
1143
+ const inner = pattern.slice(0, -1);
1144
+ if (!hasRegexMeta(inner)) {
1145
+ if (inner.length === 0) {
1146
+ compiled = (_value) => true;
1147
+ } else {
1148
+ compiled = (value) => value.endsWith(inner);
1149
+ }
1150
+ } else {
1151
+ compiled = new RegExp(pattern, "u");
1152
+ }
1153
+ } else {
1154
+ compiled = new RegExp(pattern, "u");
1155
+ }
1156
+ }
1157
+ PATTERN_CACHE.set(pattern, compiled);
1158
+ return compiled;
1159
+ }
1160
+
715
1161
  // lib/keywords/object-keywords.ts
1162
+ var PATTERN_KEY_CACHE_LIMIT = 512;
1163
+ function getPatternPropertyEntries(schema) {
1164
+ let entries = schema._patternPropertyEntries;
1165
+ if (entries) {
1166
+ return entries;
1167
+ }
1168
+ if (!schema.patternProperties || typeof schema.patternProperties !== "object" || Array.isArray(schema.patternProperties)) {
1169
+ return void 0;
1170
+ }
1171
+ const patternKeys = Object.keys(schema.patternProperties);
1172
+ entries = new Array(patternKeys.length);
1173
+ for (let i = 0; i < patternKeys.length; i++) {
1174
+ const key = patternKeys[i];
1175
+ const compiledMatcher = compilePatternMatcher(key);
1176
+ const match = compiledMatcher instanceof RegExp ? (value) => compiledMatcher.test(value) : compiledMatcher;
1177
+ entries[i] = {
1178
+ schemaProp: schema.patternProperties[key],
1179
+ match
1180
+ };
1181
+ }
1182
+ Object.defineProperty(schema, "_patternPropertyEntries", {
1183
+ value: entries,
1184
+ enumerable: false,
1185
+ configurable: false,
1186
+ writable: false
1187
+ });
1188
+ return entries;
1189
+ }
1190
+ function getPatternKeyMatchIndexes(schema, key, entries) {
1191
+ let cache = schema._patternKeyMatchIndexCache;
1192
+ if (cache) {
1193
+ const cached = cache.get(key);
1194
+ if (cached) {
1195
+ return cached;
1196
+ }
1197
+ } else {
1198
+ cache = /* @__PURE__ */ new Map();
1199
+ Object.defineProperty(schema, "_patternKeyMatchIndexCache", {
1200
+ value: cache,
1201
+ enumerable: false,
1202
+ configurable: false,
1203
+ writable: false
1204
+ });
1205
+ }
1206
+ const indexes = [];
1207
+ for (let i = 0; i < entries.length; i++) {
1208
+ if (entries[i].match(key)) {
1209
+ indexes.push(i);
1210
+ }
1211
+ }
1212
+ if (cache.size < PATTERN_KEY_CACHE_LIMIT) {
1213
+ cache.set(key, indexes);
1214
+ }
1215
+ return indexes;
1216
+ }
716
1217
  var ObjectKeywords = {
717
1218
  required(schema, data, defineError) {
718
- if (!isObject(data)) {
1219
+ if (!data || typeof data !== "object" || Array.isArray(data)) {
719
1220
  return;
720
1221
  }
721
1222
  for (let i = 0; i < schema.required.length; i++) {
722
1223
  const key = schema.required[i];
723
- if (!data.hasOwnProperty(key)) {
1224
+ if (!Object.prototype.hasOwnProperty.call(data, key)) {
724
1225
  return defineError("Required property is missing", {
725
1226
  item: key,
726
1227
  data: data[key]
@@ -730,7 +1231,7 @@ var ObjectKeywords = {
730
1231
  return;
731
1232
  },
732
1233
  properties(schema, data, defineError) {
733
- if (!isObject(data)) {
1234
+ if (!data || typeof data !== "object" || Array.isArray(data)) {
734
1235
  return;
735
1236
  }
736
1237
  let propKeys = schema._propKeys;
@@ -743,22 +1244,21 @@ var ObjectKeywords = {
743
1244
  writable: false
744
1245
  });
745
1246
  }
746
- let requiredKeys = schema._requiredKeys;
747
- if (requiredKeys === void 0) {
748
- requiredKeys = Array.isArray(schema.required) ? schema.required : null;
749
- Object.defineProperty(schema, "_requiredKeys", {
750
- value: requiredKeys,
1247
+ let requiredSet = schema._requiredSet;
1248
+ if (requiredSet === void 0) {
1249
+ requiredSet = Array.isArray(schema.required) ? new Set(schema.required) : null;
1250
+ Object.defineProperty(schema, "_requiredSet", {
1251
+ value: requiredSet,
751
1252
  enumerable: false,
752
1253
  configurable: false,
753
1254
  writable: false
754
1255
  });
755
1256
  }
756
- const required = requiredKeys || [];
757
1257
  for (let i = 0; i < propKeys.length; i++) {
758
1258
  const key = propKeys[i];
759
1259
  const schemaProp = schema.properties[key];
760
1260
  if (!Object.prototype.hasOwnProperty.call(data, key)) {
761
- if (required.length && required.indexOf(key) !== -1 && isObject(schemaProp) && "default" in schemaProp) {
1261
+ if (requiredSet && requiredSet.has(key) && schemaProp && typeof schemaProp === "object" && !Array.isArray(schemaProp) && "default" in schemaProp) {
762
1262
  const error = schemaProp.$validate(schemaProp.default);
763
1263
  if (error) {
764
1264
  return defineError("Default property is invalid", {
@@ -767,7 +1267,7 @@ var ObjectKeywords = {
767
1267
  data: schemaProp.default
768
1268
  });
769
1269
  }
770
- data[key] = deepClone(schemaProp.default);
1270
+ data[key] = deepCloneUnfreeze(schemaProp.default);
771
1271
  }
772
1272
  continue;
773
1273
  }
@@ -794,7 +1294,7 @@ var ObjectKeywords = {
794
1294
  return;
795
1295
  },
796
1296
  values(schema, data, defineError) {
797
- if (!isObject(data)) {
1297
+ if (!data || typeof data !== "object" || Array.isArray(data)) {
798
1298
  return;
799
1299
  }
800
1300
  const valueSchema = schema.values;
@@ -802,9 +1302,10 @@ var ObjectKeywords = {
802
1302
  if (typeof validate !== "function") {
803
1303
  return;
804
1304
  }
805
- const keys = Object.keys(data);
806
- for (let i = 0; i < keys.length; i++) {
807
- const key = keys[i];
1305
+ for (const key in data) {
1306
+ if (!Object.prototype.hasOwnProperty.call(data, key)) {
1307
+ continue;
1308
+ }
808
1309
  const error = validate(data[key]);
809
1310
  if (error) {
810
1311
  return defineError("Property is invalid", {
@@ -816,58 +1317,61 @@ var ObjectKeywords = {
816
1317
  }
817
1318
  },
818
1319
  maxProperties(schema, data, defineError) {
819
- if (!isObject(data) || Object.keys(data).length <= schema.maxProperties) {
1320
+ if (!data || typeof data !== "object" || Array.isArray(data)) {
820
1321
  return;
821
1322
  }
822
- return defineError("Too many properties", { data });
1323
+ let count = 0;
1324
+ for (const key in data) {
1325
+ if (!Object.prototype.hasOwnProperty.call(data, key)) {
1326
+ continue;
1327
+ }
1328
+ count++;
1329
+ if (count > schema.maxProperties) {
1330
+ return defineError("Too many properties", { data });
1331
+ }
1332
+ }
1333
+ return;
823
1334
  },
824
1335
  minProperties(schema, data, defineError) {
825
- if (!isObject(data) || Object.keys(data).length >= schema.minProperties) {
1336
+ if (!data || typeof data !== "object" || Array.isArray(data)) {
826
1337
  return;
827
1338
  }
1339
+ let count = 0;
1340
+ for (const key in data) {
1341
+ if (!Object.prototype.hasOwnProperty.call(data, key)) {
1342
+ continue;
1343
+ }
1344
+ count++;
1345
+ if (count >= schema.minProperties) {
1346
+ return;
1347
+ }
1348
+ }
828
1349
  return defineError("Too few properties", { data });
829
1350
  },
830
1351
  additionalProperties(schema, data, defineError) {
831
- if (!isObject(data)) {
1352
+ if (!data || typeof data !== "object" || Array.isArray(data)) {
832
1353
  return;
833
1354
  }
834
- const keys = Object.keys(data);
835
- let apIsCompiled = schema._apIsCompiled;
836
- if (apIsCompiled === void 0) {
837
- apIsCompiled = isCompiledSchema(schema.additionalProperties);
838
- Object.defineProperty(schema, "_apIsCompiled", {
839
- value: apIsCompiled,
840
- enumerable: false
1355
+ let apValidate = schema._apValidate;
1356
+ if (apValidate === void 0) {
1357
+ apValidate = isCompiledSchema(schema.additionalProperties) ? schema.additionalProperties.$validate : null;
1358
+ Object.defineProperty(schema, "_apValidate", {
1359
+ value: apValidate,
1360
+ enumerable: false,
1361
+ configurable: false,
1362
+ writable: false
841
1363
  });
842
1364
  }
843
- let patternList = schema._patternPropertiesList;
844
- if (schema.patternProperties && !patternList) {
845
- patternList = [];
846
- for (const pattern in schema.patternProperties) {
847
- patternList.push({
848
- regex: new RegExp(pattern, "u"),
849
- key: pattern
850
- });
1365
+ const patternEntries = getPatternPropertyEntries(schema);
1366
+ for (const key in data) {
1367
+ if (!Object.prototype.hasOwnProperty.call(data, key)) {
1368
+ continue;
851
1369
  }
852
- Object.defineProperty(schema, "_patternPropertiesList", {
853
- value: patternList,
854
- enumerable: false
855
- });
856
- }
857
- for (let i = 0; i < keys.length; i++) {
858
- const key = keys[i];
859
- if (schema.properties && schema.properties.hasOwnProperty(key)) {
1370
+ if (schema.properties && Object.prototype.hasOwnProperty.call(schema.properties, key)) {
860
1371
  continue;
861
1372
  }
862
- if (patternList && patternList.length) {
863
- let match = false;
864
- for (let j = 0; j < patternList.length; j++) {
865
- if (patternList[j].regex.test(key)) {
866
- match = true;
867
- break;
868
- }
869
- }
870
- if (match) {
1373
+ if (patternEntries && patternEntries.length) {
1374
+ if (getPatternKeyMatchIndexes(schema, key, patternEntries).length > 0) {
871
1375
  continue;
872
1376
  }
873
1377
  }
@@ -877,8 +1381,8 @@ var ObjectKeywords = {
877
1381
  data: data[key]
878
1382
  });
879
1383
  }
880
- if (apIsCompiled && isCompiledSchema(schema.additionalProperties)) {
881
- const error = schema.additionalProperties.$validate(data[key]);
1384
+ if (apValidate) {
1385
+ const error = apValidate(data[key]);
882
1386
  if (error) {
883
1387
  return defineError("Additional properties are invalid", {
884
1388
  item: key,
@@ -891,55 +1395,46 @@ var ObjectKeywords = {
891
1395
  return;
892
1396
  },
893
1397
  patternProperties(schema, data, defineError) {
894
- if (!isObject(data)) {
1398
+ if (!data || typeof data !== "object" || Array.isArray(data)) {
895
1399
  return;
896
1400
  }
897
- let patternList = schema._patternPropertiesList;
898
- if (!patternList) {
899
- patternList = [];
900
- const patterns = Object.keys(schema.patternProperties || {});
901
- for (let i = 0; i < patterns.length; i++) {
902
- const pattern = patterns[i];
903
- patternList.push({
904
- regex: new RegExp(pattern, "u"),
905
- key: pattern
906
- });
907
- }
908
- Object.defineProperty(schema, "_patternPropertiesList", {
909
- value: patternList,
910
- enumerable: false
911
- });
1401
+ const patternEntries = getPatternPropertyEntries(schema);
1402
+ if (!patternEntries || patternEntries.length === 0) {
1403
+ return;
912
1404
  }
913
- const dataKeys = Object.keys(data);
914
- for (let p = 0; p < patternList.length; p++) {
915
- const { regex, key: patternKey } = patternList[p];
916
- const schemaProp = schema.patternProperties[patternKey];
917
- if (typeof schemaProp === "boolean") {
918
- if (schemaProp === false) {
919
- for (let i = 0; i < dataKeys.length; i++) {
920
- const key = dataKeys[i];
921
- if (regex.test(key)) {
922
- return defineError("Property is not allowed", {
923
- item: key,
924
- data: data[key]
925
- });
926
- }
927
- }
1405
+ for (const key in data) {
1406
+ if (!Object.prototype.hasOwnProperty.call(data, key)) {
1407
+ continue;
1408
+ }
1409
+ const matchingIndexes = getPatternKeyMatchIndexes(schema, key, patternEntries);
1410
+ if (matchingIndexes.length === 0) {
1411
+ if (schema.additionalProperties === false && !(schema.properties && Object.prototype.hasOwnProperty.call(schema.properties, key))) {
1412
+ return defineError("Additional properties are not allowed", {
1413
+ item: key,
1414
+ data: data[key]
1415
+ });
928
1416
  }
929
1417
  continue;
930
1418
  }
931
- if ("$validate" in schemaProp) {
932
- for (let i = 0; i < dataKeys.length; i++) {
933
- const key = dataKeys[i];
934
- if (regex.test(key)) {
935
- const error = schemaProp.$validate(data[key]);
936
- if (error) {
937
- return defineError("Property is invalid", {
938
- item: key,
939
- cause: error,
940
- data: data[key]
941
- });
942
- }
1419
+ for (let j = 0; j < matchingIndexes.length; j++) {
1420
+ const schemaProp = patternEntries[matchingIndexes[j]].schemaProp;
1421
+ if (typeof schemaProp === "boolean") {
1422
+ if (schemaProp === false) {
1423
+ return defineError("Property is not allowed", {
1424
+ item: key,
1425
+ data: data[key]
1426
+ });
1427
+ }
1428
+ continue;
1429
+ }
1430
+ if ("$validate" in schemaProp) {
1431
+ const error = schemaProp.$validate(data[key]);
1432
+ if (error) {
1433
+ return defineError("Property is invalid", {
1434
+ item: key,
1435
+ cause: error,
1436
+ data: data[key]
1437
+ });
943
1438
  }
944
1439
  }
945
1440
  }
@@ -947,13 +1442,17 @@ var ObjectKeywords = {
947
1442
  return;
948
1443
  },
949
1444
  propertyNames(schema, data, defineError) {
950
- if (!isObject(data)) {
1445
+ if (!data || typeof data !== "object" || Array.isArray(data)) {
951
1446
  return;
952
1447
  }
953
1448
  const pn = schema.propertyNames;
954
1449
  if (typeof pn === "boolean") {
955
- if (pn === false && Object.keys(data).length > 0) {
956
- return defineError("Properties are not allowed", { data });
1450
+ if (pn === false) {
1451
+ for (const key in data) {
1452
+ if (Object.prototype.hasOwnProperty.call(data, key)) {
1453
+ return defineError("Properties are not allowed", { data });
1454
+ }
1455
+ }
957
1456
  }
958
1457
  return;
959
1458
  }
@@ -976,7 +1475,7 @@ var ObjectKeywords = {
976
1475
  }
977
1476
  },
978
1477
  dependencies(schema, data, defineError) {
979
- if (!isObject(data)) {
1478
+ if (!data || typeof data !== "object" || Array.isArray(data)) {
980
1479
  return;
981
1480
  }
982
1481
  for (const key in schema.dependencies) {
@@ -1038,99 +1537,194 @@ var ObjectKeywords = {
1038
1537
  };
1039
1538
 
1040
1539
  // lib/keywords/other-keywords.ts
1540
+ function toBranchEntry(item) {
1541
+ if (item && typeof item === "object" && !Array.isArray(item)) {
1542
+ if ("$validate" in item && typeof item.$validate === "function") {
1543
+ return { kind: "validate", validate: item.$validate };
1544
+ }
1545
+ return { kind: "alwaysValid" };
1546
+ }
1547
+ if (typeof item === "boolean") {
1548
+ return { kind: item ? "alwaysValid" : "alwaysInvalid" };
1549
+ }
1550
+ return { kind: "literal", value: item };
1551
+ }
1552
+ function getBranchEntries(schema, key) {
1553
+ const cacheKey = `_${key}BranchEntries`;
1554
+ let entries = schema[cacheKey];
1555
+ if (entries) {
1556
+ return entries;
1557
+ }
1558
+ const source = schema[key] || [];
1559
+ entries = [];
1560
+ for (let i = 0; i < source.length; i++) {
1561
+ entries.push(toBranchEntry(source[i]));
1562
+ }
1563
+ Object.defineProperty(schema, cacheKey, {
1564
+ value: entries,
1565
+ enumerable: false,
1566
+ configurable: false,
1567
+ writable: false
1568
+ });
1569
+ return entries;
1570
+ }
1041
1571
  var OtherKeywords = {
1042
1572
  enum(schema, data, defineError) {
1043
- const list = schema.enum;
1044
- for (let i = 0; i < list.length; i++) {
1045
- const enumItem = list[i];
1046
- if (enumItem === data) {
1047
- return;
1573
+ let enumCache = schema._enumCache;
1574
+ if (!enumCache) {
1575
+ const primitiveSet = /* @__PURE__ */ new Set();
1576
+ const objectValues = [];
1577
+ const list = schema.enum;
1578
+ for (let i = 0; i < list.length; i++) {
1579
+ const enumItem = list[i];
1580
+ if (enumItem !== null && typeof enumItem === "object") {
1581
+ objectValues.push(enumItem);
1582
+ } else {
1583
+ primitiveSet.add(enumItem);
1584
+ }
1048
1585
  }
1049
- if (enumItem !== null && data !== null && typeof enumItem === "object" && typeof data === "object" && !hasChanged(enumItem, data)) {
1050
- return;
1586
+ enumCache = { primitiveSet, objectValues };
1587
+ Object.defineProperty(schema, "_enumCache", {
1588
+ value: enumCache,
1589
+ enumerable: false,
1590
+ configurable: false,
1591
+ writable: false
1592
+ });
1593
+ }
1594
+ if (!(typeof data === "number" && Number.isNaN(data)) && enumCache.primitiveSet.has(data)) {
1595
+ return;
1596
+ }
1597
+ if (data !== null && typeof data === "object") {
1598
+ for (let i = 0; i < enumCache.objectValues.length; i++) {
1599
+ if (!hasChanged(enumCache.objectValues[i], data)) {
1600
+ return;
1601
+ }
1051
1602
  }
1052
1603
  }
1053
1604
  return defineError("Value is not one of the allowed values", { data });
1054
1605
  },
1055
1606
  allOf(schema, data, defineError) {
1056
- for (let i = 0; i < schema.allOf.length; i++) {
1057
- if (isObject(schema.allOf[i])) {
1058
- if ("$validate" in schema.allOf[i]) {
1059
- const error = schema.allOf[i].$validate(data);
1060
- if (error) {
1061
- return defineError("Value is not valid", { cause: error, data });
1062
- }
1607
+ const branches = getBranchEntries(schema, "allOf");
1608
+ if (branches.length === 1) {
1609
+ const onlyBranch = branches[0];
1610
+ if (onlyBranch.kind === "validate") {
1611
+ const error = onlyBranch.validate(data);
1612
+ if (error) {
1613
+ return defineError("Value is not valid", { cause: error, data });
1063
1614
  }
1064
- continue;
1615
+ return;
1065
1616
  }
1066
- if (typeof schema.allOf[i] === "boolean") {
1067
- if (Boolean(data) !== schema.allOf[i]) {
1068
- return defineError("Value is not valid", { data });
1617
+ if (onlyBranch.kind === "alwaysValid") {
1618
+ return;
1619
+ }
1620
+ if (onlyBranch.kind === "alwaysInvalid") {
1621
+ return defineError("Value is not valid", { data });
1622
+ }
1623
+ if (data !== onlyBranch.value) {
1624
+ return defineError("Value is not valid", { data });
1625
+ }
1626
+ return;
1627
+ }
1628
+ for (let i = 0; i < branches.length; i++) {
1629
+ const branch = branches[i];
1630
+ if (branch.kind === "validate") {
1631
+ const error = branch.validate(data);
1632
+ if (error) {
1633
+ return defineError("Value is not valid", { cause: error, data });
1069
1634
  }
1070
1635
  continue;
1071
1636
  }
1072
- if (data !== schema.allOf[i]) {
1637
+ if (branch.kind === "alwaysValid") {
1638
+ continue;
1639
+ }
1640
+ if (branch.kind === "alwaysInvalid") {
1641
+ return defineError("Value is not valid", { data });
1642
+ }
1643
+ if (data !== branch.value) {
1073
1644
  return defineError("Value is not valid", { data });
1074
1645
  }
1075
1646
  }
1076
1647
  return;
1077
1648
  },
1078
1649
  anyOf(schema, data, defineError) {
1079
- for (let i = 0; i < schema.anyOf.length; i++) {
1080
- if (isObject(schema.anyOf[i])) {
1081
- if ("$validate" in schema.anyOf[i]) {
1082
- const error = schema.anyOf[i].$validate(data);
1083
- if (!error) {
1084
- return;
1085
- }
1086
- continue;
1650
+ const branches = getBranchEntries(schema, "anyOf");
1651
+ if (branches.length === 1) {
1652
+ const onlyBranch = branches[0];
1653
+ if (onlyBranch.kind === "validate") {
1654
+ const error = onlyBranch.validate(data);
1655
+ if (!error) {
1656
+ return;
1087
1657
  }
1658
+ return defineError("Value is not valid", { data });
1659
+ }
1660
+ if (onlyBranch.kind === "alwaysValid") {
1088
1661
  return;
1089
- } else {
1090
- if (typeof schema.anyOf[i] === "boolean") {
1091
- if (Boolean(data) === schema.anyOf[i]) {
1092
- return;
1093
- }
1094
- }
1095
- if (data === schema.anyOf[i]) {
1662
+ }
1663
+ if (onlyBranch.kind === "alwaysInvalid") {
1664
+ return defineError("Value is not valid", { data });
1665
+ }
1666
+ if (data === onlyBranch.value) {
1667
+ return;
1668
+ }
1669
+ return defineError("Value is not valid", { data });
1670
+ }
1671
+ for (let i = 0; i < branches.length; i++) {
1672
+ const branch = branches[i];
1673
+ if (branch.kind === "validate") {
1674
+ const error = branch.validate(data);
1675
+ if (!error) {
1096
1676
  return;
1097
1677
  }
1678
+ continue;
1679
+ }
1680
+ if (branch.kind === "alwaysValid") {
1681
+ return;
1682
+ }
1683
+ if (branch.kind === "alwaysInvalid") {
1684
+ continue;
1685
+ }
1686
+ if (data === branch.value) {
1687
+ return;
1098
1688
  }
1099
1689
  }
1100
1690
  return defineError("Value is not valid", { data });
1101
1691
  },
1102
1692
  oneOf(schema, data, defineError) {
1103
- const list = schema.oneOf;
1104
- let validCount = 0;
1105
- for (let i = 0; i < list.length; i++) {
1106
- const sub = list[i];
1107
- if (isObject(sub)) {
1108
- if ("$validate" in sub) {
1109
- const error = sub.$validate(data);
1110
- if (!error) {
1111
- validCount++;
1112
- if (validCount > 1) {
1113
- return defineError("Value is not valid", { data });
1114
- }
1115
- }
1116
- continue;
1117
- }
1118
- validCount++;
1119
- if (validCount > 1) {
1120
- return defineError("Value is not valid", { data });
1693
+ const branches = getBranchEntries(schema, "oneOf");
1694
+ if (branches.length === 1) {
1695
+ const onlyBranch = branches[0];
1696
+ if (onlyBranch.kind === "validate") {
1697
+ const error = onlyBranch.validate(data);
1698
+ if (!error) {
1699
+ return;
1121
1700
  }
1122
- continue;
1701
+ return defineError("Value is not valid", { data });
1123
1702
  }
1124
- if (typeof sub === "boolean") {
1125
- if (Boolean(data) === sub) {
1126
- validCount++;
1127
- if (validCount > 1) {
1128
- return defineError("Value is not valid", { data });
1129
- }
1130
- }
1131
- continue;
1703
+ if (onlyBranch.kind === "alwaysValid") {
1704
+ return;
1705
+ }
1706
+ if (onlyBranch.kind === "alwaysInvalid") {
1707
+ return defineError("Value is not valid", { data });
1708
+ }
1709
+ if (data === onlyBranch.value) {
1710
+ return;
1711
+ }
1712
+ return defineError("Value is not valid", { data });
1713
+ }
1714
+ let validCount = 0;
1715
+ for (let i = 0; i < branches.length; i++) {
1716
+ const branch = branches[i];
1717
+ let isValid = false;
1718
+ if (branch.kind === "validate") {
1719
+ isValid = !branch.validate(data);
1720
+ } else if (branch.kind === "alwaysValid") {
1721
+ isValid = true;
1722
+ } else if (branch.kind === "alwaysInvalid") {
1723
+ isValid = false;
1724
+ } else {
1725
+ isValid = data === branch.value;
1132
1726
  }
1133
- if (data === sub) {
1727
+ if (isValid) {
1134
1728
  validCount++;
1135
1729
  if (validCount > 1) {
1136
1730
  return defineError("Value is not valid", { data });
@@ -1146,7 +1740,7 @@ var OtherKeywords = {
1146
1740
  if (data === schema.const) {
1147
1741
  return;
1148
1742
  }
1149
- if (isObject(data) && isObject(schema.const) && !hasChanged(data, schema.const) || Array.isArray(data) && Array.isArray(schema.const) && !hasChanged(data, schema.const)) {
1743
+ 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)) {
1150
1744
  return;
1151
1745
  }
1152
1746
  return defineError("Value is not valid", { data });
@@ -1188,11 +1782,11 @@ var OtherKeywords = {
1188
1782
  }
1189
1783
  return;
1190
1784
  }
1191
- if (isObject(schema.not)) {
1785
+ if (schema.not && typeof schema.not === "object" && !Array.isArray(schema.not)) {
1192
1786
  if ("$validate" in schema.not) {
1193
1787
  const error = schema.not.$validate(data);
1194
1788
  if (!error) {
1195
- return defineError("Value is not valid", { cause: error, data });
1789
+ return defineError("Value is not valid", { data });
1196
1790
  }
1197
1791
  return;
1198
1792
  }
@@ -1202,6 +1796,9 @@ var OtherKeywords = {
1202
1796
  },
1203
1797
  $ref(schema, data, defineError, instance) {
1204
1798
  if (schema._resolvedRef) {
1799
+ if (schema.$validate !== schema._resolvedRef) {
1800
+ schema.$validate = schema._resolvedRef;
1801
+ }
1205
1802
  return schema._resolvedRef(data);
1206
1803
  }
1207
1804
  const refPath = schema.$ref;
@@ -1216,11 +1813,14 @@ var OtherKeywords = {
1216
1813
  return;
1217
1814
  }
1218
1815
  schema._resolvedRef = targetSchema.$validate;
1816
+ schema.$validate = schema._resolvedRef;
1219
1817
  return schema._resolvedRef(data);
1220
1818
  }
1221
1819
  };
1222
1820
 
1223
1821
  // lib/keywords/string-keywords.ts
1822
+ var PATTERN_MATCH_CACHE_LIMIT = 512;
1823
+ var FORMAT_RESULT_CACHE_LIMIT = 512;
1224
1824
  var StringKeywords = {
1225
1825
  minLength(schema, data, defineError) {
1226
1826
  if (typeof data !== "string" || data.length >= schema.minLength) {
@@ -1238,12 +1838,14 @@ var StringKeywords = {
1238
1838
  if (typeof data !== "string") {
1239
1839
  return;
1240
1840
  }
1241
- let patternRegexp = schema._patternRegexp;
1242
- if (!patternRegexp) {
1841
+ let patternMatch = schema._patternMatch;
1842
+ let patternMatchCache = schema._patternMatchCache;
1843
+ if (!patternMatch) {
1243
1844
  try {
1244
- patternRegexp = new RegExp(schema.pattern, "u");
1245
- Object.defineProperty(schema, "_patternRegexp", {
1246
- value: patternRegexp,
1845
+ const compiled = compilePatternMatcher(schema.pattern);
1846
+ patternMatch = compiled instanceof RegExp ? (value) => compiled.test(value) : compiled;
1847
+ Object.defineProperty(schema, "_patternMatch", {
1848
+ value: patternMatch,
1247
1849
  enumerable: false,
1248
1850
  configurable: false,
1249
1851
  writable: false
@@ -1255,7 +1857,25 @@ var StringKeywords = {
1255
1857
  });
1256
1858
  }
1257
1859
  }
1258
- if (patternRegexp.test(data)) {
1860
+ if (!patternMatchCache) {
1861
+ patternMatchCache = /* @__PURE__ */ new Map();
1862
+ Object.defineProperty(schema, "_patternMatchCache", {
1863
+ value: patternMatchCache,
1864
+ enumerable: false,
1865
+ configurable: false,
1866
+ writable: false
1867
+ });
1868
+ } else if (patternMatchCache.has(data)) {
1869
+ if (patternMatchCache.get(data)) {
1870
+ return;
1871
+ }
1872
+ return defineError("Value does not match the pattern", { data });
1873
+ }
1874
+ const isMatch = patternMatch(data);
1875
+ if (patternMatchCache.size < PATTERN_MATCH_CACHE_LIMIT) {
1876
+ patternMatchCache.set(data, isMatch);
1877
+ }
1878
+ if (isMatch) {
1259
1879
  return;
1260
1880
  }
1261
1881
  return defineError("Value does not match the pattern", { data });
@@ -1267,6 +1887,8 @@ var StringKeywords = {
1267
1887
  return;
1268
1888
  }
1269
1889
  let formatValidate = schema._formatValidate;
1890
+ let formatResultCacheEnabled = schema._formatResultCacheEnabled;
1891
+ let formatResultCache = schema._formatResultCache;
1270
1892
  if (formatValidate === void 0) {
1271
1893
  formatValidate = instance.getFormat(schema.format);
1272
1894
  Object.defineProperty(schema, "_formatValidate", {
@@ -1276,7 +1898,46 @@ var StringKeywords = {
1276
1898
  writable: false
1277
1899
  });
1278
1900
  }
1279
- if (!formatValidate || formatValidate(data)) {
1901
+ if (!formatValidate) {
1902
+ return;
1903
+ }
1904
+ if (formatResultCacheEnabled === void 0) {
1905
+ formatResultCacheEnabled = instance.isDefaultFormatValidator(
1906
+ schema.format,
1907
+ formatValidate
1908
+ );
1909
+ Object.defineProperty(schema, "_formatResultCacheEnabled", {
1910
+ value: formatResultCacheEnabled,
1911
+ enumerable: false,
1912
+ configurable: false,
1913
+ writable: false
1914
+ });
1915
+ }
1916
+ if (!formatResultCacheEnabled) {
1917
+ if (formatValidate(data)) {
1918
+ return;
1919
+ }
1920
+ return defineError("Value does not match the format", { data });
1921
+ }
1922
+ if (!formatResultCache) {
1923
+ formatResultCache = /* @__PURE__ */ new Map();
1924
+ Object.defineProperty(schema, "_formatResultCache", {
1925
+ value: formatResultCache,
1926
+ enumerable: false,
1927
+ configurable: false,
1928
+ writable: false
1929
+ });
1930
+ } else if (formatResultCache.has(data)) {
1931
+ if (formatResultCache.get(data)) {
1932
+ return;
1933
+ }
1934
+ return defineError("Value does not match the format", { data });
1935
+ }
1936
+ const isValid = formatValidate(data);
1937
+ if (formatResultCache.size < FORMAT_RESULT_CACHE_LIMIT) {
1938
+ formatResultCache.set(data, isValid);
1939
+ }
1940
+ if (isValid) {
1280
1941
  return;
1281
1942
  }
1282
1943
  return defineError("Value does not match the format", { data });
@@ -1339,6 +2000,9 @@ var SchemaShield = class {
1339
2000
  getFormat(format) {
1340
2001
  return this.formats[format];
1341
2002
  }
2003
+ isDefaultFormatValidator(format, validator) {
2004
+ return Formats[format] === validator;
2005
+ }
1342
2006
  addKeyword(name, validator, overwrite = false) {
1343
2007
  if (this.keywords[name] && !overwrite) {
1344
2008
  throw new ValidationError(`Keyword "${name}" already exists`);
@@ -1361,20 +2025,39 @@ var SchemaShield = class {
1361
2025
  this.idRegistry.clear();
1362
2026
  const compiledSchema = this.compileSchema(schema);
1363
2027
  this.rootSchema = compiledSchema;
1364
- this.linkReferences(compiledSchema);
2028
+ if (compiledSchema._hasRef === true) {
2029
+ this.linkReferences(compiledSchema);
2030
+ }
1365
2031
  if (!compiledSchema.$validate) {
1366
- if (this.isSchemaLike(schema) === false) {
2032
+ if (schema === false) {
2033
+ const defineError = getDefinedErrorFunctionForKey(
2034
+ "oneOf",
2035
+ compiledSchema,
2036
+ this.failFast
2037
+ );
2038
+ compiledSchema.$validate = getNamedFunction(
2039
+ "Validate_False",
2040
+ (data) => defineError("Value is not valid", { data })
2041
+ );
2042
+ } else if (schema === true) {
2043
+ compiledSchema.$validate = getNamedFunction(
2044
+ "Validate_Any",
2045
+ () => {
2046
+ }
2047
+ );
2048
+ } else if (this.isSchemaLike(schema) === false) {
1367
2049
  throw new ValidationError("Invalid schema");
2050
+ } else {
2051
+ compiledSchema.$validate = getNamedFunction(
2052
+ "Validate_Any",
2053
+ () => {
2054
+ }
2055
+ );
1368
2056
  }
1369
- compiledSchema.$validate = getNamedFunction(
1370
- "Validate_Any",
1371
- () => {
1372
- }
1373
- );
1374
2057
  }
1375
2058
  const validate = (data) => {
1376
2059
  this.rootSchema = compiledSchema;
1377
- const clonedData = this.immutable ? deepClone(data) : data;
2060
+ const clonedData = this.immutable ? deepCloneUnfreeze(data) : data;
1378
2061
  const res = compiledSchema.$validate(clonedData);
1379
2062
  if (res) {
1380
2063
  return { data: clonedData, error: res, valid: false };
@@ -1384,8 +2067,181 @@ var SchemaShield = class {
1384
2067
  validate.compiledSchema = compiledSchema;
1385
2068
  return validate;
1386
2069
  }
2070
+ isPlainObject(value) {
2071
+ return !!value && typeof value === "object" && !Array.isArray(value);
2072
+ }
2073
+ isTrivialAlwaysValidSubschema(value) {
2074
+ return value === true || this.isPlainObject(value) && Object.keys(value).length === 0;
2075
+ }
2076
+ shallowArrayEquals(a, b) {
2077
+ if (a === b) {
2078
+ return true;
2079
+ }
2080
+ if (a.length !== b.length) {
2081
+ return false;
2082
+ }
2083
+ for (let i = 0; i < a.length; i++) {
2084
+ if (a[i] !== b[i]) {
2085
+ return false;
2086
+ }
2087
+ }
2088
+ return true;
2089
+ }
2090
+ flattenAssociativeBranches(key, branches) {
2091
+ const out = [];
2092
+ for (let i = 0; i < branches.length; i++) {
2093
+ const item = branches[i];
2094
+ if (this.isPlainObject(item) && Object.keys(item).length === 1 && Array.isArray(item[key])) {
2095
+ const nested = this.flattenAssociativeBranches(key, item[key]);
2096
+ for (let j = 0; j < nested.length; j++) {
2097
+ out.push(nested[j]);
2098
+ }
2099
+ continue;
2100
+ }
2101
+ out.push(item);
2102
+ }
2103
+ return out;
2104
+ }
2105
+ flattenSingleWrapperOneOf(branches) {
2106
+ let current = branches;
2107
+ while (current.length === 1) {
2108
+ const item = current[0];
2109
+ if (this.isPlainObject(item) && Object.keys(item).length === 1 && Array.isArray(item.oneOf)) {
2110
+ current = item.oneOf;
2111
+ continue;
2112
+ }
2113
+ break;
2114
+ }
2115
+ return current;
2116
+ }
2117
+ normalizeSchemaForCompile(schema) {
2118
+ let normalized = schema;
2119
+ const schemaKeys = Object.keys(schema);
2120
+ const hasOnlyKey = (key) => schemaKeys.length === 1 && schemaKeys[0] === key;
2121
+ const setNormalized = (key, value) => {
2122
+ if (normalized === schema) {
2123
+ normalized = { ...schema };
2124
+ }
2125
+ normalized[key] = value;
2126
+ };
2127
+ if (Array.isArray(schema.allOf)) {
2128
+ const flattenedAllOf = this.flattenAssociativeBranches(
2129
+ "allOf",
2130
+ schema.allOf
2131
+ ).filter(
2132
+ (item) => !(this.isPlainObject(item) && Object.keys(item).length === 0)
2133
+ );
2134
+ if (hasOnlyKey("allOf") && flattenedAllOf.length === 1 && this.isPlainObject(flattenedAllOf[0])) {
2135
+ return flattenedAllOf[0];
2136
+ }
2137
+ if (!this.shallowArrayEquals(flattenedAllOf, schema.allOf)) {
2138
+ setNormalized("allOf", flattenedAllOf);
2139
+ }
2140
+ }
2141
+ if (Array.isArray(schema.anyOf)) {
2142
+ const flattenedAnyOf = this.flattenAssociativeBranches(
2143
+ "anyOf",
2144
+ schema.anyOf
2145
+ );
2146
+ if (hasOnlyKey("anyOf") && flattenedAnyOf.length === 1 && this.isPlainObject(flattenedAnyOf[0])) {
2147
+ return flattenedAnyOf[0];
2148
+ }
2149
+ if (!this.shallowArrayEquals(flattenedAnyOf, schema.anyOf)) {
2150
+ setNormalized("anyOf", flattenedAnyOf);
2151
+ }
2152
+ }
2153
+ if (Array.isArray(schema.oneOf)) {
2154
+ const flattenedOneOf = this.flattenSingleWrapperOneOf(schema.oneOf);
2155
+ if (hasOnlyKey("oneOf") && flattenedOneOf.length === 1 && this.isPlainObject(flattenedOneOf[0])) {
2156
+ return flattenedOneOf[0];
2157
+ }
2158
+ if (!this.shallowArrayEquals(flattenedOneOf, schema.oneOf)) {
2159
+ setNormalized("oneOf", flattenedOneOf);
2160
+ }
2161
+ }
2162
+ return normalized;
2163
+ }
2164
+ markSchemaHasRef(schema) {
2165
+ if (schema._hasRef === true) {
2166
+ return;
2167
+ }
2168
+ Object.defineProperty(schema, "_hasRef", {
2169
+ value: true,
2170
+ enumerable: false,
2171
+ configurable: false,
2172
+ writable: false
2173
+ });
2174
+ }
2175
+ shouldSkipKeyword(schema, key) {
2176
+ const value = schema[key];
2177
+ switch (key) {
2178
+ case "required":
2179
+ return Array.isArray(value) && value.length === 0;
2180
+ case "uniqueItems":
2181
+ return value === false;
2182
+ case "properties":
2183
+ case "patternProperties":
2184
+ case "dependencies":
2185
+ return this.isPlainObject(value) && Object.keys(value).length === 0;
2186
+ case "propertyNames":
2187
+ case "items":
2188
+ return value === true;
2189
+ case "additionalProperties":
2190
+ if (value === true) {
2191
+ return true;
2192
+ }
2193
+ return value === false && this.isPlainObject(schema.patternProperties) && Object.keys(schema.patternProperties).length > 0;
2194
+ case "additionalItems":
2195
+ return value === true || !Array.isArray(schema.items);
2196
+ case "allOf": {
2197
+ if (!Array.isArray(value)) {
2198
+ return false;
2199
+ }
2200
+ if (value.length === 0) {
2201
+ return true;
2202
+ }
2203
+ for (let i = 0; i < value.length; i++) {
2204
+ if (this.isTrivialAlwaysValidSubschema(value[i])) {
2205
+ continue;
2206
+ }
2207
+ return false;
2208
+ }
2209
+ return true;
2210
+ }
2211
+ case "anyOf": {
2212
+ if (!Array.isArray(value)) {
2213
+ return false;
2214
+ }
2215
+ for (let i = 0; i < value.length; i++) {
2216
+ if (this.isTrivialAlwaysValidSubschema(value[i])) {
2217
+ return true;
2218
+ }
2219
+ }
2220
+ return false;
2221
+ }
2222
+ default:
2223
+ return false;
2224
+ }
2225
+ }
2226
+ hasRequiredDefaults(schema) {
2227
+ const properties = schema.properties;
2228
+ if (!this.isPlainObject(properties)) {
2229
+ return false;
2230
+ }
2231
+ const keys = Object.keys(properties);
2232
+ for (let i = 0; i < keys.length; i++) {
2233
+ const subSchema = properties[keys[i]];
2234
+ if (this.isPlainObject(subSchema) && "default" in subSchema) {
2235
+ return true;
2236
+ }
2237
+ }
2238
+ return false;
2239
+ }
2240
+ isDefaultTypeValidator(type, validator) {
2241
+ return Types[type] === validator;
2242
+ }
1387
2243
  compileSchema(schema) {
1388
- if (!isObject(schema)) {
2244
+ if (!schema || typeof schema !== "object" || Array.isArray(schema)) {
1389
2245
  if (schema === true) {
1390
2246
  schema = { anyOf: [{}] };
1391
2247
  } else if (schema === false) {
@@ -1394,11 +2250,16 @@ var SchemaShield = class {
1394
2250
  schema = { oneOf: [schema] };
1395
2251
  }
1396
2252
  }
1397
- const compiledSchema = deepClone(schema);
2253
+ schema = this.normalizeSchemaForCompile(schema);
2254
+ const compiledSchema = deepCloneUnfreeze(
2255
+ schema
2256
+ );
2257
+ let schemaHasRef = false;
1398
2258
  if (typeof schema.$id === "string") {
1399
2259
  this.idRegistry.set(schema.$id, compiledSchema);
1400
2260
  }
1401
2261
  if ("$ref" in schema) {
2262
+ schemaHasRef = true;
1402
2263
  const refValidator = this.getKeyword("$ref");
1403
2264
  if (refValidator) {
1404
2265
  const defineError = getDefinedErrorFunctionForKey(
@@ -1416,6 +2277,7 @@ var SchemaShield = class {
1416
2277
  )
1417
2278
  );
1418
2279
  }
2280
+ this.markSchemaHasRef(compiledSchema);
1419
2281
  return compiledSchema;
1420
2282
  }
1421
2283
  const validators = [];
@@ -1429,11 +2291,18 @@ var SchemaShield = class {
1429
2291
  const types = Array.isArray(schema.type) ? schema.type : schema.type.split(",").map((t) => t.trim());
1430
2292
  const typeFunctions = [];
1431
2293
  const typeNames = [];
2294
+ const defaultTypeNames = [];
2295
+ let allTypesDefault = true;
1432
2296
  for (const type2 of types) {
1433
2297
  const validator = this.getType(type2);
1434
2298
  if (validator) {
1435
2299
  typeFunctions.push(validator);
1436
2300
  typeNames.push(validator.name);
2301
+ if (this.isDefaultTypeValidator(type2, validator)) {
2302
+ defaultTypeNames.push(type2);
2303
+ } else {
2304
+ allTypesDefault = false;
2305
+ }
1437
2306
  }
1438
2307
  }
1439
2308
  if (typeFunctions.length === 0) {
@@ -1445,7 +2314,118 @@ var SchemaShield = class {
1445
2314
  }
1446
2315
  let combinedTypeValidator;
1447
2316
  let typeMethodName = "";
1448
- if (typeFunctions.length === 1) {
2317
+ if (typeFunctions.length === 1 && allTypesDefault) {
2318
+ const singleTypeName = defaultTypeNames[0];
2319
+ typeMethodName = singleTypeName;
2320
+ switch (singleTypeName) {
2321
+ case "object":
2322
+ combinedTypeValidator = (data) => {
2323
+ if (data === null || typeof data !== "object" || Array.isArray(data)) {
2324
+ return defineTypeError("Invalid type", { data });
2325
+ }
2326
+ };
2327
+ break;
2328
+ case "array":
2329
+ combinedTypeValidator = (data) => {
2330
+ if (!Array.isArray(data)) {
2331
+ return defineTypeError("Invalid type", { data });
2332
+ }
2333
+ };
2334
+ break;
2335
+ case "string":
2336
+ combinedTypeValidator = (data) => {
2337
+ if (typeof data !== "string") {
2338
+ return defineTypeError("Invalid type", { data });
2339
+ }
2340
+ };
2341
+ break;
2342
+ case "number":
2343
+ combinedTypeValidator = (data) => {
2344
+ if (typeof data !== "number") {
2345
+ return defineTypeError("Invalid type", { data });
2346
+ }
2347
+ };
2348
+ break;
2349
+ case "integer":
2350
+ combinedTypeValidator = (data) => {
2351
+ if (typeof data !== "number" || !Number.isInteger(data)) {
2352
+ return defineTypeError("Invalid type", { data });
2353
+ }
2354
+ };
2355
+ break;
2356
+ case "boolean":
2357
+ combinedTypeValidator = (data) => {
2358
+ if (typeof data !== "boolean") {
2359
+ return defineTypeError("Invalid type", { data });
2360
+ }
2361
+ };
2362
+ break;
2363
+ case "null":
2364
+ combinedTypeValidator = (data) => {
2365
+ if (data !== null) {
2366
+ return defineTypeError("Invalid type", { data });
2367
+ }
2368
+ };
2369
+ break;
2370
+ default: {
2371
+ const singleTypeFn = typeFunctions[0];
2372
+ combinedTypeValidator = (data) => {
2373
+ if (!singleTypeFn(data)) {
2374
+ return defineTypeError("Invalid type", { data });
2375
+ }
2376
+ };
2377
+ }
2378
+ }
2379
+ } else if (typeFunctions.length > 1 && allTypesDefault) {
2380
+ typeMethodName = defaultTypeNames.join("_OR_");
2381
+ const allowsObject = defaultTypeNames.includes("object");
2382
+ const allowsArray = defaultTypeNames.includes("array");
2383
+ const allowsString = defaultTypeNames.includes("string");
2384
+ const allowsNumber = defaultTypeNames.includes("number");
2385
+ const allowsInteger = defaultTypeNames.includes("integer");
2386
+ const allowsBoolean = defaultTypeNames.includes("boolean");
2387
+ const allowsNull = defaultTypeNames.includes("null");
2388
+ combinedTypeValidator = (data) => {
2389
+ const dataType = typeof data;
2390
+ if (dataType === "number") {
2391
+ if (allowsNumber || allowsInteger && Number.isInteger(data)) {
2392
+ return;
2393
+ }
2394
+ return defineTypeError("Invalid type", { data });
2395
+ }
2396
+ if (dataType === "string") {
2397
+ if (allowsString) {
2398
+ return;
2399
+ }
2400
+ return defineTypeError("Invalid type", { data });
2401
+ }
2402
+ if (dataType === "boolean") {
2403
+ if (allowsBoolean) {
2404
+ return;
2405
+ }
2406
+ return defineTypeError("Invalid type", { data });
2407
+ }
2408
+ if (dataType === "object") {
2409
+ if (data === null) {
2410
+ if (allowsNull) {
2411
+ return;
2412
+ }
2413
+ return defineTypeError("Invalid type", { data });
2414
+ }
2415
+ if (Array.isArray(data)) {
2416
+ if (allowsArray) {
2417
+ return;
2418
+ }
2419
+ return defineTypeError("Invalid type", { data });
2420
+ }
2421
+ if (allowsObject) {
2422
+ return;
2423
+ }
2424
+ return defineTypeError("Invalid type", { data });
2425
+ }
2426
+ return defineTypeError("Invalid type", { data });
2427
+ };
2428
+ } else if (typeFunctions.length === 1) {
1449
2429
  typeMethodName = typeNames[0];
1450
2430
  const singleTypeFn = typeFunctions[0];
1451
2431
  combinedTypeValidator = (data) => {
@@ -1464,72 +2444,90 @@ var SchemaShield = class {
1464
2444
  return defineTypeError("Invalid type", { data });
1465
2445
  };
1466
2446
  }
1467
- const typeAdapter = (_s, data) => combinedTypeValidator(data);
1468
2447
  validators.push({
1469
- fn: getNamedFunction(typeMethodName, typeAdapter),
1470
- defineError: defineTypeError
2448
+ name: typeMethodName,
2449
+ validate: getNamedFunction(typeMethodName, combinedTypeValidator)
1471
2450
  });
1472
2451
  activeNames.push(typeMethodName);
1473
2452
  }
1474
2453
  const { type, $id, $ref, $validate, required, ...otherKeys } = schema;
1475
- const keyOrder = required ? [...Object.keys(otherKeys), "required"] : Object.keys(otherKeys);
2454
+ const keyOrder = required ? this.hasRequiredDefaults(schema) ? [...Object.keys(otherKeys), "required"] : ["required", ...Object.keys(otherKeys)] : Object.keys(otherKeys);
1476
2455
  for (const key of keyOrder) {
1477
2456
  const keywordFn = this.getKeyword(key);
1478
- if (keywordFn) {
1479
- const defineError = getDefinedErrorFunctionForKey(
1480
- key,
1481
- schema[key],
1482
- this.failFast
1483
- );
1484
- const fnName = keywordFn.name || key;
1485
- validators.push({
1486
- fn: keywordFn,
1487
- defineError
1488
- });
1489
- activeNames.push(fnName);
2457
+ if (!keywordFn) {
2458
+ continue;
1490
2459
  }
2460
+ if (this.shouldSkipKeyword(schema, key)) {
2461
+ continue;
2462
+ }
2463
+ const defineError = getDefinedErrorFunctionForKey(
2464
+ key,
2465
+ schema[key],
2466
+ this.failFast
2467
+ );
2468
+ const fnName = keywordFn.name || key;
2469
+ validators.push({
2470
+ name: fnName,
2471
+ validate: getNamedFunction(
2472
+ fnName,
2473
+ (data) => keywordFn(compiledSchema, data, defineError, this)
2474
+ )
2475
+ });
2476
+ activeNames.push(fnName);
1491
2477
  }
1492
2478
  const literalKeywords = ["enum", "const", "default", "examples"];
1493
2479
  for (const key of keyOrder) {
1494
2480
  if (literalKeywords.includes(key)) {
1495
2481
  continue;
1496
2482
  }
1497
- if (isObject(schema[key])) {
2483
+ if (schema[key] && typeof schema[key] === "object" && !Array.isArray(schema[key])) {
1498
2484
  if (key === "properties") {
1499
2485
  for (const subKey of Object.keys(schema[key])) {
1500
- compiledSchema[key][subKey] = this.compileSchema(
2486
+ const compiledSubSchema2 = this.compileSchema(
1501
2487
  schema[key][subKey]
1502
2488
  );
2489
+ if (compiledSubSchema2._hasRef === true) {
2490
+ schemaHasRef = true;
2491
+ }
2492
+ compiledSchema[key][subKey] = compiledSubSchema2;
1503
2493
  }
1504
2494
  continue;
1505
2495
  }
1506
- compiledSchema[key] = this.compileSchema(schema[key]);
2496
+ const compiledSubSchema = this.compileSchema(schema[key]);
2497
+ if (compiledSubSchema._hasRef === true) {
2498
+ schemaHasRef = true;
2499
+ }
2500
+ compiledSchema[key] = compiledSubSchema;
1507
2501
  continue;
1508
2502
  }
1509
2503
  if (Array.isArray(schema[key])) {
1510
2504
  for (let i = 0; i < schema[key].length; i++) {
1511
2505
  if (this.isSchemaLike(schema[key][i])) {
1512
- compiledSchema[key][i] = this.compileSchema(schema[key][i]);
2506
+ const compiledSubSchema = this.compileSchema(schema[key][i]);
2507
+ if (compiledSubSchema._hasRef === true) {
2508
+ schemaHasRef = true;
2509
+ }
2510
+ compiledSchema[key][i] = compiledSubSchema;
1513
2511
  }
1514
2512
  }
1515
2513
  continue;
1516
2514
  }
1517
2515
  }
2516
+ if (schemaHasRef) {
2517
+ this.markSchemaHasRef(compiledSchema);
2518
+ }
1518
2519
  if (validators.length === 0) {
1519
2520
  return compiledSchema;
1520
2521
  }
1521
2522
  if (validators.length === 1) {
1522
2523
  const v = validators[0];
1523
- compiledSchema.$validate = getNamedFunction(
1524
- activeNames[0],
1525
- (data) => v.fn(compiledSchema, data, v.defineError, this)
1526
- );
2524
+ compiledSchema.$validate = getNamedFunction(v.name, v.validate);
1527
2525
  } else {
1528
2526
  const compositeName = "Validate_" + activeNames.join("_AND_");
1529
2527
  const masterValidator = (data) => {
1530
2528
  for (let i = 0; i < validators.length; i++) {
1531
2529
  const v = validators[i];
1532
- const error = v.fn(compiledSchema, data, v.defineError, this);
2530
+ const error = v.validate(data);
1533
2531
  if (error) {
1534
2532
  return error;
1535
2533
  }
@@ -1544,7 +2542,7 @@ var SchemaShield = class {
1544
2542
  return compiledSchema;
1545
2543
  }
1546
2544
  isSchemaLike(subSchema) {
1547
- if (isObject(subSchema)) {
2545
+ if (subSchema && typeof subSchema === "object" && !Array.isArray(subSchema)) {
1548
2546
  if ("type" in subSchema) {
1549
2547
  return true;
1550
2548
  }
@@ -1610,5 +2608,5 @@ var SchemaShield = class {
1610
2608
  export {
1611
2609
  SchemaShield,
1612
2610
  ValidationError,
1613
- deepClone
2611
+ deepCloneUnfreeze as deepClone
1614
2612
  };