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.
- package/README.md +38 -12
- package/dist/formats.d.ts.map +1 -1
- package/dist/index.d.ts +14 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1445 -447
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/dist/index.mjs +1445 -447
- package/dist/keywords/array-keywords.d.ts.map +1 -1
- package/dist/keywords/object-keywords.d.ts.map +1 -1
- package/dist/keywords/other-keywords.d.ts.map +1 -1
- package/dist/keywords/string-keywords.d.ts.map +1 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/deep-freeze.d.ts +5 -0
- package/dist/utils/deep-freeze.d.ts.map +1 -0
- package/dist/utils/has-changed.d.ts +2 -0
- package/dist/utils/has-changed.d.ts.map +1 -0
- package/dist/utils/index.d.ts +5 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/{utils.d.ts → utils/main-utils.d.ts} +3 -6
- package/dist/utils/main-utils.d.ts.map +1 -0
- package/dist/utils/pattern-matcher.d.ts +3 -0
- package/dist/utils/pattern-matcher.d.ts.map +1 -0
- package/lib/formats.ts +402 -84
- package/lib/index.ts +494 -46
- package/lib/keywords/array-keywords.ts +215 -21
- package/lib/keywords/number-keywords.ts +1 -1
- package/lib/keywords/object-keywords.ts +218 -113
- package/lib/keywords/other-keywords.ts +229 -76
- package/lib/keywords/string-keywords.ts +97 -7
- package/lib/types.ts +4 -5
- package/lib/utils/deep-freeze.ts +208 -0
- package/lib/utils/has-changed.ts +51 -0
- package/lib/utils/index.ts +4 -0
- package/lib/utils/main-utils.ts +190 -0
- package/lib/utils/pattern-matcher.ts +66 -0
- package/package.json +1 -1
- package/dist/utils.d.ts.map +0 -1
- package/lib/utils.ts +0 -362
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"array-keywords.d.ts","sourceRoot":"","sources":["../../lib/keywords/array-keywords.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"array-keywords.d.ts","sourceRoot":"","sources":["../../lib/keywords/array-keywords.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AA+F3C,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAkTzD,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"object-keywords.d.ts","sourceRoot":"","sources":["../../lib/keywords/object-keywords.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"object-keywords.d.ts","sourceRoot":"","sources":["../../lib/keywords/object-keywords.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AA8F3C,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,GAAG,KAAK,CA2YlE,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"other-keywords.d.ts","sourceRoot":"","sources":["../../lib/keywords/other-keywords.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"other-keywords.d.ts","sourceRoot":"","sources":["../../lib/keywords/other-keywords.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAkD3C,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CA0UzD,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"string-keywords.d.ts","sourceRoot":"","sources":["../../lib/keywords/string-keywords.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,eAAe,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"string-keywords.d.ts","sourceRoot":"","sources":["../../lib/keywords/string-keywords.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,eAAe,EAAE,MAAM,UAAU,CAAC;AAM3D,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAiK1D,CAAC"}
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../lib/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../lib/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEvC,eAAO,MAAM,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,GAAG,KAAK,CAiCtD,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare function deepFreeze(obj: any, freezeClassInstances?: boolean, seen?: WeakSet<object>): any;
|
|
2
|
+
declare function isPlainObject(value: any): boolean;
|
|
3
|
+
export { isPlainObject };
|
|
4
|
+
export declare function deepCloneUnfreeze<T>(obj: T, cloneClassInstances?: boolean, seen?: WeakMap<object, any>): T;
|
|
5
|
+
//# sourceMappingURL=deep-freeze.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deep-freeze.d.ts","sourceRoot":"","sources":["../../lib/utils/deep-freeze.ts"],"names":[],"mappings":"AAAA,wBAAgB,UAAU,CACxB,GAAG,EAAE,GAAG,EACR,oBAAoB,GAAE,OAAe,EACrC,IAAI,kBAAgB,GACnB,GAAG,CAkCL;AAED,iBAAS,aAAa,CAAC,KAAK,EAAE,GAAG,GAAG,OAAO,CAO1C;AAED,OAAO,EAAE,aAAa,EAAE,CAAC;AAuBzB,wBAAgB,iBAAiB,CAAC,CAAC,EACjC,GAAG,EAAE,CAAC,EACN,mBAAmB,UAAQ,EAC3B,IAAI,uBAAgB,GACnB,CAAC,CAmIH"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"has-changed.d.ts","sourceRoot":"","sources":["../../lib/utils/has-changed.ts"],"names":[],"mappings":"AAEA,wBAAgB,UAAU,CAAC,IAAI,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,WAgDjD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../lib/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,OAAO,EAAE,iBAAiB,IAAI,SAAS,EAAE,MAAM,eAAe,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CompiledSchema } from "
|
|
1
|
+
import { CompiledSchema } from "../index";
|
|
2
2
|
interface ErrorTree {
|
|
3
3
|
message: string;
|
|
4
4
|
keyword: string;
|
|
@@ -35,13 +35,10 @@ export interface DefineErrorFunction {
|
|
|
35
35
|
(message: string, options?: DefineErrorOptions): ValidationError | void | true;
|
|
36
36
|
}
|
|
37
37
|
export declare function getDefinedErrorFunctionForKey(key: string, schema: CompiledSchema, failFast: boolean): DefineErrorFunction;
|
|
38
|
-
export declare function hasChanged(prev: any, current: any): boolean;
|
|
39
|
-
export declare function isObject(data: any): boolean;
|
|
40
|
-
export declare function areCloseEnough(a: any, b: any, epsilon?: number): boolean;
|
|
41
38
|
export declare function getUTF16Length(str: any): number;
|
|
42
|
-
export declare function deepClone<T>(obj: T, cloneClassInstances?: boolean, seen?: WeakMap<object, any>): T;
|
|
43
39
|
export declare function isCompiledSchema(subSchema: any): subSchema is CompiledSchema;
|
|
44
40
|
export declare function getNamedFunction<T>(name: string, fn: T): T;
|
|
45
41
|
export declare function resolvePath(root: any, path: string): any;
|
|
42
|
+
export declare function areCloseEnough(a: number, b: number, epsilon?: number): boolean;
|
|
46
43
|
export {};
|
|
47
|
-
//# sourceMappingURL=utils.d.ts.map
|
|
44
|
+
//# sourceMappingURL=main-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"main-utils.d.ts","sourceRoot":"","sources":["../../lib/utils/main-utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAE1C,UAAU,SAAS;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,GAAG,CAAC;IACX,KAAK,CAAC,EAAE,SAAS,CAAC;CACnB;AAED,qBAAa,eAAgB,SAAQ,KAAK;IACxC,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,UAAU,EAAE,MAAM,CAAM;IACxB,YAAY,EAAE,MAAM,CAAM;IAC1B,IAAI,CAAC,EAAE,GAAG,CAAC;IACX,MAAM,CAAC,EAAE,cAAc,CAAC;IAExB,OAAO,CAAC,SAAS;IAqBjB,QAAQ,IAAI,eAAe;IAI3B,OAAO,CAAC,QAAQ;IAiBhB,OAAO,IAAI,SAAS;IAKpB,OAAO;;;;CAOR;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,CAAC,EAAE,GAAG,CAAC;IACX,KAAK,CAAC,EAAE,eAAe,GAAG,IAAI,CAAC;IAC/B,IAAI,CAAC,EAAE,GAAG,CAAC;CACZ;AAED,MAAM,WAAW,mBAAmB;IAClC,CACE,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,kBAAkB,GAC3B,eAAe,GAAG,IAAI,GAAG,IAAI,CAAC;CAClC;AAGD,wBAAgB,6BAA6B,CAC3C,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,cAAc,EACtB,QAAQ,EAAE,OAAO,uBAuBlB;AAED,wBAAgB,cAAc,CAAC,GAAG,KAAA,UAUjC;AAED,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,GAAG,GAAG,SAAS,IAAI,cAAc,CAO5E;AAED,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,GAAG,CAAC,CAE1D;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,GAAG,GAAG,CAwCxD;AAED,wBAAgB,cAAc,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,OAAO,SAAQ,GAAG,OAAO,CAE7E"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pattern-matcher.d.ts","sourceRoot":"","sources":["../../lib/utils/pattern-matcher.ts"],"names":[],"mappings":"AAQA,MAAM,MAAM,sBAAsB,GAAG,MAAM,GAAG,CAAC,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC;AAE3E,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,sBAAsB,CAuD7E"}
|
package/lib/formats.ts
CHANGED
|
@@ -6,53 +6,409 @@ const UUID_REGEX =
|
|
|
6
6
|
// ISO 8601 Duration (P3Y6M4DT12H30M5S)
|
|
7
7
|
const DURATION_REGEX =
|
|
8
8
|
/^P(?!$)((\d+Y)?(\d+M)?(\d+W)?(\d+D)?)(T(?=\d)(\d+H)?(\d+M)?(\d+S)?)?$/;
|
|
9
|
-
const DATE_TIME_REGEX =
|
|
10
|
-
/^(\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;
|
|
11
9
|
const URI_REGEX = /^[a-zA-Z][a-zA-Z0-9+\-.]*:[^\s]*$/;
|
|
12
10
|
const EMAIL_REGEX =
|
|
13
11
|
/^(?!\.)(?!.*\.$)[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;
|
|
14
|
-
const IPV4_REGEX =
|
|
15
|
-
/^(?:(?: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])$/;
|
|
16
|
-
const IPV6_REGEX = /(?:\s+|:::+|^\w{5,}|\w{5}$|^:{1}\w|\w:{1}$)/;
|
|
17
|
-
const IPV6_SHORT_REGEX = /^[0-9a-fA-F:.]*$/;
|
|
18
|
-
const IPV6_FULL_REGEX = /^(?:(?:[0-9a-fA-F]{1,4}:){7}(?:[0-9a-fA-F]{1,4}|:))$/;
|
|
19
|
-
const IPV6_INVALID_CHAR_REGEX = /(?:[0-9a-fA-F]{5,}|\D[0-9a-fA-F]{3}:)/;
|
|
20
|
-
const IPV6_FAST_FAIL_REGEX =
|
|
21
|
-
/^(?:(?:(?:[0-9a-fA-F]{1,4}(?::|$)){1,6}))|(?:::(?:[0-9a-fA-F]{1,4})){0,5}$/;
|
|
22
12
|
const HOSTNAME_REGEX =
|
|
23
13
|
/^[a-z0-9][a-z0-9-]{0,62}(?:\.[a-z0-9][a-z0-9-]{0,62})*[a-z0-9]$/i;
|
|
24
14
|
const DATE_REGEX = /^(\d{4})-(\d{2})-(\d{2})$/;
|
|
25
|
-
const JSON_POINTER_REGEX = /^\/(?:[^~]|~0|~1)*$/;
|
|
26
|
-
const RELATIVE_JSON_POINTER_REGEX = /^([0-9]+)(#|\/(?:[^~]|~0|~1)*)?$/;
|
|
27
15
|
const TIME_REGEX =
|
|
28
16
|
/^([01]\d|2[0-3]):([0-5]\d):([0-5]\d)(\.\d+)?(Z|([+-])([01]\d|2[0-3]):([0-5]\d))$/;
|
|
29
17
|
const URI_REFERENCE_REGEX =
|
|
30
18
|
/^(([^:/?#]+):)?(\/\/([^/?#]*))?([^?#]*)(\?([^#]*))?(#((?![^#]*\\)[^#]*))?/i;
|
|
31
|
-
const URI_TEMPLATE_REGEX = /^(?:[^{}]|\{[^}]+\})*$/;
|
|
32
19
|
const IRI_REGEX = /^[a-zA-Z][a-zA-Z0-9+\-.]*:[^\s]*$/;
|
|
33
20
|
const IRI_REFERENCE_REGEX =
|
|
34
21
|
/^(([^:/?#]+):)?(\/\/([^/?#]*))?([^?#]*)(\?([^#]*))?(#((?![^#]*\\)[^#]*))?/i;
|
|
35
22
|
const IDN_EMAIL_REGEX = /^[^@\s]+@[^@\s]+\.[^@\s]+$/;
|
|
36
23
|
const IDN_HOSTNAME_REGEX = /^[^\s!@#$%^&*()_+\=\[\]{};':"\\|,<>\/?]+$/;
|
|
37
|
-
const BACK_SLASH_REGEX = /\\/;
|
|
38
24
|
|
|
39
25
|
const DAYS_IN_MONTH = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
|
|
40
26
|
|
|
27
|
+
function isDigitCharCode(code: number) {
|
|
28
|
+
return code >= 48 && code <= 57;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function parseTwoDigits(data: string, index: number) {
|
|
32
|
+
const first = data.charCodeAt(index) - 48;
|
|
33
|
+
const second = data.charCodeAt(index + 1) - 48;
|
|
34
|
+
|
|
35
|
+
if (first < 0 || first > 9 || second < 0 || second > 9) {
|
|
36
|
+
return -1;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return first * 10 + second;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function parseFourDigits(data: string, index: number) {
|
|
43
|
+
const a = data.charCodeAt(index) - 48;
|
|
44
|
+
const b = data.charCodeAt(index + 1) - 48;
|
|
45
|
+
const c = data.charCodeAt(index + 2) - 48;
|
|
46
|
+
const d = data.charCodeAt(index + 3) - 48;
|
|
47
|
+
|
|
48
|
+
if (
|
|
49
|
+
a < 0 ||
|
|
50
|
+
a > 9 ||
|
|
51
|
+
b < 0 ||
|
|
52
|
+
b > 9 ||
|
|
53
|
+
c < 0 ||
|
|
54
|
+
c > 9 ||
|
|
55
|
+
d < 0 ||
|
|
56
|
+
d > 9
|
|
57
|
+
) {
|
|
58
|
+
return -1;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return a * 1000 + b * 100 + c * 10 + d;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function isValidIpv4Range(data: string, start: number, end: number) {
|
|
65
|
+
let segmentCount = 0;
|
|
66
|
+
let segmentStart = start;
|
|
67
|
+
|
|
68
|
+
for (let i = start; i <= end; i++) {
|
|
69
|
+
if (i !== end && data.charCodeAt(i) !== 46) {
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const segmentLength = i - segmentStart;
|
|
74
|
+
if (segmentLength < 1 || segmentLength > 3) {
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (segmentLength > 1 && data.charCodeAt(segmentStart) === 48) {
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
let value = 0;
|
|
83
|
+
for (let j = segmentStart; j < i; j++) {
|
|
84
|
+
const digit = data.charCodeAt(j) - 48;
|
|
85
|
+
if (digit < 0 || digit > 9) {
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
value = value * 10 + digit;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (value > 255) {
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
segmentCount++;
|
|
97
|
+
segmentStart = i + 1;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return segmentCount === 4;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function isValidIpv4(data: string) {
|
|
104
|
+
return isValidIpv4Range(data, 0, data.length);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function isHexCharCode(code: number) {
|
|
108
|
+
return (
|
|
109
|
+
(code >= 48 && code <= 57) ||
|
|
110
|
+
(code >= 65 && code <= 70) ||
|
|
111
|
+
(code >= 97 && code <= 102)
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function isValidIpv6(data: string) {
|
|
116
|
+
const length = data.length;
|
|
117
|
+
if (length === 0) {
|
|
118
|
+
return false;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
let hasColon = false;
|
|
122
|
+
let hasDoubleColon = false;
|
|
123
|
+
let hextetCount = 0;
|
|
124
|
+
let i = 0;
|
|
125
|
+
|
|
126
|
+
while (i < length) {
|
|
127
|
+
if (data.charCodeAt(i) === 58) {
|
|
128
|
+
hasColon = true;
|
|
129
|
+
|
|
130
|
+
if (i + 1 < length && data.charCodeAt(i + 1) === 58) {
|
|
131
|
+
if (hasDoubleColon) {
|
|
132
|
+
return false;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
hasDoubleColon = true;
|
|
136
|
+
i += 2;
|
|
137
|
+
|
|
138
|
+
if (i === length) {
|
|
139
|
+
break;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
continue;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
return false;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
const segmentStart = i;
|
|
149
|
+
let segmentLength = 0;
|
|
150
|
+
|
|
151
|
+
while (i < length && isHexCharCode(data.charCodeAt(i))) {
|
|
152
|
+
segmentLength++;
|
|
153
|
+
if (segmentLength > 4) {
|
|
154
|
+
return false;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
i++;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
if (segmentLength === 0) {
|
|
161
|
+
return false;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
if (i < length && data.charCodeAt(i) === 46) {
|
|
165
|
+
if (!hasColon) {
|
|
166
|
+
return false;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
if (!isValidIpv4Range(data, segmentStart, length)) {
|
|
170
|
+
return false;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
if (hasDoubleColon) {
|
|
174
|
+
return hextetCount < 6;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
return hextetCount === 6;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
hextetCount++;
|
|
181
|
+
if (hextetCount > 8) {
|
|
182
|
+
return false;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
if (i === length) {
|
|
186
|
+
break;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
if (data.charCodeAt(i) !== 58) {
|
|
190
|
+
return false;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
hasColon = true;
|
|
194
|
+
i++;
|
|
195
|
+
|
|
196
|
+
if (i === length) {
|
|
197
|
+
return false;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
if (data.charCodeAt(i) === 58) {
|
|
201
|
+
if (hasDoubleColon) {
|
|
202
|
+
return false;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
hasDoubleColon = true;
|
|
206
|
+
i++;
|
|
207
|
+
|
|
208
|
+
if (i === length) {
|
|
209
|
+
break;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
if (!hasColon) {
|
|
215
|
+
return false;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
if (hasDoubleColon) {
|
|
219
|
+
return hextetCount < 8;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
return hextetCount === 8;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
function isValidJsonPointer(data: string) {
|
|
226
|
+
if (data === "") {
|
|
227
|
+
return true;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
if (data.charCodeAt(0) !== 47) {
|
|
231
|
+
return false;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
for (let i = 1; i < data.length; i++) {
|
|
235
|
+
if (data.charCodeAt(i) !== 126) {
|
|
236
|
+
continue;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
const next = data.charCodeAt(i + 1);
|
|
240
|
+
if (next !== 48 && next !== 49) {
|
|
241
|
+
return false;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
i++;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
return true;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
function isValidRelativeJsonPointer(data: string) {
|
|
251
|
+
if (data.length === 0) {
|
|
252
|
+
return true;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
let i = 0;
|
|
256
|
+
while (i < data.length) {
|
|
257
|
+
const code = data.charCodeAt(i);
|
|
258
|
+
if (code < 48 || code > 57) {
|
|
259
|
+
break;
|
|
260
|
+
}
|
|
261
|
+
i++;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
if (i === 0) {
|
|
265
|
+
return false;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
if (i === data.length) {
|
|
269
|
+
return true;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
if (data.charCodeAt(i) === 35) {
|
|
273
|
+
return i + 1 === data.length;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
if (data.charCodeAt(i) !== 47) {
|
|
277
|
+
return false;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
for (i = i + 1; i < data.length; i++) {
|
|
281
|
+
if (data.charCodeAt(i) !== 126) {
|
|
282
|
+
continue;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
const next = data.charCodeAt(i + 1);
|
|
286
|
+
if (next !== 48 && next !== 49) {
|
|
287
|
+
return false;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
i++;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
return true;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
function isValidUriTemplate(data: string) {
|
|
297
|
+
for (let i = 0; i < data.length; i++) {
|
|
298
|
+
const code = data.charCodeAt(i);
|
|
299
|
+
|
|
300
|
+
if (code === 125) {
|
|
301
|
+
return false;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
if (code !== 123) {
|
|
305
|
+
continue;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
const closeIndex = data.indexOf("}", i + 1);
|
|
309
|
+
if (closeIndex === -1 || closeIndex === i + 1) {
|
|
310
|
+
return false;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
i = closeIndex;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
return true;
|
|
317
|
+
}
|
|
318
|
+
|
|
41
319
|
export const Formats: Record<string, FormatFunction | false> = {
|
|
42
320
|
["date-time"](data) {
|
|
43
|
-
const
|
|
44
|
-
if (
|
|
321
|
+
const length = data.length;
|
|
322
|
+
if (length < 19) {
|
|
45
323
|
return false;
|
|
46
324
|
}
|
|
47
325
|
|
|
48
|
-
|
|
326
|
+
if (
|
|
327
|
+
data.charCodeAt(4) !== 45 ||
|
|
328
|
+
data.charCodeAt(7) !== 45 ||
|
|
329
|
+
data.charCodeAt(13) !== 58 ||
|
|
330
|
+
data.charCodeAt(16) !== 58
|
|
331
|
+
) {
|
|
332
|
+
return false;
|
|
333
|
+
}
|
|
49
334
|
|
|
50
|
-
const
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
const
|
|
335
|
+
const tCode = data.charCodeAt(10);
|
|
336
|
+
if (tCode !== 84 && tCode !== 116) {
|
|
337
|
+
return false;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
const year = parseFourDigits(data, 0);
|
|
341
|
+
const month = parseTwoDigits(data, 5);
|
|
342
|
+
const day = parseTwoDigits(data, 8);
|
|
343
|
+
const hour = parseTwoDigits(data, 11);
|
|
344
|
+
const minute = parseTwoDigits(data, 14);
|
|
345
|
+
const second = parseTwoDigits(data, 17);
|
|
346
|
+
|
|
347
|
+
if (
|
|
348
|
+
year < 0 ||
|
|
349
|
+
month < 0 ||
|
|
350
|
+
day < 0 ||
|
|
351
|
+
hour < 0 ||
|
|
352
|
+
minute < 0 ||
|
|
353
|
+
second < 0
|
|
354
|
+
) {
|
|
355
|
+
return false;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
if (hour > 23 || minute > 59 || second > 60) {
|
|
359
|
+
return false;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
let cursor = 19;
|
|
363
|
+
let offsetSign: "+" | "-" | null = null;
|
|
364
|
+
let offsetHour = 0;
|
|
365
|
+
let offsetMinute = 0;
|
|
366
|
+
|
|
367
|
+
if (cursor < length && data.charCodeAt(cursor) === 46) {
|
|
368
|
+
cursor++;
|
|
369
|
+
const fracStart = cursor;
|
|
370
|
+
while (cursor < length && isDigitCharCode(data.charCodeAt(cursor))) {
|
|
371
|
+
cursor++;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
if (cursor === fracStart) {
|
|
375
|
+
return false;
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
if (cursor < length) {
|
|
380
|
+
const tzCode = data.charCodeAt(cursor);
|
|
381
|
+
|
|
382
|
+
if (tzCode === 90 || tzCode === 122) {
|
|
383
|
+
cursor++;
|
|
384
|
+
} else if (tzCode === 43 || tzCode === 45) {
|
|
385
|
+
offsetSign = tzCode === 43 ? "+" : "-";
|
|
386
|
+
|
|
387
|
+
if (cursor + 6 > length || data.charCodeAt(cursor + 3) !== 58) {
|
|
388
|
+
return false;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
offsetHour = parseTwoDigits(data, cursor + 1);
|
|
392
|
+
offsetMinute = parseTwoDigits(data, cursor + 4);
|
|
393
|
+
|
|
394
|
+
if (
|
|
395
|
+
offsetHour < 0 ||
|
|
396
|
+
offsetMinute < 0 ||
|
|
397
|
+
offsetHour > 23 ||
|
|
398
|
+
offsetMinute > 59
|
|
399
|
+
) {
|
|
400
|
+
return false;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
cursor += 6;
|
|
404
|
+
} else {
|
|
405
|
+
return false;
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
if (cursor !== length) {
|
|
410
|
+
return false;
|
|
411
|
+
}
|
|
56
412
|
|
|
57
413
|
// Mes 1–12
|
|
58
414
|
if (month < 1 || month > 12) {
|
|
@@ -74,9 +430,22 @@ export const Formats: Record<string, FormatFunction | false> = {
|
|
|
74
430
|
return false;
|
|
75
431
|
}
|
|
76
432
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
433
|
+
if (second === 60) {
|
|
434
|
+
let utcTotalMinutes = hour * 60 + minute;
|
|
435
|
+
|
|
436
|
+
if (offsetSign) {
|
|
437
|
+
const offsetTotalMinutes = offsetHour * 60 + offsetMinute;
|
|
438
|
+
utcTotalMinutes +=
|
|
439
|
+
offsetSign === "+" ? -offsetTotalMinutes : offsetTotalMinutes;
|
|
440
|
+
utcTotalMinutes %= 24 * 60;
|
|
441
|
+
if (utcTotalMinutes < 0) {
|
|
442
|
+
utcTotalMinutes += 24 * 60;
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
if (utcTotalMinutes !== 23 * 60 + 59) {
|
|
447
|
+
return false;
|
|
448
|
+
}
|
|
80
449
|
}
|
|
81
450
|
|
|
82
451
|
return true;
|
|
@@ -88,54 +457,11 @@ export const Formats: Record<string, FormatFunction | false> = {
|
|
|
88
457
|
return EMAIL_REGEX.test(data);
|
|
89
458
|
},
|
|
90
459
|
ipv4(data) {
|
|
91
|
-
|
|
92
|
-
return IPV4_REGEX.test(data);
|
|
460
|
+
return isValidIpv4(data);
|
|
93
461
|
},
|
|
94
462
|
|
|
95
|
-
// ipv6: isMyIpValid({ version: 6 }),
|
|
96
463
|
ipv6(data) {
|
|
97
|
-
|
|
98
|
-
return true;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
if (data.indexOf(":") === -1 || IPV6_REGEX.test(data)) {
|
|
102
|
-
return false;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
const hasIpv4 = data.indexOf(".") !== -1;
|
|
106
|
-
let addressParts = data;
|
|
107
|
-
|
|
108
|
-
if (hasIpv4) {
|
|
109
|
-
addressParts = data.split(":");
|
|
110
|
-
const ipv4Part = addressParts.pop();
|
|
111
|
-
if (!IPV4_REGEX.test(ipv4Part)) {
|
|
112
|
-
return false;
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
const isShortened = data.indexOf("::") !== -1;
|
|
117
|
-
const ipv6Part = hasIpv4 ? addressParts.join(":") : data;
|
|
118
|
-
|
|
119
|
-
if (isShortened) {
|
|
120
|
-
if (ipv6Part.split("::").length - 1 > 1) {
|
|
121
|
-
return false;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
if (!IPV6_SHORT_REGEX.test(ipv6Part)) {
|
|
125
|
-
return false;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
return IPV6_FAST_FAIL_REGEX.test(ipv6Part);
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
const isIpv6Valid = IPV6_FULL_REGEX.test(ipv6Part);
|
|
132
|
-
const hasInvalidChar = IPV6_INVALID_CHAR_REGEX.test(ipv6Part);
|
|
133
|
-
|
|
134
|
-
if (hasIpv4) {
|
|
135
|
-
return isIpv6Valid || !hasInvalidChar;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
return isIpv6Valid && !hasInvalidChar;
|
|
464
|
+
return isValidIpv6(data);
|
|
139
465
|
},
|
|
140
466
|
|
|
141
467
|
hostname(data) {
|
|
@@ -177,24 +503,16 @@ export const Formats: Record<string, FormatFunction | false> = {
|
|
|
177
503
|
}
|
|
178
504
|
},
|
|
179
505
|
"json-pointer"(data) {
|
|
180
|
-
|
|
181
|
-
return true;
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
return JSON_POINTER_REGEX.test(data);
|
|
506
|
+
return isValidJsonPointer(data);
|
|
185
507
|
},
|
|
186
508
|
"relative-json-pointer"(data) {
|
|
187
|
-
|
|
188
|
-
return true;
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
return RELATIVE_JSON_POINTER_REGEX.test(data);
|
|
509
|
+
return isValidRelativeJsonPointer(data);
|
|
192
510
|
},
|
|
193
511
|
time(data) {
|
|
194
512
|
return TIME_REGEX.test(data);
|
|
195
513
|
},
|
|
196
514
|
"uri-reference"(data) {
|
|
197
|
-
if (
|
|
515
|
+
if (data.includes("\\")) {
|
|
198
516
|
return false;
|
|
199
517
|
}
|
|
200
518
|
|
|
@@ -202,7 +520,7 @@ export const Formats: Record<string, FormatFunction | false> = {
|
|
|
202
520
|
},
|
|
203
521
|
|
|
204
522
|
"uri-template"(data) {
|
|
205
|
-
return
|
|
523
|
+
return isValidUriTemplate(data);
|
|
206
524
|
},
|
|
207
525
|
|
|
208
526
|
duration(data) {
|
|
@@ -219,7 +537,7 @@ export const Formats: Record<string, FormatFunction | false> = {
|
|
|
219
537
|
},
|
|
220
538
|
|
|
221
539
|
"iri-reference"(data) {
|
|
222
|
-
if (
|
|
540
|
+
if (data.includes("\\")) {
|
|
223
541
|
return false;
|
|
224
542
|
}
|
|
225
543
|
return IRI_REFERENCE_REGEX.test(data);
|