zod 3.14.4 → 3.15.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 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/edgedb/edgedb-js/actions"><img src="https://github.com/colinhacks/zod/actions/workflows/test.yml/badge.svg?event=push&branch=master" alt="Zod CI status" /></a>
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. Zod is maintained by a solo developer ([hi!](https://twitter.com/colinhacks)). For individual developers, consider the [Cup of Coffee tier](https://github.com/sponsors/colinhacks). If you built a paid product using Zod, consider the [Startup tier](https://github.com/sponsors/colinhacks). You can learn more about the tiers at [github.com/sponsors/colinhacks](https://github.com/sponsors/colinhacks).
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
- ### Sponsors
130
+ ### Gold
131
131
 
132
132
  <table>
133
133
  <tr>
134
- <td align="center">
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="100px;" alt="" />
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/">deletype.com/</a>
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
- <td align="center">
144
- <a href="https://github.com/kevinsimper">
145
- <img src="https://avatars1.githubusercontent.com/u/1126497?s=460&v=4" width="100px;" alt="" />
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>Kevin Simper</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/jeremyBanks">
177
- <img src="https://avatars.githubusercontent.com/u/18020?s=400&u=dba6c1402ae1746a276a5d256e01d68e774a0e9d&v=4" width="100px;" alt="" />
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>Jeremy Banks</b>
181
- <br>
182
- <a href="https://github.com/jeremyBanks">github.com/jeremyBanks</a>
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://marcatopartners.com/">
186
- <img src="https://avatars.githubusercontent.com/u/84106192?s=200&v=4" width="100px;" alt="Marcato Partners" />
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>Marcato Partners</b>
190
- <br>
191
- <a href="https://marcatopartners.com/">marcatopartners.com</a>
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
  );
@@ -1305,7 +1353,7 @@ All Zod schemas contain certain methods.
1305
1353
 
1306
1354
  Given any Zod schema, you can call its `.parse` method to check `data` is valid. If it is, a value is returned with full type information! Otherwise, an error is thrown.
1307
1355
 
1308
- > IMPORTANT: In Zod 2 and Zod 1.11+, the value returned by `.parse` is a _deep clone_ of the variable you passed in. This was also the case in zod@1.4 and earlier.
1356
+ > IMPORTANT: The value returned by `.parse` is a _deep clone_ of the variable you passed in.
1309
1357
 
1310
1358
  ```ts
1311
1359
  const stringSchema = z.string();
@@ -1768,7 +1816,7 @@ class ZodType<
1768
1816
  > { ... }
1769
1817
  ```
1770
1818
 
1771
- By contraining these in your generic input, you can limit what schemas are allowable as inputs to your function:
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
@@ -0,0 +1,2 @@
1
+ export * from "./lib";
2
+ export as namespace Zod;
package/lib/ZodError.d.ts CHANGED
@@ -1,6 +1,15 @@
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";
6
15
  invalid_literal: "invalid_literal";
@@ -97,42 +106,31 @@ export declare type ZodIssue = ZodIssueOptionalMessage & {
97
106
  message: string;
98
107
  };
99
108
  export declare const quotelessJson: (obj: any) => string;
100
- export declare type ZodFormattedError<T> = {
101
- _errors: string[];
109
+ export declare type ZodFormattedError<T, U = string> = {
110
+ _errors: U[];
102
111
  } & (T extends [any, ...any[]] ? {
103
112
  [K in keyof T]?: ZodFormattedError<T[K]>;
104
- } : T extends any[] ? ZodFormattedError<T[number]>[] : T extends object ? {
113
+ } : T extends any[] ? {
114
+ [k: number]: ZodFormattedError<T[number]>;
115
+ } : T extends object ? {
105
116
  [K in keyof T]?: ZodFormattedError<T[K]>;
106
117
  } : unknown);
118
+ export declare type inferFormattedError<T extends ZodType<any, any, any>, U = string> = ZodFormattedError<TypeOf<T>, U>;
107
119
  export declare class ZodError<T = any> extends Error {
108
120
  issues: ZodIssue[];
109
121
  get errors(): ZodIssue[];
110
122
  constructor(issues: ZodIssue[]);
111
- format: () => ZodFormattedError<T>;
123
+ format(): ZodFormattedError<T>;
124
+ format<U>(mapper: (issue: ZodIssue) => U): ZodFormattedError<T, U>;
112
125
  static create: (issues: ZodIssue[]) => ZodError<any>;
113
126
  toString(): string;
114
127
  get message(): string;
115
128
  get isEmpty(): boolean;
116
129
  addIssue: (sub: ZodIssue) => void;
117
130
  addIssues: (subs?: ZodIssue[]) => void;
118
- flatten(mapper?: (issue: ZodIssue) => string): {
119
- formErrors: string[];
120
- fieldErrors: {
121
- [k: string]: string[];
122
- };
123
- };
124
- flatten<U>(mapper?: (issue: ZodIssue) => U): {
125
- formErrors: U[];
126
- fieldErrors: {
127
- [k: string]: U[];
128
- };
129
- };
130
- get formErrors(): {
131
- formErrors: string[];
132
- fieldErrors: {
133
- [k: string]: string[];
134
- };
135
- };
131
+ flatten(): typeToFlattenedError<T>;
132
+ flatten<U>(mapper?: (issue: ZodIssue) => U): typeToFlattenedError<T, U>;
133
+ get formErrors(): typeToFlattenedError<T, string>;
136
134
  }
137
135
  declare type stripPath<T extends object> = T extends any ? util.OmitKeys<T, "path"> : never;
138
136
  export declare type IssueData = stripPath<ZodIssueOptionalMessage> & {
package/lib/ZodError.js CHANGED
@@ -28,51 +28,6 @@ class ZodError extends Error {
28
28
  constructor(issues) {
29
29
  super();
30
30
  this.issues = [];
31
- this.format = () => {
32
- const fieldErrors = { _errors: [] };
33
- const processError = (error) => {
34
- for (const issue of error.issues) {
35
- if (issue.code === "invalid_union") {
36
- issue.unionErrors.map(processError);
37
- }
38
- else if (issue.code === "invalid_return_type") {
39
- processError(issue.returnTypeError);
40
- }
41
- else if (issue.code === "invalid_arguments") {
42
- processError(issue.argumentsError);
43
- }
44
- else if (issue.path.length === 0) {
45
- fieldErrors._errors.push(issue.message);
46
- }
47
- else {
48
- let curr = fieldErrors;
49
- let i = 0;
50
- while (i < issue.path.length) {
51
- const el = issue.path[i];
52
- const terminal = i === issue.path.length - 1;
53
- if (!terminal) {
54
- if (typeof el === "string") {
55
- curr[el] = curr[el] || { _errors: [] };
56
- }
57
- else if (typeof el === "number") {
58
- const errorArray = [];
59
- errorArray._errors = [];
60
- curr[el] = curr[el] || errorArray;
61
- }
62
- }
63
- else {
64
- curr[el] = curr[el] || { _errors: [] };
65
- curr[el]._errors.push(issue.message);
66
- }
67
- curr = curr[el];
68
- i++;
69
- }
70
- }
71
- }
72
- };
73
- processError(this);
74
- return fieldErrors;
75
- };
76
31
  this.addIssue = (sub) => {
77
32
  this.issues = [...this.issues, sub];
78
33
  };
@@ -93,6 +48,55 @@ class ZodError extends Error {
93
48
  get errors() {
94
49
  return this.issues;
95
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
+ curr[el] = curr[el] || { _errors: [] };
79
+ // if (typeof el === "string") {
80
+ // curr[el] = curr[el] || { _errors: [] };
81
+ // } else if (typeof el === "number") {
82
+ // const errorArray: any = [];
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
+ }
96
100
  toString() {
97
101
  return this.message;
98
102
  }
package/lib/index.mjs CHANGED
@@ -72,51 +72,6 @@ class ZodError extends Error {
72
72
  constructor(issues) {
73
73
  super();
74
74
  this.issues = [];
75
- this.format = () => {
76
- const fieldErrors = { _errors: [] };
77
- const processError = (error) => {
78
- for (const issue of error.issues) {
79
- if (issue.code === "invalid_union") {
80
- issue.unionErrors.map(processError);
81
- }
82
- else if (issue.code === "invalid_return_type") {
83
- processError(issue.returnTypeError);
84
- }
85
- else if (issue.code === "invalid_arguments") {
86
- processError(issue.argumentsError);
87
- }
88
- else if (issue.path.length === 0) {
89
- fieldErrors._errors.push(issue.message);
90
- }
91
- else {
92
- let curr = fieldErrors;
93
- let i = 0;
94
- while (i < issue.path.length) {
95
- const el = issue.path[i];
96
- const terminal = i === issue.path.length - 1;
97
- if (!terminal) {
98
- if (typeof el === "string") {
99
- curr[el] = curr[el] || { _errors: [] };
100
- }
101
- else if (typeof el === "number") {
102
- const errorArray = [];
103
- errorArray._errors = [];
104
- curr[el] = curr[el] || errorArray;
105
- }
106
- }
107
- else {
108
- curr[el] = curr[el] || { _errors: [] };
109
- curr[el]._errors.push(issue.message);
110
- }
111
- curr = curr[el];
112
- i++;
113
- }
114
- }
115
- }
116
- };
117
- processError(this);
118
- return fieldErrors;
119
- };
120
75
  this.addIssue = (sub) => {
121
76
  this.issues = [...this.issues, sub];
122
77
  };
@@ -137,6 +92,55 @@ class ZodError extends Error {
137
92
  get errors() {
138
93
  return this.issues;
139
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
+ curr[el] = curr[el] || { _errors: [] };
123
+ // if (typeof el === "string") {
124
+ // curr[el] = curr[el] || { _errors: [] };
125
+ // } else if (typeof el === "number") {
126
+ // const errorArray: any = [];
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
+ }
140
144
  toString() {
141
145
  return this.message;
142
146
  }
@@ -2502,22 +2506,22 @@ class ZodEffects extends ZodType {
2502
2506
  });
2503
2507
  }
2504
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);
2505
2524
  if (effect.type === "refinement") {
2506
- const checkCtx = {
2507
- addIssue: (arg) => {
2508
- addIssueToContext(ctx, arg);
2509
- if (arg.fatal) {
2510
- status.abort();
2511
- }
2512
- else {
2513
- status.dirty();
2514
- }
2515
- },
2516
- get path() {
2517
- return ctx.path;
2518
- },
2519
- };
2520
- checkCtx.addIssue = checkCtx.addIssue.bind(checkCtx);
2521
2525
  const executeRefinement = (acc
2522
2526
  // effect: RefinementEffect<any>
2523
2527
  ) => {
@@ -2571,11 +2575,11 @@ class ZodEffects extends ZodType {
2571
2575
  // }
2572
2576
  if (!isValid(base))
2573
2577
  return base;
2574
- const result = effect.transform(base.value);
2578
+ const result = effect.transform(base.value, checkCtx);
2575
2579
  if (result instanceof Promise) {
2576
2580
  throw new Error(`Asynchronous transform encountered during synchronous parse operation. Use .parseAsync instead.`);
2577
2581
  }
2578
- return OK(result);
2582
+ return { status: status.value, value: result };
2579
2583
  }
2580
2584
  else {
2581
2585
  return this._def.schema
@@ -2587,7 +2591,7 @@ class ZodEffects extends ZodType {
2587
2591
  // if (base.status === "dirty") {
2588
2592
  // return { status: "dirty", value: base.value };
2589
2593
  // }
2590
- return Promise.resolve(effect.transform(base.value)).then(OK);
2594
+ return Promise.resolve(effect.transform(base.value, checkCtx)).then(OK);
2591
2595
  });
2592
2596
  }
2593
2597
  }