z-schema 12.3.1 → 12.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/z-schema +0 -0
- package/cjs/index.cjs +151 -29
- package/dist/format-validators.js +20 -10
- package/dist/json-schema.js +9 -3
- package/dist/json-validation.js +3 -2
- package/dist/report.d.ts +1 -1
- package/dist/schema-cache.d.ts +1 -1
- package/dist/schema-compiler.js +8 -4
- package/dist/utils/hostname.js +109 -5
- package/dist/utils/json.js +2 -1
- package/dist/utils/time.js +3 -3
- package/dist/validation/ref.js +1 -1
- package/dist/validation/shared.js +4 -2
- package/dist/validation/string.js +4 -4
- package/dist/z-schema-options.js +1 -1
- package/dist/z-schema.js +1 -1
- package/package.json +5 -5
- package/src/format-validators.ts +36 -10
- package/src/json-validation.ts +7 -7
- package/src/utils/base64.ts +1 -1
- package/src/utils/hostname.ts +230 -4
- package/src/utils/time.ts +3 -2
- package/src/validation/string.ts +7 -3
- package/umd/ZSchema.js +151 -29
- package/umd/ZSchema.min.js +2 -2
package/umd/ZSchema.js
CHANGED
|
@@ -71,7 +71,7 @@
|
|
|
71
71
|
function isInteger(value) {
|
|
72
72
|
return typeof value === "number" && Number.isFinite(value) && value % 1 === 0;
|
|
73
73
|
}
|
|
74
|
-
const NON_SCHEMA_KEYWORDS_SET = new Set([
|
|
74
|
+
const NON_SCHEMA_KEYWORDS_SET = /* @__PURE__ */ new Set([
|
|
75
75
|
"enum",
|
|
76
76
|
"const",
|
|
77
77
|
"default",
|
|
@@ -246,7 +246,8 @@
|
|
|
246
246
|
}
|
|
247
247
|
if (isObject(json1) && isObject(json2)) {
|
|
248
248
|
const keys1 = sortedKeys(json1);
|
|
249
|
-
|
|
249
|
+
const keys2 = sortedKeys(json2);
|
|
250
|
+
if (!areEqual(keys1, keys2, options, _depth + 1)) return false;
|
|
250
251
|
len = keys1.length;
|
|
251
252
|
for (i = 0; i < len; i++) if (!areEqual(json1[keys1[i]], json2[keys1[i]], options, _depth + 1)) return false;
|
|
252
253
|
return true;
|
|
@@ -2444,6 +2445,94 @@
|
|
|
2444
2445
|
})))(), 1);
|
|
2445
2446
|
const IDN_SEPARATOR_REGEX = /[\u3002\uFF0E\uFF61]/g;
|
|
2446
2447
|
const IDN_SEPARATOR_TEST_REGEX = /[\u3002\uFF0E\uFF61]/;
|
|
2448
|
+
const XN_LABEL_REGEX = /^xn--/i;
|
|
2449
|
+
const DISALLOWED_CATEGORY_REGEX = /[\p{P}\p{S}\p{Z}\p{C}]/u;
|
|
2450
|
+
const DISALLOWED_CATEGORY_WHITELIST = /* @__PURE__ */ new Set([
|
|
2451
|
+
"-",
|
|
2452
|
+
"·",
|
|
2453
|
+
"͵",
|
|
2454
|
+
"׳",
|
|
2455
|
+
"״",
|
|
2456
|
+
"・",
|
|
2457
|
+
"۽",
|
|
2458
|
+
"۾",
|
|
2459
|
+
"་",
|
|
2460
|
+
"",
|
|
2461
|
+
""
|
|
2462
|
+
]);
|
|
2463
|
+
const isDisallowedCodePoint = (char) => DISALLOWED_CATEGORY_REGEX.test(char) && !DISALLOWED_CATEGORY_WHITELIST.has(char);
|
|
2464
|
+
const TRANSPARENT_MARK_REGEX = /\p{Mn}/u;
|
|
2465
|
+
const ARABIC_SCRIPT_REGEX = /\p{Script=Arabic}/u;
|
|
2466
|
+
const ARABIC_INDIC_DIGITS_REGEX = /[\u0660-\u0669\u06F0-\u06F9]/;
|
|
2467
|
+
const isArabicJoiningLetter = (char) => char !== void 0 && ARABIC_SCRIPT_REGEX.test(char) && !ARABIC_INDIC_DIGITS_REGEX.test(char);
|
|
2468
|
+
const hasZwnjJoiningContext = (label, idx) => {
|
|
2469
|
+
let before = idx - 1;
|
|
2470
|
+
while (before >= 0 && TRANSPARENT_MARK_REGEX.test(label[before])) before--;
|
|
2471
|
+
let after = idx + 1;
|
|
2472
|
+
while (after < label.length && TRANSPARENT_MARK_REGEX.test(label[after])) after++;
|
|
2473
|
+
return isArabicJoiningLetter(label[before]) && isArabicJoiningLetter(label[after]);
|
|
2474
|
+
};
|
|
2475
|
+
const BIDI_NSM_REGEX = /[\p{Mn}\p{Me}]/u;
|
|
2476
|
+
const BIDI_ARABIC_INDIC_DIGIT_REGEX = /[\u0660-\u0669]/;
|
|
2477
|
+
const BIDI_EXTENDED_ARABIC_INDIC_DIGIT_REGEX = /[\u06F0-\u06F9]/;
|
|
2478
|
+
const BIDI_HEBREW_SCRIPT_REGEX = /\p{Script=Hebrew}/u;
|
|
2479
|
+
const BIDI_AL_SCRIPT_REGEX = /[\p{Script=Arabic}\p{Script=Syriac}\p{Script=Thaana}]/u;
|
|
2480
|
+
const BIDI_ASCII_DIGIT_REGEX = /[0-9]/;
|
|
2481
|
+
const BIDI_LETTER_REGEX = /\p{L}/u;
|
|
2482
|
+
const classifyBidi = (char) => {
|
|
2483
|
+
if (BIDI_NSM_REGEX.test(char)) return "NSM";
|
|
2484
|
+
if (BIDI_ARABIC_INDIC_DIGIT_REGEX.test(char)) return "AN";
|
|
2485
|
+
if (BIDI_EXTENDED_ARABIC_INDIC_DIGIT_REGEX.test(char)) return "EN";
|
|
2486
|
+
if (BIDI_HEBREW_SCRIPT_REGEX.test(char)) return "R";
|
|
2487
|
+
if (BIDI_AL_SCRIPT_REGEX.test(char)) return "AL";
|
|
2488
|
+
if (BIDI_ASCII_DIGIT_REGEX.test(char)) return "EN";
|
|
2489
|
+
if (BIDI_LETTER_REGEX.test(char)) return "L";
|
|
2490
|
+
return "ON";
|
|
2491
|
+
};
|
|
2492
|
+
const isLabelBidiTriggering = (label) => {
|
|
2493
|
+
for (const char of label) {
|
|
2494
|
+
const bidiClass = classifyBidi(char);
|
|
2495
|
+
if (bidiClass === "R" || bidiClass === "AL" || bidiClass === "AN") return true;
|
|
2496
|
+
}
|
|
2497
|
+
return false;
|
|
2498
|
+
};
|
|
2499
|
+
const isLabelBidiRuleValid = (label) => {
|
|
2500
|
+
const classes = [];
|
|
2501
|
+
for (const char of label) classes.push(classifyBidi(char));
|
|
2502
|
+
if (classes.length === 0) return false;
|
|
2503
|
+
const first = classes[0];
|
|
2504
|
+
if (first !== "L" && first !== "R" && first !== "AL") return false;
|
|
2505
|
+
let lastIdx = classes.length - 1;
|
|
2506
|
+
while (lastIdx > 0 && classes[lastIdx] === "NSM") lastIdx--;
|
|
2507
|
+
const last = classes[lastIdx];
|
|
2508
|
+
if (first === "R" || first === "AL") {
|
|
2509
|
+
let hasEN = false;
|
|
2510
|
+
let hasAN = false;
|
|
2511
|
+
for (let i = 0; i < classes.length; i++) {
|
|
2512
|
+
const c = classes[i];
|
|
2513
|
+
if (c !== "R" && c !== "AL" && c !== "AN" && c !== "EN" && c !== "NSM" && c !== "ON") return false;
|
|
2514
|
+
if (c === "EN") hasEN = true;
|
|
2515
|
+
else if (c === "AN") hasAN = true;
|
|
2516
|
+
}
|
|
2517
|
+
if (hasEN && hasAN) return false;
|
|
2518
|
+
return last === "R" || last === "AL" || last === "EN" || last === "AN";
|
|
2519
|
+
}
|
|
2520
|
+
for (let i = 0; i < classes.length; i++) {
|
|
2521
|
+
const c = classes[i];
|
|
2522
|
+
if (c !== "L" && c !== "EN" && c !== "NSM" && c !== "ON") return false;
|
|
2523
|
+
}
|
|
2524
|
+
return last === "L" || last === "EN";
|
|
2525
|
+
};
|
|
2526
|
+
const isDomainBidiValid = (unicodeLabels) => {
|
|
2527
|
+
let isBidiDomain = false;
|
|
2528
|
+
for (let i = 0; i < unicodeLabels.length; i++) if (isLabelBidiTriggering(unicodeLabels[i])) {
|
|
2529
|
+
isBidiDomain = true;
|
|
2530
|
+
break;
|
|
2531
|
+
}
|
|
2532
|
+
if (!isBidiDomain) return true;
|
|
2533
|
+
for (let i = 0; i < unicodeLabels.length; i++) if (!isLabelBidiRuleValid(unicodeLabels[i])) return false;
|
|
2534
|
+
return true;
|
|
2535
|
+
};
|
|
2447
2536
|
const splitHostnameLabels = (hostname) => {
|
|
2448
2537
|
if (hostname.length === 0 || hostname.length > 255) return null;
|
|
2449
2538
|
if (hostname.startsWith(".") || hostname.endsWith(".")) return null;
|
|
@@ -2459,7 +2548,7 @@
|
|
|
2459
2548
|
const isHebrew = (char) => /\p{Script=Hebrew}/u.test(char);
|
|
2460
2549
|
const hasCjkKanaOrHan = (input) => /[\p{Script=Hiragana}\p{Script=Katakana}\p{Script=Han}]/u.test(input);
|
|
2461
2550
|
const toUnicodeLabel = (label) => {
|
|
2462
|
-
if (
|
|
2551
|
+
if (!XN_LABEL_REGEX.test(label)) return label;
|
|
2463
2552
|
try {
|
|
2464
2553
|
return import_punycode.default.toUnicode(label.toLowerCase());
|
|
2465
2554
|
} catch {
|
|
@@ -2468,7 +2557,7 @@
|
|
|
2468
2557
|
};
|
|
2469
2558
|
const isValidIdnUnicodeLabel = (label) => {
|
|
2470
2559
|
if (label.startsWith("-") || label.endsWith("-")) return false;
|
|
2471
|
-
if (label.length >= 4 && label[2] === "-" && label[3] === "-" &&
|
|
2560
|
+
if (label.length >= 4 && label[2] === "-" && label[3] === "-" && !XN_LABEL_REGEX.test(label)) return false;
|
|
2472
2561
|
if (/^\p{M}/u.test(label)) return false;
|
|
2473
2562
|
if (/[\u302E\u302F\u0640\u07FA]/u.test(label)) return false;
|
|
2474
2563
|
for (let idx = 0; idx < label.length; idx++) {
|
|
@@ -2477,7 +2566,9 @@
|
|
|
2477
2566
|
if (char === "͵" && (idx === label.length - 1 || !isGreek(label[idx + 1]))) return false;
|
|
2478
2567
|
if ((char === "׳" || char === "״") && (idx === 0 || !isHebrew(label[idx - 1]))) return false;
|
|
2479
2568
|
if (char === "" && (idx === 0 || label[idx - 1] !== "्")) return false;
|
|
2569
|
+
if (char === "" && (idx === 0 || label[idx - 1] !== "्" && !hasZwnjJoiningContext(label, idx))) return false;
|
|
2480
2570
|
}
|
|
2571
|
+
for (const char of label) if (isDisallowedCodePoint(char)) return false;
|
|
2481
2572
|
if (label.includes("・") && !hasCjkKanaOrHan(label.replaceAll("・", ""))) return false;
|
|
2482
2573
|
const hasArabicIndic = /[\u0660-\u0669]/.test(label);
|
|
2483
2574
|
const hasExtendedArabicIndic = /[\u06F0-\u06F9]/.test(label);
|
|
@@ -2492,7 +2583,7 @@
|
|
|
2492
2583
|
for (let i = 0; i < labels.length; i++) {
|
|
2493
2584
|
const label = labels[i];
|
|
2494
2585
|
if (!isAsciiHostnameLabel(label)) return false;
|
|
2495
|
-
if (
|
|
2586
|
+
if (XN_LABEL_REGEX.test(label)) {
|
|
2496
2587
|
const unicodeLabel = toUnicodeLabel(label);
|
|
2497
2588
|
if (unicodeLabel === null || !isValidIdnUnicodeLabel(unicodeLabel)) return false;
|
|
2498
2589
|
}
|
|
@@ -2500,14 +2591,28 @@
|
|
|
2500
2591
|
return true;
|
|
2501
2592
|
};
|
|
2502
2593
|
const isValidIdnHostname = (hostname) => {
|
|
2503
|
-
const
|
|
2594
|
+
const normalizedHostname = hostname.replace(IDN_SEPARATOR_REGEX, ".");
|
|
2595
|
+
const labels = splitHostnameLabels(normalizedHostname);
|
|
2504
2596
|
if (labels === null) return false;
|
|
2597
|
+
const unicodeLabels = [];
|
|
2598
|
+
let totalLength = labels.length - 1;
|
|
2505
2599
|
for (let i = 0; i < labels.length; i++) {
|
|
2506
2600
|
const label = labels[i];
|
|
2507
2601
|
const unicodeLabel = toUnicodeLabel(label);
|
|
2508
2602
|
if (unicodeLabel === null || !isValidIdnUnicodeLabel(unicodeLabel)) return false;
|
|
2603
|
+
let aLabel;
|
|
2604
|
+
try {
|
|
2605
|
+
aLabel = import_punycode.default.toASCII(unicodeLabel);
|
|
2606
|
+
} catch {
|
|
2607
|
+
return false;
|
|
2608
|
+
}
|
|
2609
|
+
if (XN_LABEL_REGEX.test(label) && aLabel.toLowerCase() !== label.toLowerCase()) return false;
|
|
2610
|
+
if (aLabel.length > 63) return false;
|
|
2611
|
+
totalLength += aLabel.length;
|
|
2612
|
+
unicodeLabels.push(unicodeLabel);
|
|
2509
2613
|
}
|
|
2510
|
-
return
|
|
2614
|
+
if (totalLength > 253) return false;
|
|
2615
|
+
return isDomainBidiValid(unicodeLabels);
|
|
2511
2616
|
};
|
|
2512
2617
|
//#endregion
|
|
2513
2618
|
//#region src/utils/time.ts
|
|
@@ -2520,7 +2625,7 @@
|
|
|
2520
2625
|
minute: normalizedUtcTotalMinutes % 60
|
|
2521
2626
|
};
|
|
2522
2627
|
};
|
|
2523
|
-
const RFC3339_TIME_REGEX = /^([0-9]{2}):([0-9]{2}):([0-9]{2})(
|
|
2628
|
+
const RFC3339_TIME_REGEX = /^(?<hour>[0-9]{2}):(?<minute>[0-9]{2}):(?<second>[0-9]{2})(?<fraction>\.[0-9]+)?(?<offset>z|(?<offsetValue>[+-][0-9]{2}:[0-9]{2}))$/i;
|
|
2524
2629
|
const parseRfc3339Time = (time) => {
|
|
2525
2630
|
const matches = RFC3339_TIME_REGEX.exec(time);
|
|
2526
2631
|
if (matches === null) return null;
|
|
@@ -2531,7 +2636,7 @@
|
|
|
2531
2636
|
let utcHour = hour;
|
|
2532
2637
|
let utcMinute = minute;
|
|
2533
2638
|
if (matches[5].toLowerCase() !== "z") {
|
|
2534
|
-
const offsetMatches = /^([+-])([0-9]{2}):([0-9]{2})$/.exec(matches[5]);
|
|
2639
|
+
const offsetMatches = /^(?<sign>[+-])(?<hour>[0-9]{2}):(?<minute>[0-9]{2})$/.exec(matches[5]);
|
|
2535
2640
|
if (offsetMatches === null) return null;
|
|
2536
2641
|
const offsetSign = offsetMatches[1];
|
|
2537
2642
|
const offsetHour = Number.parseInt(offsetMatches[2], 10);
|
|
@@ -2554,7 +2659,7 @@
|
|
|
2554
2659
|
//#region src/format-validators.ts
|
|
2555
2660
|
const dateValidator = (date) => {
|
|
2556
2661
|
if (typeof date !== "string") return true;
|
|
2557
|
-
const matches = /^([0-9]{4})-([0-9]{2})-([0-9]{2})$/.exec(date);
|
|
2662
|
+
const matches = /^(?<year>[0-9]{4})-(?<month>[0-9]{2})-(?<day>[0-9]{2})$/.exec(date);
|
|
2558
2663
|
if (matches === null) return false;
|
|
2559
2664
|
return isValidRfc3339Date(Number.parseInt(matches[1], 10), Number.parseInt(matches[2], 10), Number.parseInt(matches[3], 10));
|
|
2560
2665
|
};
|
|
@@ -2565,7 +2670,7 @@
|
|
|
2565
2670
|
if (tIdx === -1) return false;
|
|
2566
2671
|
const datePart = dateTime.slice(0, tIdx);
|
|
2567
2672
|
const timePart = dateTime.slice(tIdx + 1);
|
|
2568
|
-
const dateMatches = /^([0-9]{4})-([0-9]{2})-([0-9]{2})$/.exec(datePart);
|
|
2673
|
+
const dateMatches = /^(?<year>[0-9]{4})-(?<month>[0-9]{2})-(?<day>[0-9]{2})$/.exec(datePart);
|
|
2569
2674
|
if (dateMatches === null) return false;
|
|
2570
2675
|
if (!isValidRfc3339Date(Number.parseInt(dateMatches[1], 10), Number.parseInt(dateMatches[2], 10), Number.parseInt(dateMatches[3], 10))) return false;
|
|
2571
2676
|
return parseRfc3339Time(timePart) !== null;
|
|
@@ -2576,7 +2681,7 @@
|
|
|
2576
2681
|
require_tld: true,
|
|
2577
2682
|
allow_ip_domain: true
|
|
2578
2683
|
})) return true;
|
|
2579
|
-
const ipv6Literal = /^(
|
|
2684
|
+
const ipv6Literal = /^(?<localPart>.+)@\[IPv6:(?<address>[^\]]+)\]$/i.exec(email);
|
|
2580
2685
|
if (!ipv6Literal) return false;
|
|
2581
2686
|
const localPart = ipv6Literal[1];
|
|
2582
2687
|
const addressPart = ipv6Literal[2];
|
|
@@ -2596,7 +2701,7 @@
|
|
|
2596
2701
|
if (ipv6.includes("%")) return false;
|
|
2597
2702
|
return import_isIP.default.default(ipv6, 6);
|
|
2598
2703
|
};
|
|
2599
|
-
const INVALID_REGEX_ESCAPES = new Set(["a"]);
|
|
2704
|
+
const INVALID_REGEX_ESCAPES = /* @__PURE__ */ new Set(["a"]);
|
|
2600
2705
|
const regexValidator = (input) => {
|
|
2601
2706
|
if (typeof input !== "string") return true;
|
|
2602
2707
|
for (let idx = 0; idx < input.length; idx++) {
|
|
@@ -2649,7 +2754,7 @@
|
|
|
2649
2754
|
if (typeof uri !== "string") return true;
|
|
2650
2755
|
if (/[^\u0000-\u007F]/.test(uri)) return false;
|
|
2651
2756
|
if (!hasValidPercentEncoding(uri)) return false;
|
|
2652
|
-
const match = /^([a-zA-Z][a-zA-Z0-9+.-]*):\/\/([^/?#]*)/.exec(uri);
|
|
2757
|
+
const match = /^(?<scheme>[a-zA-Z][a-zA-Z0-9+.-]*):\/\/(?<authority>[^/?#]*)/.exec(uri);
|
|
2653
2758
|
if (match) {
|
|
2654
2759
|
const authority = match[2];
|
|
2655
2760
|
const atIndex = authority.indexOf("@");
|
|
@@ -2673,11 +2778,11 @@
|
|
|
2673
2778
|
const uriReferenceValidator = (uri) => {
|
|
2674
2779
|
if (typeof uri !== "string") return true;
|
|
2675
2780
|
if (/[^\u0000-\u007F]/.test(uri)) return false;
|
|
2676
|
-
return /^([a-zA-Z][a-zA-Z0-9+.-]*:)?[^"\\<>^{}^`| ]*$/.test(uri);
|
|
2781
|
+
return /^(?:[a-zA-Z][a-zA-Z0-9+.-]*:)?[^"\\<>^{}^`| ]*$/.test(uri);
|
|
2677
2782
|
};
|
|
2678
2783
|
const uriTemplateValidator = (uri) => {
|
|
2679
2784
|
if (typeof uri !== "string") return true;
|
|
2680
|
-
if (!/^([a-zA-Z][a-zA-Z0-9+.-]*:)?[^"\\<>^`| ]*$/.test(uri)) return false;
|
|
2785
|
+
if (!/^(?:[a-zA-Z][a-zA-Z0-9+.-]*:)?[^"\\<>^`| ]*$/.test(uri)) return false;
|
|
2681
2786
|
let inExpression = false;
|
|
2682
2787
|
for (let idx = 0; idx < uri.length; idx++) {
|
|
2683
2788
|
const ch = uri[idx];
|
|
@@ -2709,7 +2814,7 @@
|
|
|
2709
2814
|
};
|
|
2710
2815
|
const relativeJsonPointerValidator = (pointer) => {
|
|
2711
2816
|
if (typeof pointer !== "string") return true;
|
|
2712
|
-
const match = /^(0|[1-9]\d*)(
|
|
2817
|
+
const match = /^(?<int>0|[1-9]\d*)(?<suffix>.*)$/.exec(pointer);
|
|
2713
2818
|
if (!match) return false;
|
|
2714
2819
|
const suffix = match[2];
|
|
2715
2820
|
if (suffix === "" || suffix === "#") return true;
|
|
@@ -2723,9 +2828,19 @@
|
|
|
2723
2828
|
if (typeof time !== "string") return true;
|
|
2724
2829
|
return parseRfc3339Time(time) !== null;
|
|
2725
2830
|
};
|
|
2831
|
+
const LONE_SURROGATE_REGEX = /[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:^|[^\uD800-\uDBFF])[\uDC00-\uDFFF]/;
|
|
2832
|
+
const QUOTED_LOCAL_PART_REGEX = /^"(?:[^"\\]|\\.)*"$/u;
|
|
2833
|
+
const UNQUOTED_LOCAL_PART_REGEX = /^[^\s@]+$/u;
|
|
2834
|
+
const isValidIdnEmailLocalPart = (localPart) => {
|
|
2835
|
+
if (localPart.length === 0 || LONE_SURROGATE_REGEX.test(localPart)) return false;
|
|
2836
|
+
if (localPart.length >= 2 && localPart.startsWith("\"") && localPart.endsWith("\"")) return QUOTED_LOCAL_PART_REGEX.test(localPart);
|
|
2837
|
+
return UNQUOTED_LOCAL_PART_REGEX.test(localPart);
|
|
2838
|
+
};
|
|
2726
2839
|
const idnEmailValidator = (email) => {
|
|
2727
2840
|
if (typeof email !== "string") return true;
|
|
2728
|
-
|
|
2841
|
+
const atIdx = email.lastIndexOf("@");
|
|
2842
|
+
if (atIdx <= 0 || atIdx === email.length - 1) return false;
|
|
2843
|
+
return isValidIdnEmailLocalPart(email.slice(0, atIdx)) && isValidIdnHostname(email.slice(atIdx + 1));
|
|
2729
2844
|
};
|
|
2730
2845
|
const idnHostnameValidator = (hostname) => {
|
|
2731
2846
|
if (typeof hostname !== "string") return true;
|
|
@@ -2743,7 +2858,7 @@
|
|
|
2743
2858
|
};
|
|
2744
2859
|
const iriReferenceValidator = (iriReference) => {
|
|
2745
2860
|
if (typeof iriReference !== "string") return true;
|
|
2746
|
-
return /^([a-zA-Z][a-zA-Z0-9+.-]*:)?[^"\\<>^{}^`| ]*$/u.test(iriReference);
|
|
2861
|
+
return /^(?:[a-zA-Z][a-zA-Z0-9+.-]*:)?[^"\\<>^{}^`| ]*$/u.test(iriReference);
|
|
2747
2862
|
};
|
|
2748
2863
|
const inbuiltValidators = {
|
|
2749
2864
|
date: dateValidator,
|
|
@@ -3778,7 +3893,7 @@
|
|
|
3778
3893
|
const VOCAB_VALIDATION_2020_12 = "https://json-schema.org/draft/2020-12/vocab/validation";
|
|
3779
3894
|
const VOCAB_FORMAT_2019_09 = "https://json-schema.org/draft/2019-09/vocab/format";
|
|
3780
3895
|
const VOCAB_FORMAT_ASSERTION_2020_12 = "https://json-schema.org/draft/2020-12/vocab/format-assertion";
|
|
3781
|
-
const VALIDATION_VOCAB_KEYWORDS = new Set([
|
|
3896
|
+
const VALIDATION_VOCAB_KEYWORDS = /* @__PURE__ */ new Set([
|
|
3782
3897
|
"type",
|
|
3783
3898
|
"multipleOf",
|
|
3784
3899
|
"maximum",
|
|
@@ -3809,7 +3924,9 @@
|
|
|
3809
3924
|
const metaSchema = currentSchemaMeta || rootSchemaMeta;
|
|
3810
3925
|
if (!metaSchema || typeof metaSchema !== "object" || !isObject(metaSchema.$vocabulary)) return true;
|
|
3811
3926
|
const vocabulary = metaSchema.$vocabulary;
|
|
3812
|
-
|
|
3927
|
+
const has2019 = Object.hasOwn(vocabulary, VOCAB_VALIDATION_2019_09);
|
|
3928
|
+
const has2020 = Object.hasOwn(vocabulary, VOCAB_VALIDATION_2020_12);
|
|
3929
|
+
if (has2019 || has2020) return vocabulary[VOCAB_VALIDATION_2019_09] || vocabulary[VOCAB_VALIDATION_2020_12];
|
|
3813
3930
|
return false;
|
|
3814
3931
|
};
|
|
3815
3932
|
/**
|
|
@@ -4245,11 +4362,11 @@
|
|
|
4245
4362
|
if (result instanceof Promise) {
|
|
4246
4363
|
const promiseResult = result;
|
|
4247
4364
|
report.addAsyncTaskWithPath(async (callback) => {
|
|
4365
|
+
let resolved = false;
|
|
4248
4366
|
try {
|
|
4249
|
-
|
|
4250
|
-
} catch {
|
|
4251
|
-
|
|
4252
|
-
}
|
|
4367
|
+
resolved = await promiseResult;
|
|
4368
|
+
} catch {}
|
|
4369
|
+
callback(resolved);
|
|
4253
4370
|
}, [], (resolvedResult) => {
|
|
4254
4371
|
if (resolvedResult !== true) report.addError("INVALID_FORMAT", [schema.format, JSON.stringify(json)], void 0, schema, "format");
|
|
4255
4372
|
});
|
|
@@ -4742,7 +4859,8 @@
|
|
|
4742
4859
|
}
|
|
4743
4860
|
}
|
|
4744
4861
|
if (deferredUnevaluatedKeys.length > 0 && !(report.errors.length > 0 && ctx.options.breakOnFirstError)) for (let i = 0; i < deferredUnevaluatedKeys.length; i++) {
|
|
4745
|
-
const
|
|
4862
|
+
const key = deferredUnevaluatedKeys[i];
|
|
4863
|
+
const validator = JsonValidators[key];
|
|
4746
4864
|
if (validator) {
|
|
4747
4865
|
validator(ctx, report, schema, json);
|
|
4748
4866
|
if (report.errors.length && ctx.options.breakOnFirstError) break;
|
|
@@ -4769,7 +4887,7 @@
|
|
|
4769
4887
|
}
|
|
4770
4888
|
//#endregion
|
|
4771
4889
|
//#region src/schema-compiler.ts
|
|
4772
|
-
const UNSAFE_TARGETS = new Set([
|
|
4890
|
+
const UNSAFE_TARGETS = /* @__PURE__ */ new Set([
|
|
4773
4891
|
Object.prototype,
|
|
4774
4892
|
Function.prototype,
|
|
4775
4893
|
Array.prototype
|
|
@@ -4851,7 +4969,10 @@
|
|
|
4851
4969
|
}
|
|
4852
4970
|
}
|
|
4853
4971
|
id.absoluteParent = absoluteParent;
|
|
4854
|
-
if (id.absoluteParent)
|
|
4972
|
+
if (id.absoluteParent) {
|
|
4973
|
+
const parentUri = id.absoluteParent.absoluteUri || id.absoluteParent.id;
|
|
4974
|
+
id.absoluteUri = resolveSchemaScopeId(parentUri, schemaNode, id.id);
|
|
4975
|
+
}
|
|
4855
4976
|
}
|
|
4856
4977
|
ids.push(id);
|
|
4857
4978
|
scope.push(id);
|
|
@@ -4935,7 +5056,8 @@
|
|
|
4935
5056
|
for (const item of ids) if (item.absoluteUri) {
|
|
4936
5057
|
this.validator.scache.cacheSchemaByUri(item.absoluteUri, item.obj);
|
|
4937
5058
|
if (item.type === "relative" && item.absoluteParent && isSimpleIdentifier(item.id)) {
|
|
4938
|
-
const
|
|
5059
|
+
const parentUri = item.absoluteParent.absoluteUri || item.absoluteParent.id;
|
|
5060
|
+
const altAbsoluteUri = resolveReference(parentUri, item.id);
|
|
4939
5061
|
this.validator.scache.cacheSchemaByUri(altAbsoluteUri, item.obj);
|
|
4940
5062
|
}
|
|
4941
5063
|
} else if (item.type === "root") this.validator.scache.cacheSchemaByUri(item.id, item.obj);
|