zod 3.22.4 → 3.23.8
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 +279 -237
- package/lib/ZodError.d.ts +2 -1
- package/lib/ZodError.js +5 -0
- package/lib/benchmarks/datetime.d.ts +5 -0
- package/lib/benchmarks/datetime.js +54 -0
- package/lib/benchmarks/index.js +15 -2
- package/lib/benchmarks/ipv4.d.ts +5 -0
- package/lib/benchmarks/ipv4.js +54 -0
- package/lib/benchmarks/primitives.js +34 -0
- package/lib/helpers/parseUtil.d.ts +1 -1
- package/lib/helpers/parseUtil.js +15 -5
- package/lib/helpers/util.d.ts +16 -2
- package/lib/index.mjs +289 -70
- package/lib/index.umd.js +289 -69
- package/lib/types.d.ts +113 -43
- package/lib/types.js +249 -67
- package/package.json +6 -6
package/lib/ZodError.d.ts
CHANGED
|
@@ -70,7 +70,7 @@ export interface ZodInvalidReturnTypeIssue extends ZodIssueBase {
|
|
|
70
70
|
export interface ZodInvalidDateIssue extends ZodIssueBase {
|
|
71
71
|
code: typeof ZodIssueCode.invalid_date;
|
|
72
72
|
}
|
|
73
|
-
export declare type StringValidation = "email" | "url" | "emoji" | "uuid" | "regex" | "cuid" | "cuid2" | "ulid" | "datetime" | "ip" | {
|
|
73
|
+
export declare type StringValidation = "email" | "url" | "emoji" | "uuid" | "nanoid" | "regex" | "cuid" | "cuid2" | "ulid" | "datetime" | "date" | "time" | "duration" | "ip" | "base64" | {
|
|
74
74
|
includes: string;
|
|
75
75
|
position?: number;
|
|
76
76
|
} | {
|
|
@@ -139,6 +139,7 @@ export declare class ZodError<T = any> extends Error {
|
|
|
139
139
|
format(): ZodFormattedError<T>;
|
|
140
140
|
format<U>(mapper: (issue: ZodIssue) => U): ZodFormattedError<T, U>;
|
|
141
141
|
static create: (issues: ZodIssue[]) => ZodError<any>;
|
|
142
|
+
static assert(value: unknown): asserts value is ZodError;
|
|
142
143
|
toString(): string;
|
|
143
144
|
get message(): string;
|
|
144
145
|
get isEmpty(): boolean;
|
package/lib/ZodError.js
CHANGED
|
@@ -98,6 +98,11 @@ class ZodError extends Error {
|
|
|
98
98
|
processError(this);
|
|
99
99
|
return fieldErrors;
|
|
100
100
|
}
|
|
101
|
+
static assert(value) {
|
|
102
|
+
if (!(value instanceof ZodError)) {
|
|
103
|
+
throw new Error(`Not a ZodError: ${value}`);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
101
106
|
toString() {
|
|
102
107
|
return this.message;
|
|
103
108
|
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const benchmark_1 = __importDefault(require("benchmark"));
|
|
7
|
+
const datetimeValidationSuite = new benchmark_1.default.Suite("datetime");
|
|
8
|
+
const DATA = "2021-01-01";
|
|
9
|
+
const MONTHS_31 = new Set([1, 3, 5, 7, 8, 10, 12]);
|
|
10
|
+
const MONTHS_30 = new Set([4, 6, 9, 11]);
|
|
11
|
+
const simpleDatetimeRegex = /^(\d{4})-(\d{2})-(\d{2})$/;
|
|
12
|
+
const datetimeRegexNoLeapYearValidation = /^\d{4}-((0[13578]|10|12)-31|(0[13-9]|1[0-2])-30|(0[1-9]|1[0-2])-(0[1-9]|1\d|2\d))$/;
|
|
13
|
+
const datetimeRegexWithLeapYearValidation = /^((\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-((0[13578]|1[02])-(0[1-9]|[12]\d|3[01])|(0[469]|11)-(0[1-9]|[12]\d|30)|(02)-(0[1-9]|1\d|2[0-8])))$/;
|
|
14
|
+
datetimeValidationSuite
|
|
15
|
+
.add("new Date()", () => {
|
|
16
|
+
return !isNaN(new Date(DATA).getTime());
|
|
17
|
+
})
|
|
18
|
+
.add("regex (no validation)", () => {
|
|
19
|
+
return simpleDatetimeRegex.test(DATA);
|
|
20
|
+
})
|
|
21
|
+
.add("regex (no leap year)", () => {
|
|
22
|
+
return datetimeRegexNoLeapYearValidation.test(DATA);
|
|
23
|
+
})
|
|
24
|
+
.add("regex (w/ leap year)", () => {
|
|
25
|
+
return datetimeRegexWithLeapYearValidation.test(DATA);
|
|
26
|
+
})
|
|
27
|
+
.add("capture groups + code", () => {
|
|
28
|
+
const match = DATA.match(simpleDatetimeRegex);
|
|
29
|
+
if (!match)
|
|
30
|
+
return false;
|
|
31
|
+
// Extract year, month, and day from the capture groups
|
|
32
|
+
const year = Number.parseInt(match[1], 10);
|
|
33
|
+
const month = Number.parseInt(match[2], 10); // month is 0-indexed in JavaScript Date, so subtract 1
|
|
34
|
+
const day = Number.parseInt(match[3], 10);
|
|
35
|
+
if (month === 2) {
|
|
36
|
+
if ((year % 4 === 0 && year % 100 !== 0) || year % 400 === 0) {
|
|
37
|
+
return day <= 29;
|
|
38
|
+
}
|
|
39
|
+
return day <= 28;
|
|
40
|
+
}
|
|
41
|
+
if (MONTHS_30.has(month)) {
|
|
42
|
+
return day <= 30;
|
|
43
|
+
}
|
|
44
|
+
if (MONTHS_31.has(month)) {
|
|
45
|
+
return day <= 31;
|
|
46
|
+
}
|
|
47
|
+
return false;
|
|
48
|
+
})
|
|
49
|
+
.on("cycle", (e) => {
|
|
50
|
+
console.log(`${datetimeValidationSuite.name}: ${e.target}`);
|
|
51
|
+
});
|
|
52
|
+
exports.default = {
|
|
53
|
+
suites: [datetimeValidationSuite],
|
|
54
|
+
};
|
package/lib/benchmarks/index.js
CHANGED
|
@@ -3,7 +3,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const datetime_1 = __importDefault(require("./datetime"));
|
|
6
7
|
const discriminatedUnion_1 = __importDefault(require("./discriminatedUnion"));
|
|
8
|
+
const ipv4_1 = __importDefault(require("./ipv4"));
|
|
7
9
|
const object_1 = __importDefault(require("./object"));
|
|
8
10
|
const primitives_1 = __importDefault(require("./primitives"));
|
|
9
11
|
const realworld_1 = __importDefault(require("./realworld"));
|
|
@@ -38,9 +40,20 @@ else {
|
|
|
38
40
|
suites.push(...union_1.default.suites);
|
|
39
41
|
}
|
|
40
42
|
if (argv.includes("--discriminatedUnion")) {
|
|
41
|
-
suites.push(...
|
|
43
|
+
suites.push(...datetime_1.default.suites);
|
|
44
|
+
}
|
|
45
|
+
if (argv.includes("--datetime")) {
|
|
46
|
+
suites.push(...datetime_1.default.suites);
|
|
47
|
+
}
|
|
48
|
+
if (argv.includes("--ipv4")) {
|
|
49
|
+
suites.push(...ipv4_1.default.suites);
|
|
42
50
|
}
|
|
43
51
|
}
|
|
44
52
|
for (const suite of suites) {
|
|
45
|
-
suite.run();
|
|
53
|
+
suite.run({});
|
|
46
54
|
}
|
|
55
|
+
// exit on Ctrl-C
|
|
56
|
+
process.on("SIGINT", function () {
|
|
57
|
+
console.log("Exiting...");
|
|
58
|
+
process.exit();
|
|
59
|
+
});
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const benchmark_1 = __importDefault(require("benchmark"));
|
|
7
|
+
const suite = new benchmark_1.default.Suite("ipv4");
|
|
8
|
+
const DATA = "127.0.0.1";
|
|
9
|
+
const ipv4RegexA = /^(((25[0-5])|(2[0-4][0-9])|(1[0-9]{2})|([0-9]{1,2}))\.){3}((25[0-5])|(2[0-4][0-9])|(1[0-9]{2})|([0-9]{1,2}))$/;
|
|
10
|
+
const ipv4RegexB = /^(?:(?:(?=(25[0-5]))\1|(?=(2[0-4][0-9]))\2|(?=(1[0-9]{2}))\3|(?=([0-9]{1,2}))\4)\.){3}(?:(?=(25[0-5]))\5|(?=(2[0-4][0-9]))\6|(?=(1[0-9]{2}))\7|(?=([0-9]{1,2}))\8)$/;
|
|
11
|
+
const ipv4RegexC = /^(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)$/;
|
|
12
|
+
const ipv4RegexD = /^(\b25[0-5]|\b2[0-4][0-9]|\b[01]?[0-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/;
|
|
13
|
+
const ipv4RegexE = /^((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)\.){3}(25[0-5]|(2[0-4]|1\d|[1-9]|)\d)$/;
|
|
14
|
+
const ipv4RegexF = /^((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)\.?\b){4}$/;
|
|
15
|
+
const ipv4RegexG = /^((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)(\.(?!$)|$)){4}$/;
|
|
16
|
+
const ipv4RegexH = /^((25[0-5]|(2[0-4]|1[0-9]|[1-9]|)[0-9])(\.(?!$)|$)){4}$/;
|
|
17
|
+
const ipv4RegexI = /^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])$/;
|
|
18
|
+
suite
|
|
19
|
+
.add("A", () => {
|
|
20
|
+
return ipv4RegexA.test(DATA);
|
|
21
|
+
})
|
|
22
|
+
.add("B", () => {
|
|
23
|
+
return ipv4RegexB.test(DATA);
|
|
24
|
+
})
|
|
25
|
+
.add("C", () => {
|
|
26
|
+
return ipv4RegexC.test(DATA);
|
|
27
|
+
})
|
|
28
|
+
.add("D", () => {
|
|
29
|
+
return ipv4RegexD.test(DATA);
|
|
30
|
+
})
|
|
31
|
+
.add("E", () => {
|
|
32
|
+
return ipv4RegexE.test(DATA);
|
|
33
|
+
})
|
|
34
|
+
.add("F", () => {
|
|
35
|
+
return ipv4RegexF.test(DATA);
|
|
36
|
+
})
|
|
37
|
+
.add("G", () => {
|
|
38
|
+
return ipv4RegexG.test(DATA);
|
|
39
|
+
})
|
|
40
|
+
.add("H", () => {
|
|
41
|
+
return ipv4RegexH.test(DATA);
|
|
42
|
+
})
|
|
43
|
+
.add("I", () => {
|
|
44
|
+
return ipv4RegexI.test(DATA);
|
|
45
|
+
})
|
|
46
|
+
.on("cycle", (e) => {
|
|
47
|
+
console.log(`${suite.name}: ${e.target}`);
|
|
48
|
+
});
|
|
49
|
+
exports.default = {
|
|
50
|
+
suites: [suite],
|
|
51
|
+
};
|
|
52
|
+
if (require.main === module) {
|
|
53
|
+
suite.run();
|
|
54
|
+
}
|
|
@@ -22,6 +22,39 @@ enumSuite
|
|
|
22
22
|
.on("cycle", (e) => {
|
|
23
23
|
console.log(`z.enum: ${e.target}`);
|
|
24
24
|
});
|
|
25
|
+
const longEnumSuite = new benchmark_1.default.Suite("long z.enum");
|
|
26
|
+
const longEnumSchema = index_1.z.enum([
|
|
27
|
+
"one",
|
|
28
|
+
"two",
|
|
29
|
+
"three",
|
|
30
|
+
"four",
|
|
31
|
+
"five",
|
|
32
|
+
"six",
|
|
33
|
+
"seven",
|
|
34
|
+
"eight",
|
|
35
|
+
"nine",
|
|
36
|
+
"ten",
|
|
37
|
+
"eleven",
|
|
38
|
+
"twelve",
|
|
39
|
+
"thirteen",
|
|
40
|
+
"fourteen",
|
|
41
|
+
"fifteen",
|
|
42
|
+
"sixteen",
|
|
43
|
+
"seventeen",
|
|
44
|
+
]);
|
|
45
|
+
longEnumSuite
|
|
46
|
+
.add("valid", () => {
|
|
47
|
+
longEnumSchema.parse("five");
|
|
48
|
+
})
|
|
49
|
+
.add("invalid", () => {
|
|
50
|
+
try {
|
|
51
|
+
longEnumSchema.parse("invalid");
|
|
52
|
+
}
|
|
53
|
+
catch (e) { }
|
|
54
|
+
})
|
|
55
|
+
.on("cycle", (e) => {
|
|
56
|
+
console.log(`long z.enum: ${e.target}`);
|
|
57
|
+
});
|
|
25
58
|
const undefinedSuite = new benchmark_1.default.Suite("z.undefined");
|
|
26
59
|
const undefinedSchema = index_1.z.undefined();
|
|
27
60
|
undefinedSuite
|
|
@@ -127,6 +160,7 @@ symbolSuite
|
|
|
127
160
|
exports.default = {
|
|
128
161
|
suites: [
|
|
129
162
|
enumSuite,
|
|
163
|
+
longEnumSuite,
|
|
130
164
|
undefinedSuite,
|
|
131
165
|
literalSuite,
|
|
132
166
|
numberSuite,
|
|
@@ -74,5 +74,5 @@ export declare type AsyncParseReturnType<T> = Promise<SyncParseReturnType<T>>;
|
|
|
74
74
|
export declare type ParseReturnType<T> = SyncParseReturnType<T> | AsyncParseReturnType<T>;
|
|
75
75
|
export declare const isAborted: (x: ParseReturnType<any>) => x is INVALID;
|
|
76
76
|
export declare const isDirty: <T>(x: ParseReturnType<T>) => x is OK<T> | DIRTY<T>;
|
|
77
|
-
export declare const isValid: <T>(x: ParseReturnType<T>) => x is OK<T
|
|
77
|
+
export declare const isValid: <T>(x: ParseReturnType<T>) => x is OK<T>;
|
|
78
78
|
export declare const isAsync: <T>(x: ParseReturnType<T>) => x is AsyncParseReturnType<T>;
|
package/lib/helpers/parseUtil.js
CHANGED
|
@@ -13,6 +13,13 @@ const makeIssue = (params) => {
|
|
|
13
13
|
...issueData,
|
|
14
14
|
path: fullPath,
|
|
15
15
|
};
|
|
16
|
+
if (issueData.message !== undefined) {
|
|
17
|
+
return {
|
|
18
|
+
...issueData,
|
|
19
|
+
path: fullPath,
|
|
20
|
+
message: issueData.message,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
16
23
|
let errorMessage = "";
|
|
17
24
|
const maps = errorMaps
|
|
18
25
|
.filter((m) => !!m)
|
|
@@ -24,12 +31,13 @@ const makeIssue = (params) => {
|
|
|
24
31
|
return {
|
|
25
32
|
...issueData,
|
|
26
33
|
path: fullPath,
|
|
27
|
-
message:
|
|
34
|
+
message: errorMessage,
|
|
28
35
|
};
|
|
29
36
|
};
|
|
30
37
|
exports.makeIssue = makeIssue;
|
|
31
38
|
exports.EMPTY_PATH = [];
|
|
32
39
|
function addIssueToContext(ctx, issueData) {
|
|
40
|
+
const overrideMap = (0, errors_1.getErrorMap)();
|
|
33
41
|
const issue = (0, exports.makeIssue)({
|
|
34
42
|
issueData: issueData,
|
|
35
43
|
data: ctx.data,
|
|
@@ -37,8 +45,8 @@ function addIssueToContext(ctx, issueData) {
|
|
|
37
45
|
errorMaps: [
|
|
38
46
|
ctx.common.contextualErrorMap,
|
|
39
47
|
ctx.schemaErrorMap,
|
|
40
|
-
|
|
41
|
-
en_1.default, // then global default map
|
|
48
|
+
overrideMap,
|
|
49
|
+
overrideMap === en_1.default ? undefined : en_1.default, // then global default map
|
|
42
50
|
].filter((x) => !!x),
|
|
43
51
|
});
|
|
44
52
|
ctx.common.issues.push(issue);
|
|
@@ -70,9 +78,11 @@ class ParseStatus {
|
|
|
70
78
|
static async mergeObjectAsync(status, pairs) {
|
|
71
79
|
const syncPairs = [];
|
|
72
80
|
for (const pair of pairs) {
|
|
81
|
+
const key = await pair.key;
|
|
82
|
+
const value = await pair.value;
|
|
73
83
|
syncPairs.push({
|
|
74
|
-
key
|
|
75
|
-
value
|
|
84
|
+
key,
|
|
85
|
+
value,
|
|
76
86
|
});
|
|
77
87
|
}
|
|
78
88
|
return ParseStatus.mergeObjectSync(status, syncPairs);
|
package/lib/helpers/util.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ export declare namespace util {
|
|
|
7
7
|
export type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;
|
|
8
8
|
export type OmitKeys<T, K extends string> = Pick<T, Exclude<keyof T, K>>;
|
|
9
9
|
export type MakePartial<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
|
|
10
|
+
export type Exactly<T, X> = T & Record<Exclude<keyof X, keyof T>, never>;
|
|
10
11
|
export const arrayToEnum: <T extends string, U extends [T, ...T[]]>(items: U) => { [k in U[number]]: k; };
|
|
11
12
|
export const getValidEnumValues: (obj: any) => any[];
|
|
12
13
|
export const objectValues: (obj: any) => any[];
|
|
@@ -24,10 +25,19 @@ export declare namespace objectUtil {
|
|
|
24
25
|
export type MergeShapes<U, V> = {
|
|
25
26
|
[k in Exclude<keyof U, keyof V>]: U[k];
|
|
26
27
|
} & V;
|
|
28
|
+
type optionalKeys<T extends object> = {
|
|
29
|
+
[k in keyof T]: undefined extends T[k] ? k : never;
|
|
30
|
+
}[keyof T];
|
|
27
31
|
type requiredKeys<T extends object> = {
|
|
28
32
|
[k in keyof T]: undefined extends T[k] ? never : k;
|
|
29
33
|
}[keyof T];
|
|
30
|
-
export type addQuestionMarks<T extends object,
|
|
34
|
+
export type addQuestionMarks<T extends object, _O = any> = {
|
|
35
|
+
[K in requiredKeys<T>]: T[K];
|
|
36
|
+
} & {
|
|
37
|
+
[K in optionalKeys<T>]?: T[K];
|
|
38
|
+
} & {
|
|
39
|
+
[k in keyof T]?: unknown;
|
|
40
|
+
};
|
|
31
41
|
export type identity<T> = T;
|
|
32
42
|
export type flatten<T> = identity<{
|
|
33
43
|
[k in keyof T]: T[k];
|
|
@@ -39,7 +49,11 @@ export declare namespace objectUtil {
|
|
|
39
49
|
[k in noNeverKeys<T>]: k extends keyof T ? T[k] : never;
|
|
40
50
|
}>;
|
|
41
51
|
export const mergeShapes: <U, T>(first: U, second: T) => T & U;
|
|
42
|
-
export type extendShape<A, B
|
|
52
|
+
export type extendShape<A extends object, B extends object> = {
|
|
53
|
+
[K in keyof A as K extends keyof B ? never : K]: A[K];
|
|
54
|
+
} & {
|
|
55
|
+
[K in keyof B]: B[K];
|
|
56
|
+
};
|
|
43
57
|
export {};
|
|
44
58
|
}
|
|
45
59
|
export declare const ZodParsedType: {
|