zod 3.14.3 → 3.15.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 +93 -45
- package/index.d.ts +2 -0
- package/lib/ZodError.d.ts +23 -22
- package/lib/ZodError.js +53 -45
- package/lib/helpers/parseUtil.d.ts +0 -1
- package/lib/index.mjs +79 -70
- package/lib/index.umd.js +2983 -0
- package/lib/types.d.ts +14 -34
- package/lib/types.js +26 -27
- package/package.json +6 -4
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<h1 align="center">Zod</h1>
|
|
4
4
|
</p>
|
|
5
5
|
<p align="center">
|
|
6
|
-
<a href="https://github.com/
|
|
6
|
+
<a href="https://github.com/colinhacks/zod/actions?query=branch%3Amaster"><img src="https://github.com/colinhacks/zod/actions/workflows/test.yml/badge.svg?event=push&branch=master" alt="Zod CI status" /></a>
|
|
7
7
|
<a href="https://twitter.com/colinhacks" rel="nofollow"><img src="https://img.shields.io/badge/created%20by-@colinhacks-4BBAAB.svg" alt="Created by Colin McDonnell"></a>
|
|
8
8
|
<a href="https://opensource.org/licenses/MIT" rel="nofollow"><img src="https://img.shields.io/github/license/colinhacks/zod" alt="License"></a>
|
|
9
9
|
<a href="https://www.npmjs.com/package/zod" rel="nofollow"><img src="https://img.shields.io/npm/dw/zod.svg" alt="npm"></a>
|
|
@@ -125,76 +125,123 @@ Some other great aspects:
|
|
|
125
125
|
|
|
126
126
|
# Sponsorship
|
|
127
127
|
|
|
128
|
-
Sponsorship at any level is appreciated and encouraged.
|
|
128
|
+
Sponsorship at any level is appreciated and encouraged. For individual developers, consider the [Cup of Coffee tier](https://github.com/sponsors/colinhacks). If you built a paid product using Zod, consider one of the [podium tiers](https://github.com/sponsors/colinhacks).
|
|
129
129
|
|
|
130
|
-
###
|
|
130
|
+
### Gold
|
|
131
131
|
|
|
132
132
|
<table>
|
|
133
133
|
<tr>
|
|
134
|
-
|
|
134
|
+
<td align="center">
|
|
135
|
+
<a href="https://astro.build/">
|
|
136
|
+
<img src="https://avatars.githubusercontent.com/u/44914786?s=200&v=4" width="200px;" alt="" />
|
|
137
|
+
</a>
|
|
138
|
+
<br />
|
|
139
|
+
<b>Astro</b>
|
|
140
|
+
<br />
|
|
141
|
+
<a href="https://astro.build">astro.build</a>
|
|
142
|
+
<br />
|
|
143
|
+
<p width="200px">
|
|
144
|
+
Astro is a new kind of static <br/>
|
|
145
|
+
site builder for the modern web. <br/>
|
|
146
|
+
Powerful developer experience meets <br/>
|
|
147
|
+
lightweight output.</p>
|
|
148
|
+
</td>
|
|
149
|
+
<td align="center">
|
|
150
|
+
<a href="https://glow.app/">
|
|
151
|
+
<img src="https://i.imgur.com/R0R43S2.jpg" width="200px;" alt="" />
|
|
152
|
+
</a>
|
|
153
|
+
<br />
|
|
154
|
+
<b>Glow Wallet</b>
|
|
155
|
+
<br />
|
|
156
|
+
<a href="https://glow.app/">glow.app</a>
|
|
157
|
+
<br />
|
|
158
|
+
<p width="200px">Your new favorite
|
|
159
|
+
<br/>
|
|
160
|
+
Solana wallet.</p>
|
|
161
|
+
</td>
|
|
162
|
+
</tr>
|
|
163
|
+
<tr>
|
|
164
|
+
<td align="center">
|
|
135
165
|
<a href="https://deletype.com/">
|
|
136
|
-
<img src="https://avatars0.githubusercontent.com/u/15068039?s=200&v=4" width="
|
|
166
|
+
<img src="https://avatars0.githubusercontent.com/u/15068039?s=200&v=4" width="200px;" alt="" />
|
|
137
167
|
</a>
|
|
138
|
-
<br
|
|
168
|
+
<br />
|
|
139
169
|
<b>Deletype</b>
|
|
140
|
-
<br
|
|
141
|
-
<a href="https://deletype.com
|
|
170
|
+
<br />
|
|
171
|
+
<a href="https://deletype.com">deletype.com</a>
|
|
172
|
+
</td>
|
|
173
|
+
</tr>
|
|
174
|
+
</table>
|
|
175
|
+
|
|
176
|
+
### Silver
|
|
177
|
+
|
|
178
|
+
<table>
|
|
179
|
+
<tr>
|
|
180
|
+
<td align="center">
|
|
181
|
+
<a href="https://snaplet.dev">
|
|
182
|
+
<img src="https://avatars.githubusercontent.com/u/69029941?s=200&v=4" width="150px;" alt="" />
|
|
183
|
+
</a>
|
|
184
|
+
<br />
|
|
185
|
+
<b>Snaplet</b>
|
|
186
|
+
<br />
|
|
187
|
+
<a href="https://snaplet.dev">snaplet.dev</a>
|
|
188
|
+
</td>
|
|
189
|
+
<td align="center">
|
|
190
|
+
<a href="https://marcatopartners.com/">
|
|
191
|
+
<img src="https://avatars.githubusercontent.com/u/84106192?s=200&v=4" width="150px;" alt="Marcato Partners" />
|
|
192
|
+
</a>
|
|
193
|
+
<br />
|
|
194
|
+
<b>Marcato Partners</b>
|
|
195
|
+
<br />
|
|
196
|
+
<a href="https://marcatopartners.com/">marcatopartners.com</a>
|
|
142
197
|
</td>
|
|
143
|
-
|
|
144
|
-
<a href="https://github.com/
|
|
145
|
-
<img src="https://
|
|
198
|
+
<td align="center">
|
|
199
|
+
<a href="https://github.com/macandcheese-spaghetticode">
|
|
200
|
+
<img src="https://avatars.githubusercontent.com/u/76997592?v=4" width="150px;" alt="Trip" />
|
|
146
201
|
</a>
|
|
147
|
-
<br
|
|
148
|
-
<b>
|
|
149
|
-
<br>
|
|
150
|
-
<a href="https://github.com/kevinsimper">@kevinsimper</a>
|
|
202
|
+
<br />
|
|
203
|
+
<b>Trip</b>
|
|
151
204
|
</td>
|
|
205
|
+
</tr>
|
|
206
|
+
</table>
|
|
207
|
+
|
|
208
|
+
### Bronze
|
|
209
|
+
|
|
210
|
+
<table>
|
|
211
|
+
<tr>
|
|
152
212
|
<td align="center">
|
|
153
213
|
<a href="https://twitter.com/flybayer">
|
|
154
214
|
<img src="https://avatars2.githubusercontent.com/u/8813276?s=460&u=4ff8beb9a67b173015c4b426a92d89cab960af1b&v=4" width="100px;" alt=""/>
|
|
155
215
|
</a>
|
|
156
|
-
<br
|
|
216
|
+
<br />
|
|
157
217
|
<b>Brandon Bayer</b>
|
|
158
218
|
<br/>
|
|
159
219
|
<a href="https://twitter.com/flybayer">@flybayer</a>,
|
|
160
220
|
<span>creator of <a href="https://blitzjs.com">Blitz.js</a></span>
|
|
161
221
|
<br />
|
|
162
222
|
</td>
|
|
163
|
-
|
|
164
|
-
</tr>
|
|
165
|
-
<tr>
|
|
166
|
-
<td align="center">
|
|
167
|
-
<a href="https://www.bamboocreative.nz/">
|
|
168
|
-
<img src="https://avatars1.githubusercontent.com/u/41406870?s=460&v=4" width="100px;" alt="" />
|
|
169
|
-
</a>
|
|
170
|
-
<br>
|
|
171
|
-
<b>Bamboo Creative</b>
|
|
172
|
-
<br>
|
|
173
|
-
<a href="https://www.bamboocreative.nz/">bamboocreative.nz</a>
|
|
174
|
-
</td>
|
|
175
223
|
<td align="center">
|
|
176
|
-
<a href="https://github.com/
|
|
177
|
-
<img src="https://avatars.githubusercontent.com/u/
|
|
224
|
+
<a href="https://github.com/brabeji">
|
|
225
|
+
<img src="https://avatars.githubusercontent.com/u/2237954?v=4" width="100px;" alt=""/>
|
|
178
226
|
</a>
|
|
179
|
-
<br
|
|
180
|
-
<b>
|
|
181
|
-
<br
|
|
182
|
-
<a href="https://github.com/
|
|
227
|
+
<br />
|
|
228
|
+
<b>Jiří Brabec</b>
|
|
229
|
+
<br/>
|
|
230
|
+
<a href="https://github.com/brabeji">@brabeji</a>
|
|
231
|
+
<br />
|
|
183
232
|
</td>
|
|
184
233
|
<td align="center">
|
|
185
|
-
<a href="https://
|
|
186
|
-
<img src="https://avatars.githubusercontent.com/u/
|
|
234
|
+
<a href="https://twitter.com/alexdotjs">
|
|
235
|
+
<img src="https://avatars.githubusercontent.com/u/459267?v=4" width="100px;" alt="" />
|
|
187
236
|
</a>
|
|
188
|
-
<br
|
|
189
|
-
<b>
|
|
190
|
-
<br
|
|
191
|
-
<a href="https://
|
|
237
|
+
<br />
|
|
238
|
+
<b>Alex Johansson</b>
|
|
239
|
+
<br />
|
|
240
|
+
<a href="https://twitter.com/alexdotjs">@alexdotjs</a>
|
|
192
241
|
</td>
|
|
193
242
|
</tr>
|
|
194
243
|
</table>
|
|
195
244
|
|
|
196
|
-
_To get your name + Twitter + website here, sponsor Zod at the [Freelancer](https://github.com/sponsors/colinhacks) or [Consultancy](https://github.com/sponsors/colinhacks) tier._
|
|
197
|
-
|
|
198
245
|
# Installation
|
|
199
246
|
|
|
200
247
|
To install Zod v3:
|
|
@@ -245,6 +292,7 @@ There are a growing number of tools that are built atop or support Zod natively!
|
|
|
245
292
|
- [`zod-prisma`](https://github.com/CarterGrimmeisen/zod-prisma): Generate Zod schemas from your Prisma schema.
|
|
246
293
|
- [`fastify-type-provider-zod`](https://github.com/turkerdev/fastify-type-provider-zod): Create Fastify type providers from Zod schemas
|
|
247
294
|
- [`Supervillain`](https://github.com/Southclaws/supervillain): Generate Zod schemas from your Go structs
|
|
295
|
+
- [`zod-to-openapi`](https://github.com/asteasolutions/zod-to-openapi): Generate full OpenAPI (Swagger) docs from Zod, including schemas, endpoints & parameters
|
|
248
296
|
|
|
249
297
|
### Form integrations
|
|
250
298
|
|
|
@@ -1138,9 +1186,9 @@ const Category: z.ZodType<Category> = BaseCategory.merge(
|
|
|
1138
1186
|
If you want to validate any JSON value, you can use the snippet below.
|
|
1139
1187
|
|
|
1140
1188
|
```ts
|
|
1141
|
-
type Literal = boolean | null | number | string;
|
|
1142
|
-
type Json = Literal | { [key: string]: Json } | Json[];
|
|
1143
1189
|
const literalSchema = z.union([z.string(), z.number(), z.boolean(), z.null()]);
|
|
1190
|
+
type Literal = z.infer<typeof literalSchema>;
|
|
1191
|
+
type Json = Literal | { [key: string]: Json } | Json[];
|
|
1144
1192
|
const jsonSchema: z.ZodType<Json> = z.lazy(() =>
|
|
1145
1193
|
z.union([literalSchema, z.array(jsonSchema), z.record(jsonSchema)])
|
|
1146
1194
|
);
|
|
@@ -1768,7 +1816,7 @@ class ZodType<
|
|
|
1768
1816
|
> { ... }
|
|
1769
1817
|
```
|
|
1770
1818
|
|
|
1771
|
-
By
|
|
1819
|
+
By constraining these in your generic input, you can limit what schemas are allowable as inputs to your function:
|
|
1772
1820
|
|
|
1773
1821
|
```ts
|
|
1774
1822
|
function makeSchemaOptional<T extends z.ZodType<string>>(schema: T) {
|
package/index.d.ts
ADDED
package/lib/ZodError.d.ts
CHANGED
|
@@ -1,8 +1,18 @@
|
|
|
1
|
+
import type { TypeOf, ZodType } from ".";
|
|
1
2
|
import { ZodParsedType } from "./helpers/parseUtil";
|
|
2
3
|
import { Primitive } from "./helpers/typeAliases";
|
|
3
4
|
import { util } from "./helpers/util";
|
|
5
|
+
declare type allKeys<T> = T extends any ? keyof T : never;
|
|
6
|
+
export declare type inferFlattenedErrors<T extends ZodType<any, any, any>, U = string> = typeToFlattenedError<TypeOf<T>, U>;
|
|
7
|
+
export declare type typeToFlattenedError<T, U = string> = {
|
|
8
|
+
formErrors: U[];
|
|
9
|
+
fieldErrors: {
|
|
10
|
+
[P in allKeys<T>]?: U[];
|
|
11
|
+
};
|
|
12
|
+
};
|
|
4
13
|
export declare const ZodIssueCode: {
|
|
5
14
|
invalid_type: "invalid_type";
|
|
15
|
+
invalid_literal: "invalid_literal";
|
|
6
16
|
custom: "custom";
|
|
7
17
|
invalid_union: "invalid_union";
|
|
8
18
|
invalid_union_discriminator: "invalid_union_discriminator";
|
|
@@ -27,6 +37,10 @@ export interface ZodInvalidTypeIssue extends ZodIssueBase {
|
|
|
27
37
|
expected: ZodParsedType;
|
|
28
38
|
received: ZodParsedType;
|
|
29
39
|
}
|
|
40
|
+
export interface ZodInvalidLiteralIssue extends ZodIssueBase {
|
|
41
|
+
code: typeof ZodIssueCode.invalid_literal;
|
|
42
|
+
expected: unknown;
|
|
43
|
+
}
|
|
30
44
|
export interface ZodUnrecognizedKeysIssue extends ZodIssueBase {
|
|
31
45
|
code: typeof ZodIssueCode.unrecognized_keys;
|
|
32
46
|
keys: string[];
|
|
@@ -87,47 +101,34 @@ export interface ZodCustomIssue extends ZodIssueBase {
|
|
|
87
101
|
export declare type DenormalizedError = {
|
|
88
102
|
[k: string]: DenormalizedError | string[];
|
|
89
103
|
};
|
|
90
|
-
export declare type ZodIssueOptionalMessage = ZodInvalidTypeIssue | ZodUnrecognizedKeysIssue | ZodInvalidUnionIssue | ZodInvalidUnionDiscriminatorIssue | ZodInvalidEnumValueIssue | ZodInvalidArgumentsIssue | ZodInvalidReturnTypeIssue | ZodInvalidDateIssue | ZodInvalidStringIssue | ZodTooSmallIssue | ZodTooBigIssue | ZodInvalidIntersectionTypesIssue | ZodNotMultipleOfIssue | ZodCustomIssue;
|
|
104
|
+
export declare type ZodIssueOptionalMessage = ZodInvalidTypeIssue | ZodInvalidLiteralIssue | ZodUnrecognizedKeysIssue | ZodInvalidUnionIssue | ZodInvalidUnionDiscriminatorIssue | ZodInvalidEnumValueIssue | ZodInvalidArgumentsIssue | ZodInvalidReturnTypeIssue | ZodInvalidDateIssue | ZodInvalidStringIssue | ZodTooSmallIssue | ZodTooBigIssue | ZodInvalidIntersectionTypesIssue | ZodNotMultipleOfIssue | ZodCustomIssue;
|
|
91
105
|
export declare type ZodIssue = ZodIssueOptionalMessage & {
|
|
92
106
|
message: string;
|
|
93
107
|
};
|
|
94
108
|
export declare const quotelessJson: (obj: any) => string;
|
|
95
|
-
export declare type ZodFormattedError<T> = {
|
|
96
|
-
_errors:
|
|
109
|
+
export declare type ZodFormattedError<T, U = string> = {
|
|
110
|
+
_errors: U[];
|
|
97
111
|
} & (T extends [any, ...any[]] ? {
|
|
98
112
|
[K in keyof T]?: ZodFormattedError<T[K]>;
|
|
99
113
|
} : T extends any[] ? ZodFormattedError<T[number]>[] : T extends object ? {
|
|
100
114
|
[K in keyof T]?: ZodFormattedError<T[K]>;
|
|
101
115
|
} : unknown);
|
|
116
|
+
export declare type inferFormattedError<T extends ZodType<any, any, any>, U = string> = ZodFormattedError<TypeOf<T>, U>;
|
|
102
117
|
export declare class ZodError<T = any> extends Error {
|
|
103
118
|
issues: ZodIssue[];
|
|
104
119
|
get errors(): ZodIssue[];
|
|
105
120
|
constructor(issues: ZodIssue[]);
|
|
106
|
-
format
|
|
121
|
+
format(): ZodFormattedError<T>;
|
|
122
|
+
format<U>(mapper: (issue: ZodIssue) => U): ZodFormattedError<T, U>;
|
|
107
123
|
static create: (issues: ZodIssue[]) => ZodError<any>;
|
|
108
124
|
toString(): string;
|
|
109
125
|
get message(): string;
|
|
110
126
|
get isEmpty(): boolean;
|
|
111
127
|
addIssue: (sub: ZodIssue) => void;
|
|
112
128
|
addIssues: (subs?: ZodIssue[]) => void;
|
|
113
|
-
flatten(
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
[k: string]: string[];
|
|
117
|
-
};
|
|
118
|
-
};
|
|
119
|
-
flatten<U>(mapper?: (issue: ZodIssue) => U): {
|
|
120
|
-
formErrors: U[];
|
|
121
|
-
fieldErrors: {
|
|
122
|
-
[k: string]: U[];
|
|
123
|
-
};
|
|
124
|
-
};
|
|
125
|
-
get formErrors(): {
|
|
126
|
-
formErrors: string[];
|
|
127
|
-
fieldErrors: {
|
|
128
|
-
[k: string]: string[];
|
|
129
|
-
};
|
|
130
|
-
};
|
|
129
|
+
flatten(): typeToFlattenedError<T>;
|
|
130
|
+
flatten<U>(mapper?: (issue: ZodIssue) => U): typeToFlattenedError<T, U>;
|
|
131
|
+
get formErrors(): typeToFlattenedError<T, string>;
|
|
131
132
|
}
|
|
132
133
|
declare type stripPath<T extends object> = T extends any ? util.OmitKeys<T, "path"> : never;
|
|
133
134
|
export declare type IssueData = stripPath<ZodIssueOptionalMessage> & {
|
package/lib/ZodError.js
CHANGED
|
@@ -4,6 +4,7 @@ exports.setErrorMap = exports.overrideErrorMap = exports.defaultErrorMap = expor
|
|
|
4
4
|
const util_1 = require("./helpers/util");
|
|
5
5
|
exports.ZodIssueCode = util_1.util.arrayToEnum([
|
|
6
6
|
"invalid_type",
|
|
7
|
+
"invalid_literal",
|
|
7
8
|
"custom",
|
|
8
9
|
"invalid_union",
|
|
9
10
|
"invalid_union_discriminator",
|
|
@@ -27,51 +28,6 @@ class ZodError extends Error {
|
|
|
27
28
|
constructor(issues) {
|
|
28
29
|
super();
|
|
29
30
|
this.issues = [];
|
|
30
|
-
this.format = () => {
|
|
31
|
-
const fieldErrors = { _errors: [] };
|
|
32
|
-
const processError = (error) => {
|
|
33
|
-
for (const issue of error.issues) {
|
|
34
|
-
if (issue.code === "invalid_union") {
|
|
35
|
-
issue.unionErrors.map(processError);
|
|
36
|
-
}
|
|
37
|
-
else if (issue.code === "invalid_return_type") {
|
|
38
|
-
processError(issue.returnTypeError);
|
|
39
|
-
}
|
|
40
|
-
else if (issue.code === "invalid_arguments") {
|
|
41
|
-
processError(issue.argumentsError);
|
|
42
|
-
}
|
|
43
|
-
else if (issue.path.length === 0) {
|
|
44
|
-
fieldErrors._errors.push(issue.message);
|
|
45
|
-
}
|
|
46
|
-
else {
|
|
47
|
-
let curr = fieldErrors;
|
|
48
|
-
let i = 0;
|
|
49
|
-
while (i < issue.path.length) {
|
|
50
|
-
const el = issue.path[i];
|
|
51
|
-
const terminal = i === issue.path.length - 1;
|
|
52
|
-
if (!terminal) {
|
|
53
|
-
if (typeof el === "string") {
|
|
54
|
-
curr[el] = curr[el] || { _errors: [] };
|
|
55
|
-
}
|
|
56
|
-
else if (typeof el === "number") {
|
|
57
|
-
const errorArray = [];
|
|
58
|
-
errorArray._errors = [];
|
|
59
|
-
curr[el] = curr[el] || errorArray;
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
else {
|
|
63
|
-
curr[el] = curr[el] || { _errors: [] };
|
|
64
|
-
curr[el]._errors.push(issue.message);
|
|
65
|
-
}
|
|
66
|
-
curr = curr[el];
|
|
67
|
-
i++;
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
};
|
|
72
|
-
processError(this);
|
|
73
|
-
return fieldErrors;
|
|
74
|
-
};
|
|
75
31
|
this.addIssue = (sub) => {
|
|
76
32
|
this.issues = [...this.issues, sub];
|
|
77
33
|
};
|
|
@@ -92,6 +48,55 @@ class ZodError extends Error {
|
|
|
92
48
|
get errors() {
|
|
93
49
|
return this.issues;
|
|
94
50
|
}
|
|
51
|
+
format(_mapper) {
|
|
52
|
+
const mapper = _mapper ||
|
|
53
|
+
function (issue) {
|
|
54
|
+
return issue.message;
|
|
55
|
+
};
|
|
56
|
+
const fieldErrors = { _errors: [] };
|
|
57
|
+
const processError = (error) => {
|
|
58
|
+
for (const issue of error.issues) {
|
|
59
|
+
if (issue.code === "invalid_union") {
|
|
60
|
+
issue.unionErrors.map(processError);
|
|
61
|
+
}
|
|
62
|
+
else if (issue.code === "invalid_return_type") {
|
|
63
|
+
processError(issue.returnTypeError);
|
|
64
|
+
}
|
|
65
|
+
else if (issue.code === "invalid_arguments") {
|
|
66
|
+
processError(issue.argumentsError);
|
|
67
|
+
}
|
|
68
|
+
else if (issue.path.length === 0) {
|
|
69
|
+
fieldErrors._errors.push(mapper(issue));
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
let curr = fieldErrors;
|
|
73
|
+
let i = 0;
|
|
74
|
+
while (i < issue.path.length) {
|
|
75
|
+
const el = issue.path[i];
|
|
76
|
+
const terminal = i === issue.path.length - 1;
|
|
77
|
+
if (!terminal) {
|
|
78
|
+
if (typeof el === "string") {
|
|
79
|
+
curr[el] = curr[el] || { _errors: [] };
|
|
80
|
+
}
|
|
81
|
+
else if (typeof el === "number") {
|
|
82
|
+
const errorArray = [];
|
|
83
|
+
errorArray._errors = [];
|
|
84
|
+
curr[el] = curr[el] || errorArray;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
curr[el] = curr[el] || { _errors: [] };
|
|
89
|
+
curr[el]._errors.push(mapper(issue));
|
|
90
|
+
}
|
|
91
|
+
curr = curr[el];
|
|
92
|
+
i++;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
processError(this);
|
|
98
|
+
return fieldErrors;
|
|
99
|
+
}
|
|
95
100
|
toString() {
|
|
96
101
|
return this.message;
|
|
97
102
|
}
|
|
@@ -135,6 +140,9 @@ const defaultErrorMap = (issue, _ctx) => {
|
|
|
135
140
|
message = `Expected ${issue.expected}, received ${issue.received}`;
|
|
136
141
|
}
|
|
137
142
|
break;
|
|
143
|
+
case exports.ZodIssueCode.invalid_literal:
|
|
144
|
+
message = `Invalid literal value, expected ${JSON.stringify(issue.expected)}`;
|
|
145
|
+
break;
|
|
138
146
|
case exports.ZodIssueCode.unrecognized_keys:
|
|
139
147
|
message = `Unrecognized key(s) in object: ${issue.keys
|
|
140
148
|
.map((k) => `'${k}'`)
|
|
@@ -42,7 +42,6 @@ export interface ParseContext {
|
|
|
42
42
|
readonly issues: ZodIssue[];
|
|
43
43
|
readonly contextualErrorMap?: ZodErrorMap;
|
|
44
44
|
readonly async: boolean;
|
|
45
|
-
readonly typeCache: Map<any, ZodParsedType> | undefined;
|
|
46
45
|
};
|
|
47
46
|
readonly path: ParsePath;
|
|
48
47
|
readonly schemaErrorMap?: ZodErrorMap;
|
package/lib/index.mjs
CHANGED
|
@@ -49,6 +49,7 @@ var util;
|
|
|
49
49
|
|
|
50
50
|
const ZodIssueCode = util.arrayToEnum([
|
|
51
51
|
"invalid_type",
|
|
52
|
+
"invalid_literal",
|
|
52
53
|
"custom",
|
|
53
54
|
"invalid_union",
|
|
54
55
|
"invalid_union_discriminator",
|
|
@@ -71,51 +72,6 @@ class ZodError extends Error {
|
|
|
71
72
|
constructor(issues) {
|
|
72
73
|
super();
|
|
73
74
|
this.issues = [];
|
|
74
|
-
this.format = () => {
|
|
75
|
-
const fieldErrors = { _errors: [] };
|
|
76
|
-
const processError = (error) => {
|
|
77
|
-
for (const issue of error.issues) {
|
|
78
|
-
if (issue.code === "invalid_union") {
|
|
79
|
-
issue.unionErrors.map(processError);
|
|
80
|
-
}
|
|
81
|
-
else if (issue.code === "invalid_return_type") {
|
|
82
|
-
processError(issue.returnTypeError);
|
|
83
|
-
}
|
|
84
|
-
else if (issue.code === "invalid_arguments") {
|
|
85
|
-
processError(issue.argumentsError);
|
|
86
|
-
}
|
|
87
|
-
else if (issue.path.length === 0) {
|
|
88
|
-
fieldErrors._errors.push(issue.message);
|
|
89
|
-
}
|
|
90
|
-
else {
|
|
91
|
-
let curr = fieldErrors;
|
|
92
|
-
let i = 0;
|
|
93
|
-
while (i < issue.path.length) {
|
|
94
|
-
const el = issue.path[i];
|
|
95
|
-
const terminal = i === issue.path.length - 1;
|
|
96
|
-
if (!terminal) {
|
|
97
|
-
if (typeof el === "string") {
|
|
98
|
-
curr[el] = curr[el] || { _errors: [] };
|
|
99
|
-
}
|
|
100
|
-
else if (typeof el === "number") {
|
|
101
|
-
const errorArray = [];
|
|
102
|
-
errorArray._errors = [];
|
|
103
|
-
curr[el] = curr[el] || errorArray;
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
else {
|
|
107
|
-
curr[el] = curr[el] || { _errors: [] };
|
|
108
|
-
curr[el]._errors.push(issue.message);
|
|
109
|
-
}
|
|
110
|
-
curr = curr[el];
|
|
111
|
-
i++;
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
};
|
|
116
|
-
processError(this);
|
|
117
|
-
return fieldErrors;
|
|
118
|
-
};
|
|
119
75
|
this.addIssue = (sub) => {
|
|
120
76
|
this.issues = [...this.issues, sub];
|
|
121
77
|
};
|
|
@@ -136,6 +92,55 @@ class ZodError extends Error {
|
|
|
136
92
|
get errors() {
|
|
137
93
|
return this.issues;
|
|
138
94
|
}
|
|
95
|
+
format(_mapper) {
|
|
96
|
+
const mapper = _mapper ||
|
|
97
|
+
function (issue) {
|
|
98
|
+
return issue.message;
|
|
99
|
+
};
|
|
100
|
+
const fieldErrors = { _errors: [] };
|
|
101
|
+
const processError = (error) => {
|
|
102
|
+
for (const issue of error.issues) {
|
|
103
|
+
if (issue.code === "invalid_union") {
|
|
104
|
+
issue.unionErrors.map(processError);
|
|
105
|
+
}
|
|
106
|
+
else if (issue.code === "invalid_return_type") {
|
|
107
|
+
processError(issue.returnTypeError);
|
|
108
|
+
}
|
|
109
|
+
else if (issue.code === "invalid_arguments") {
|
|
110
|
+
processError(issue.argumentsError);
|
|
111
|
+
}
|
|
112
|
+
else if (issue.path.length === 0) {
|
|
113
|
+
fieldErrors._errors.push(mapper(issue));
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
let curr = fieldErrors;
|
|
117
|
+
let i = 0;
|
|
118
|
+
while (i < issue.path.length) {
|
|
119
|
+
const el = issue.path[i];
|
|
120
|
+
const terminal = i === issue.path.length - 1;
|
|
121
|
+
if (!terminal) {
|
|
122
|
+
if (typeof el === "string") {
|
|
123
|
+
curr[el] = curr[el] || { _errors: [] };
|
|
124
|
+
}
|
|
125
|
+
else if (typeof el === "number") {
|
|
126
|
+
const errorArray = [];
|
|
127
|
+
errorArray._errors = [];
|
|
128
|
+
curr[el] = curr[el] || errorArray;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
curr[el] = curr[el] || { _errors: [] };
|
|
133
|
+
curr[el]._errors.push(mapper(issue));
|
|
134
|
+
}
|
|
135
|
+
curr = curr[el];
|
|
136
|
+
i++;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
processError(this);
|
|
142
|
+
return fieldErrors;
|
|
143
|
+
}
|
|
139
144
|
toString() {
|
|
140
145
|
return this.message;
|
|
141
146
|
}
|
|
@@ -178,6 +183,9 @@ const defaultErrorMap = (issue, _ctx) => {
|
|
|
178
183
|
message = `Expected ${issue.expected}, received ${issue.received}`;
|
|
179
184
|
}
|
|
180
185
|
break;
|
|
186
|
+
case ZodIssueCode.invalid_literal:
|
|
187
|
+
message = `Invalid literal value, expected ${JSON.stringify(issue.expected)}`;
|
|
188
|
+
break;
|
|
181
189
|
case ZodIssueCode.unrecognized_keys:
|
|
182
190
|
message = `Unrecognized key(s) in object: ${issue.keys
|
|
183
191
|
.map((k) => `'${k}'`)
|
|
@@ -541,7 +549,6 @@ class ZodType {
|
|
|
541
549
|
common: {
|
|
542
550
|
issues: [],
|
|
543
551
|
async: (_a = params === null || params === void 0 ? void 0 : params.async) !== null && _a !== void 0 ? _a : false,
|
|
544
|
-
typeCache: typeof Map !== "undefined" ? new Map() : undefined,
|
|
545
552
|
contextualErrorMap: params === null || params === void 0 ? void 0 : params.errorMap,
|
|
546
553
|
},
|
|
547
554
|
path: (params === null || params === void 0 ? void 0 : params.path) || [],
|
|
@@ -565,7 +572,6 @@ class ZodType {
|
|
|
565
572
|
issues: [],
|
|
566
573
|
contextualErrorMap: params === null || params === void 0 ? void 0 : params.errorMap,
|
|
567
574
|
async: true,
|
|
568
|
-
typeCache: typeof Map !== "undefined" ? new Map() : undefined,
|
|
569
575
|
},
|
|
570
576
|
path: (params === null || params === void 0 ? void 0 : params.path) || [],
|
|
571
577
|
schemaErrorMap: this._def.errorMap,
|
|
@@ -1445,8 +1451,12 @@ class ZodObject extends ZodType {
|
|
|
1445
1451
|
}
|
|
1446
1452
|
const { status, ctx } = this._processInputParams(input);
|
|
1447
1453
|
const { shape, keys: shapeKeys } = this._getCached();
|
|
1448
|
-
const
|
|
1449
|
-
const
|
|
1454
|
+
const extraKeys = [];
|
|
1455
|
+
for (const key in ctx.data) {
|
|
1456
|
+
if (!shapeKeys.includes(key)) {
|
|
1457
|
+
extraKeys.push(key);
|
|
1458
|
+
}
|
|
1459
|
+
}
|
|
1450
1460
|
const pairs = [];
|
|
1451
1461
|
for (const key of shapeKeys) {
|
|
1452
1462
|
const keyValidator = shape[key];
|
|
@@ -2354,9 +2364,8 @@ class ZodLiteral extends ZodType {
|
|
|
2354
2364
|
if (input.data !== this._def.value) {
|
|
2355
2365
|
const ctx = this._getOrReturnCtx(input);
|
|
2356
2366
|
addIssueToContext(ctx, {
|
|
2357
|
-
code: ZodIssueCode.
|
|
2358
|
-
expected:
|
|
2359
|
-
received: ctx.parsedType,
|
|
2367
|
+
code: ZodIssueCode.invalid_literal,
|
|
2368
|
+
expected: this._def.value,
|
|
2360
2369
|
});
|
|
2361
2370
|
return INVALID;
|
|
2362
2371
|
}
|
|
@@ -2497,22 +2506,22 @@ class ZodEffects extends ZodType {
|
|
|
2497
2506
|
});
|
|
2498
2507
|
}
|
|
2499
2508
|
}
|
|
2509
|
+
const checkCtx = {
|
|
2510
|
+
addIssue: (arg) => {
|
|
2511
|
+
addIssueToContext(ctx, arg);
|
|
2512
|
+
if (arg.fatal) {
|
|
2513
|
+
status.abort();
|
|
2514
|
+
}
|
|
2515
|
+
else {
|
|
2516
|
+
status.dirty();
|
|
2517
|
+
}
|
|
2518
|
+
},
|
|
2519
|
+
get path() {
|
|
2520
|
+
return ctx.path;
|
|
2521
|
+
},
|
|
2522
|
+
};
|
|
2523
|
+
checkCtx.addIssue = checkCtx.addIssue.bind(checkCtx);
|
|
2500
2524
|
if (effect.type === "refinement") {
|
|
2501
|
-
const checkCtx = {
|
|
2502
|
-
addIssue: (arg) => {
|
|
2503
|
-
addIssueToContext(ctx, arg);
|
|
2504
|
-
if (arg.fatal) {
|
|
2505
|
-
status.abort();
|
|
2506
|
-
}
|
|
2507
|
-
else {
|
|
2508
|
-
status.dirty();
|
|
2509
|
-
}
|
|
2510
|
-
},
|
|
2511
|
-
get path() {
|
|
2512
|
-
return ctx.path;
|
|
2513
|
-
},
|
|
2514
|
-
};
|
|
2515
|
-
checkCtx.addIssue = checkCtx.addIssue.bind(checkCtx);
|
|
2516
2525
|
const executeRefinement = (acc
|
|
2517
2526
|
// effect: RefinementEffect<any>
|
|
2518
2527
|
) => {
|
|
@@ -2566,11 +2575,11 @@ class ZodEffects extends ZodType {
|
|
|
2566
2575
|
// }
|
|
2567
2576
|
if (!isValid(base))
|
|
2568
2577
|
return base;
|
|
2569
|
-
const result = effect.transform(base.value);
|
|
2578
|
+
const result = effect.transform(base.value, checkCtx);
|
|
2570
2579
|
if (result instanceof Promise) {
|
|
2571
2580
|
throw new Error(`Asynchronous transform encountered during synchronous parse operation. Use .parseAsync instead.`);
|
|
2572
2581
|
}
|
|
2573
|
-
return
|
|
2582
|
+
return { status: status.value, value: result };
|
|
2574
2583
|
}
|
|
2575
2584
|
else {
|
|
2576
2585
|
return this._def.schema
|
|
@@ -2582,7 +2591,7 @@ class ZodEffects extends ZodType {
|
|
|
2582
2591
|
// if (base.status === "dirty") {
|
|
2583
2592
|
// return { status: "dirty", value: base.value };
|
|
2584
2593
|
// }
|
|
2585
|
-
return Promise.resolve(effect.transform(base.value)).then(OK);
|
|
2594
|
+
return Promise.resolve(effect.transform(base.value, checkCtx)).then(OK);
|
|
2586
2595
|
});
|
|
2587
2596
|
}
|
|
2588
2597
|
}
|