schema-shield 0.0.6 → 1.0.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/README.md +194 -66
- package/dist/formats.d.ts.map +1 -1
- package/dist/index.d.ts +11 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +702 -347
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/dist/index.mjs +702 -347
- 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.d.ts +6 -5
- package/dist/utils.d.ts.map +1 -1
- package/lib/formats.ts +125 -130
- package/lib/index.ts +244 -97
- package/lib/keywords/array-keywords.ts +60 -46
- package/lib/keywords/object-keywords.ts +155 -53
- package/lib/keywords/other-keywords.ts +68 -28
- package/lib/keywords/string-keywords.ts +32 -6
- package/lib/types.ts +1 -13
- package/lib/utils.ts +202 -44
- package/package.json +2 -2
- package/tsconfig.json +4 -4
|
@@ -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;AAE3C,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,
|
|
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;AAE3C,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CA6MzD,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;AAE3C,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,GAAG,KAAK,
|
|
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;AAE3C,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,GAAG,KAAK,CA8XlE,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;AAE3C,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,
|
|
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;AAE3C,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAiOzD,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"string-keywords.d.ts","sourceRoot":"","sources":["../../lib/keywords/string-keywords.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
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;AAE3D,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CA2E1D,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;AAGvC,eAAO,MAAM,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,GAAG,KAAK,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../lib/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAGvC,eAAO,MAAM,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,GAAG,KAAK,CAiCtD,CAAC"}
|
package/dist/utils.d.ts
CHANGED
|
@@ -28,19 +28,20 @@ export declare class ValidationError extends Error {
|
|
|
28
28
|
}
|
|
29
29
|
export interface DefineErrorOptions {
|
|
30
30
|
item?: any;
|
|
31
|
-
cause?: ValidationError;
|
|
31
|
+
cause?: ValidationError | true;
|
|
32
32
|
data?: any;
|
|
33
33
|
}
|
|
34
34
|
export interface DefineErrorFunction {
|
|
35
|
-
(message: string, options?: DefineErrorOptions): ValidationError;
|
|
35
|
+
(message: string, options?: DefineErrorOptions): ValidationError | void | true;
|
|
36
36
|
}
|
|
37
|
-
export declare function getDefinedErrorFunctionForKey(key: string, schema: CompiledSchema): DefineErrorFunction;
|
|
38
|
-
export declare function
|
|
37
|
+
export declare function getDefinedErrorFunctionForKey(key: string, schema: CompiledSchema, failFast: boolean): DefineErrorFunction;
|
|
38
|
+
export declare function hasChanged(prev: any, current: any): boolean;
|
|
39
39
|
export declare function isObject(data: any): boolean;
|
|
40
40
|
export declare function areCloseEnough(a: any, b: any, epsilon?: number): boolean;
|
|
41
41
|
export declare function getUTF16Length(str: any): number;
|
|
42
|
-
export declare function deepClone(obj: any):
|
|
42
|
+
export declare function deepClone<T>(obj: T, cloneClassInstances?: boolean, seen?: WeakMap<object, any>): T;
|
|
43
43
|
export declare function isCompiledSchema(subSchema: any): subSchema is CompiledSchema;
|
|
44
44
|
export declare function getNamedFunction<T>(name: string, fn: T): T;
|
|
45
|
+
export declare function resolvePath(root: any, path: string): any;
|
|
45
46
|
export {};
|
|
46
47
|
//# sourceMappingURL=utils.d.ts.map
|
package/dist/utils.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../lib/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAEzC,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,CAAC;
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../lib/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAEzC,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,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,kBAAkB,GAC1C,eAAe,GACf,IAAI,GACJ,IAAI,CAAC;CACV;AAGD,wBAAgB,6BAA6B,CAC3C,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,cAAc,EACtB,QAAQ,EAAE,OAAO,uBAuBlB;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,WAwCjD;AAED,wBAAgB,QAAQ,CAAC,IAAI,KAAA,WAE5B;AAED,wBAAgB,cAAc,CAAC,CAAC,KAAA,EAAE,CAAC,KAAA,EAAE,OAAO,SAAQ,WAEnD;AAED,wBAAgB,cAAc,CAAC,GAAG,KAAA,UAUjC;AAED,wBAAgB,SAAS,CAAC,CAAC,EACzB,GAAG,EAAE,CAAC,EACN,mBAAmB,UAAQ,EAC3B,IAAI,uBAAgB,GACnB,CAAC,CA6HH;AAED,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,GAAG,GAAG,SAAS,IAAI,cAAc,CAE5E;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"}
|
package/lib/formats.ts
CHANGED
|
@@ -1,102 +1,80 @@
|
|
|
1
1
|
import { FormatFunction } from "./index";
|
|
2
2
|
|
|
3
|
+
// Regex helpers
|
|
4
|
+
const UUID_REGEX =
|
|
5
|
+
/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
6
|
+
// ISO 8601 Duration (P3Y6M4DT12H30M5S)
|
|
7
|
+
const DURATION_REGEX =
|
|
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
|
+
const URI_REGEX = /^[a-zA-Z][a-zA-Z0-9+\-.]*:[^\s]*$/;
|
|
12
|
+
const EMAIL_REGEX =
|
|
13
|
+
/^(?!\.)(?!.*\.$)[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
|
+
const HOSTNAME_REGEX =
|
|
23
|
+
/^[a-z0-9][a-z0-9-]{0,62}(?:\.[a-z0-9][a-z0-9-]{0,62})*[a-z0-9]$/i;
|
|
24
|
+
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
|
+
const TIME_REGEX =
|
|
28
|
+
/^([01]\d|2[0-3]):([0-5]\d):([0-5]\d)(\.\d+)?(Z|([+-])([01]\d|2[0-3]):([0-5]\d))$/;
|
|
29
|
+
const URI_REFERENCE_REGEX =
|
|
30
|
+
/^(([^:/?#]+):)?(\/\/([^/?#]*))?([^?#]*)(\?([^#]*))?(#((?![^#]*\\)[^#]*))?/i;
|
|
31
|
+
const URI_TEMPLATE_REGEX = /^(?:[^{}]|\{[^}]+\})*$/;
|
|
32
|
+
const IRI_REGEX = /^[a-zA-Z][a-zA-Z0-9+\-.]*:[^\s]*$/;
|
|
33
|
+
const IRI_REFERENCE_REGEX =
|
|
34
|
+
/^(([^:/?#]+):)?(\/\/([^/?#]*))?([^?#]*)(\?([^#]*))?(#((?![^#]*\\)[^#]*))?/i;
|
|
35
|
+
const IDN_EMAIL_REGEX = /^[^@\s]+@[^@\s]+\.[^@\s]+$/;
|
|
36
|
+
const IDN_HOSTNAME_REGEX = /^[^\s!@#$%^&*()_+\=\[\]{};':"\\|,<>\/?]+$/;
|
|
37
|
+
const BACK_SLASH_REGEX = /\\/;
|
|
38
|
+
|
|
39
|
+
const DAYS_IN_MONTH = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
|
|
40
|
+
|
|
3
41
|
export const Formats: Record<string, FormatFunction | false> = {
|
|
4
42
|
["date-time"](data) {
|
|
5
|
-
const match = data.match(
|
|
6
|
-
/^(\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
|
|
7
|
-
);
|
|
8
|
-
|
|
43
|
+
const match = data.match(DATE_TIME_REGEX);
|
|
9
44
|
if (!match) {
|
|
10
45
|
return false;
|
|
11
46
|
}
|
|
12
47
|
|
|
13
|
-
|
|
48
|
+
const [, yearStr, monthStr, dayStr, hourStr, minuteStr, secondStr] = match;
|
|
49
|
+
|
|
50
|
+
const year = Number(yearStr);
|
|
51
|
+
const month = Number(monthStr);
|
|
52
|
+
const day = Number(dayStr);
|
|
53
|
+
const hour = Number(hourStr);
|
|
54
|
+
const minute = Number(minuteStr);
|
|
55
|
+
const second = Number(secondStr);
|
|
14
56
|
|
|
15
|
-
|
|
57
|
+
// Mes 1–12
|
|
58
|
+
if (month < 1 || month > 12) {
|
|
16
59
|
return false;
|
|
17
60
|
}
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
yearStr,
|
|
22
|
-
monthStr,
|
|
23
|
-
,
|
|
24
|
-
hourStr,
|
|
25
|
-
minuteStr,
|
|
26
|
-
secondStr,
|
|
27
|
-
timezoneSign,
|
|
28
|
-
timezoneHourStr,
|
|
29
|
-
timezoneMinuteStr
|
|
30
|
-
] = match;
|
|
31
|
-
|
|
32
|
-
let year = Number(yearStr);
|
|
33
|
-
let month = Number(monthStr);
|
|
34
|
-
let hour = Number(hourStr);
|
|
35
|
-
let minute = Number(minuteStr);
|
|
36
|
-
let second = Number(secondStr);
|
|
37
|
-
|
|
38
|
-
if (timezoneSign === "-" || timezoneSign === "+") {
|
|
39
|
-
const timezoneHour = Number(timezoneHourStr);
|
|
40
|
-
const timezoneMinute = Number(timezoneMinuteStr);
|
|
41
|
-
|
|
42
|
-
if (timezoneSign === "-") {
|
|
43
|
-
hour += timezoneHour;
|
|
44
|
-
minute += timezoneMinute;
|
|
45
|
-
} else if (timezoneSign === "+") {
|
|
46
|
-
hour -= timezoneHour;
|
|
47
|
-
minute -= timezoneMinute;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
if (minute > 59) {
|
|
51
|
-
hour += 1;
|
|
52
|
-
minute -= 60;
|
|
53
|
-
} else if (minute < 0) {
|
|
54
|
-
hour -= 1;
|
|
55
|
-
minute += 60;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
if (hour > 23) {
|
|
59
|
-
day += 1;
|
|
60
|
-
hour -= 24;
|
|
61
|
-
} else if (hour < 0) {
|
|
62
|
-
day -= 1;
|
|
63
|
-
hour += 24;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
if (day > 31) {
|
|
67
|
-
month += 1;
|
|
68
|
-
day -= 31;
|
|
69
|
-
} else if (day < 1) {
|
|
70
|
-
month -= 1;
|
|
71
|
-
day += 31;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
if (month > 12) {
|
|
75
|
-
year += 1;
|
|
76
|
-
month -= 12;
|
|
77
|
-
} else if (month < 1) {
|
|
78
|
-
year -= 1;
|
|
79
|
-
month += 12;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
if (year < 0) {
|
|
83
|
-
return false;
|
|
84
|
-
}
|
|
61
|
+
// Día >= 1
|
|
62
|
+
if (day < 1) {
|
|
63
|
+
return false;
|
|
85
64
|
}
|
|
86
65
|
|
|
87
|
-
const daysInMonth = [31, , 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
|
|
88
66
|
const maxDays =
|
|
89
67
|
month === 2
|
|
90
68
|
? year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0)
|
|
91
69
|
? 29
|
|
92
70
|
: 28
|
|
93
|
-
:
|
|
71
|
+
: DAYS_IN_MONTH[month - 1];
|
|
94
72
|
|
|
95
|
-
if (day > maxDays) {
|
|
73
|
+
if (!maxDays || day > maxDays) {
|
|
96
74
|
return false;
|
|
97
75
|
}
|
|
98
76
|
|
|
99
|
-
// Leap seconds
|
|
77
|
+
// Leap seconds (si quieres seguir permitiendo 60)
|
|
100
78
|
if (second === 60 && (minute !== 59 || hour !== 23)) {
|
|
101
79
|
return false;
|
|
102
80
|
}
|
|
@@ -104,19 +82,14 @@ export const Formats: Record<string, FormatFunction | false> = {
|
|
|
104
82
|
return true;
|
|
105
83
|
},
|
|
106
84
|
uri(data) {
|
|
107
|
-
return
|
|
85
|
+
return URI_REGEX.test(data);
|
|
108
86
|
},
|
|
109
87
|
email(data) {
|
|
110
|
-
return
|
|
111
|
-
data
|
|
112
|
-
);
|
|
88
|
+
return EMAIL_REGEX.test(data);
|
|
113
89
|
},
|
|
114
90
|
ipv4(data) {
|
|
115
91
|
// Matches a string formed by 4 numbers between 0 and 255 separated by dots without leading zeros
|
|
116
|
-
|
|
117
|
-
return /^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])$/.test(
|
|
118
|
-
data
|
|
119
|
-
);
|
|
92
|
+
return IPV4_REGEX.test(data);
|
|
120
93
|
},
|
|
121
94
|
|
|
122
95
|
// ipv6: isMyIpValid({ version: 6 }),
|
|
@@ -125,10 +98,7 @@ export const Formats: Record<string, FormatFunction | false> = {
|
|
|
125
98
|
return true;
|
|
126
99
|
}
|
|
127
100
|
|
|
128
|
-
if (
|
|
129
|
-
data.indexOf(":") === -1 ||
|
|
130
|
-
/(?:\s+|:::+|^\w{5,}|\w{5}$|^:{1}\w|\w:{1}$)/.test(data)
|
|
131
|
-
) {
|
|
101
|
+
if (data.indexOf(":") === -1 || IPV6_REGEX.test(data)) {
|
|
132
102
|
return false;
|
|
133
103
|
}
|
|
134
104
|
|
|
@@ -138,11 +108,7 @@ export const Formats: Record<string, FormatFunction | false> = {
|
|
|
138
108
|
if (hasIpv4) {
|
|
139
109
|
addressParts = data.split(":");
|
|
140
110
|
const ipv4Part = addressParts.pop();
|
|
141
|
-
if (
|
|
142
|
-
!/^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])$/.test(
|
|
143
|
-
ipv4Part
|
|
144
|
-
)
|
|
145
|
-
) {
|
|
111
|
+
if (!IPV4_REGEX.test(ipv4Part)) {
|
|
146
112
|
return false;
|
|
147
113
|
}
|
|
148
114
|
}
|
|
@@ -155,21 +121,15 @@ export const Formats: Record<string, FormatFunction | false> = {
|
|
|
155
121
|
return false;
|
|
156
122
|
}
|
|
157
123
|
|
|
158
|
-
if (
|
|
124
|
+
if (!IPV6_SHORT_REGEX.test(ipv6Part)) {
|
|
159
125
|
return false;
|
|
160
126
|
}
|
|
161
127
|
|
|
162
|
-
return
|
|
163
|
-
ipv6Part
|
|
164
|
-
);
|
|
128
|
+
return IPV6_FAST_FAIL_REGEX.test(ipv6Part);
|
|
165
129
|
}
|
|
166
130
|
|
|
167
|
-
const isIpv6Valid =
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
const hasInvalidChar = /(?:[0-9a-fA-F]{5,}|\D[0-9a-fA-F]{3}:)/.test(
|
|
171
|
-
ipv6Part
|
|
172
|
-
);
|
|
131
|
+
const isIpv6Valid = IPV6_FULL_REGEX.test(ipv6Part);
|
|
132
|
+
const hasInvalidChar = IPV6_INVALID_CHAR_REGEX.test(ipv6Part);
|
|
173
133
|
|
|
174
134
|
if (hasIpv4) {
|
|
175
135
|
return isIpv6Valid || !hasInvalidChar;
|
|
@@ -179,16 +139,34 @@ export const Formats: Record<string, FormatFunction | false> = {
|
|
|
179
139
|
},
|
|
180
140
|
|
|
181
141
|
hostname(data) {
|
|
182
|
-
return
|
|
183
|
-
data
|
|
184
|
-
);
|
|
142
|
+
return HOSTNAME_REGEX.test(data);
|
|
185
143
|
},
|
|
186
144
|
date(data) {
|
|
187
|
-
|
|
145
|
+
const match = DATE_REGEX.exec(data);
|
|
146
|
+
if (!match) {
|
|
147
|
+
return false;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
const [, yearStr, monthStr, dayStr] = match;
|
|
151
|
+
const year = Number(yearStr);
|
|
152
|
+
const month = Number(monthStr);
|
|
153
|
+
const day = Number(dayStr);
|
|
154
|
+
|
|
155
|
+
if (month < 1 || month > 12) {
|
|
188
156
|
return false;
|
|
189
157
|
}
|
|
158
|
+
if (day < 1) {
|
|
159
|
+
return false;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const maxDays =
|
|
163
|
+
month === 2
|
|
164
|
+
? year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0)
|
|
165
|
+
? 29
|
|
166
|
+
: 28
|
|
167
|
+
: DAYS_IN_MONTH[month - 1];
|
|
190
168
|
|
|
191
|
-
return
|
|
169
|
+
return !!maxDays && day <= maxDays;
|
|
192
170
|
},
|
|
193
171
|
regex(data) {
|
|
194
172
|
try {
|
|
@@ -203,40 +181,57 @@ export const Formats: Record<string, FormatFunction | false> = {
|
|
|
203
181
|
return true;
|
|
204
182
|
}
|
|
205
183
|
|
|
206
|
-
return
|
|
184
|
+
return JSON_POINTER_REGEX.test(data);
|
|
207
185
|
},
|
|
208
186
|
"relative-json-pointer"(data) {
|
|
209
187
|
if (data === "") {
|
|
210
188
|
return true;
|
|
211
189
|
}
|
|
212
190
|
|
|
213
|
-
return
|
|
191
|
+
return RELATIVE_JSON_POINTER_REGEX.test(data);
|
|
214
192
|
},
|
|
215
193
|
time(data) {
|
|
216
|
-
return
|
|
217
|
-
data
|
|
218
|
-
);
|
|
194
|
+
return TIME_REGEX.test(data);
|
|
219
195
|
},
|
|
220
196
|
"uri-reference"(data) {
|
|
221
|
-
if (
|
|
197
|
+
if (BACK_SLASH_REGEX.test(data)) {
|
|
222
198
|
return false;
|
|
223
199
|
}
|
|
224
200
|
|
|
225
|
-
return
|
|
226
|
-
data
|
|
227
|
-
);
|
|
201
|
+
return URI_REFERENCE_REGEX.test(data);
|
|
228
202
|
},
|
|
203
|
+
|
|
229
204
|
"uri-template"(data) {
|
|
230
|
-
return
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
uuid
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
205
|
+
return URI_TEMPLATE_REGEX.test(data);
|
|
206
|
+
},
|
|
207
|
+
|
|
208
|
+
duration(data) {
|
|
209
|
+
return DURATION_REGEX.test(data);
|
|
210
|
+
},
|
|
211
|
+
|
|
212
|
+
uuid(data) {
|
|
213
|
+
return UUID_REGEX.test(data);
|
|
214
|
+
},
|
|
215
|
+
|
|
216
|
+
// IRI is like URI but allows Unicode. We reuse a permissive logic.
|
|
217
|
+
iri(data) {
|
|
218
|
+
return IRI_REGEX.test(data);
|
|
219
|
+
},
|
|
220
|
+
|
|
221
|
+
"iri-reference"(data) {
|
|
222
|
+
if (BACK_SLASH_REGEX.test(data)) {
|
|
223
|
+
return false;
|
|
224
|
+
}
|
|
225
|
+
return IRI_REFERENCE_REGEX.test(data);
|
|
226
|
+
},
|
|
227
|
+
|
|
228
|
+
// Best-effort structural validation for IDN (no punycode/tables)
|
|
229
|
+
"idn-email"(data) {
|
|
230
|
+
return IDN_EMAIL_REGEX.test(data);
|
|
231
|
+
},
|
|
232
|
+
|
|
233
|
+
"idn-hostname"(data) {
|
|
234
|
+
// Allows unicode, forbids spaces and typical invalid URL chars
|
|
235
|
+
return IDN_HOSTNAME_REGEX.test(data);
|
|
236
|
+
}
|
|
242
237
|
};
|