zod 3.17.2 → 3.17.5
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 +70 -20
- package/lib/ZodError.d.ts +5 -1
- package/lib/ZodError.js +15 -2
- package/lib/external.js +1 -5
- package/lib/helpers/errorUtil.d.ts +6 -2
- package/lib/helpers/parseUtil.d.ts +2 -2
- package/lib/helpers/parseUtil.js +2 -2
- package/lib/index.js +1 -5
- package/lib/index.mjs +60 -13
- package/lib/index.umd.js +60 -13
- package/lib/types.d.ts +29 -9
- package/lib/types.js +123 -89
- package/package.json +6 -5
package/README.md
CHANGED
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
<span> • </span>
|
|
23
23
|
<a href="https://discord.gg/RcG33DQJdf">Discord</a>
|
|
24
24
|
<span> • </span>
|
|
25
|
-
<a href="https://www.npmjs.com/package/zod">
|
|
25
|
+
<a href="https://www.npmjs.com/package/zod">npm</a>
|
|
26
26
|
<span> • </span>
|
|
27
27
|
<a href="https://github.com/colinhacks/zod/issues/new">Issues</a>
|
|
28
28
|
<span> • </span>
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
- [Sponsors](#sponsors)
|
|
48
48
|
- [Ecosystem](#ecosystem)
|
|
49
49
|
- [Installation](#installation)
|
|
50
|
-
- [Node](#
|
|
50
|
+
- [Node/npm](#Node/npm)
|
|
51
51
|
- [Deno](#deno)
|
|
52
52
|
- [Basic usage](#basic-usage)
|
|
53
53
|
- [Primitives](#primitives)
|
|
@@ -215,6 +215,26 @@ Sponsorship at any level is appreciated and encouraged. For individual developer
|
|
|
215
215
|
<b>Trip</b>
|
|
216
216
|
</td>
|
|
217
217
|
</tr>
|
|
218
|
+
<tr>
|
|
219
|
+
<td align="center">
|
|
220
|
+
<a href="https://seasoned.cc">
|
|
221
|
+
<img src="https://avatars.githubusercontent.com/u/33913103?s=200&v=4" width="150px;" alt="" />
|
|
222
|
+
</a>
|
|
223
|
+
<br />
|
|
224
|
+
<b>Seasoned Software</b>
|
|
225
|
+
<br />
|
|
226
|
+
<a href="https://seasoned.cc">seasoned.cc</a>
|
|
227
|
+
</td>
|
|
228
|
+
<td align="center">
|
|
229
|
+
<a href="https://seasoned.cc">
|
|
230
|
+
<img src="https://avatars.githubusercontent.com/u/67802063?s=200&v=4" width="150px;" alt="" />
|
|
231
|
+
</a>
|
|
232
|
+
<br />
|
|
233
|
+
<b>Interval</b>
|
|
234
|
+
<br />
|
|
235
|
+
<a href="https://interval.com">interval.com</a>
|
|
236
|
+
</td>
|
|
237
|
+
</tr>
|
|
218
238
|
</table>
|
|
219
239
|
|
|
220
240
|
#### Bronze
|
|
@@ -252,6 +272,18 @@ Sponsorship at any level is appreciated and encouraged. For individual developer
|
|
|
252
272
|
<a href="https://twitter.com/alexdotjs">@alexdotjs</a>
|
|
253
273
|
</td>
|
|
254
274
|
</tr>
|
|
275
|
+
<tr>
|
|
276
|
+
<td align="center">
|
|
277
|
+
<a href="https://adaptable.io/">
|
|
278
|
+
<img src="https://avatars.githubusercontent.com/u/60378268?s=200&v=4" width="100px;" alt=""/>
|
|
279
|
+
</a>
|
|
280
|
+
<br />
|
|
281
|
+
<b>Adaptable</b>
|
|
282
|
+
<br/>
|
|
283
|
+
<a href="https://adaptable.io/">adaptable.io</a>
|
|
284
|
+
<br />
|
|
285
|
+
</td>
|
|
286
|
+
</tr>
|
|
255
287
|
</table>
|
|
256
288
|
|
|
257
289
|
### Ecosystem
|
|
@@ -281,6 +313,7 @@ There are a growing number of tools that are built atop or support Zod natively!
|
|
|
281
313
|
- [`prisma-zod-generator`](https://github.com/omar-dulaimi/prisma-zod-generator): Emit Zod schemas from your Prisma schema.
|
|
282
314
|
- [`prisma-trpc-generator`](https://github.com/omar-dulaimi/prisma-trpc-generator): Emit fully implemented tRPC routers and their validation schemas using Zod.
|
|
283
315
|
- [`nestjs-graphql-zod`](https://github.com/incetarik/nestjs-graphql-zod): Generates NestJS GraphQL model classes from Zod schemas dynamically and provides GraphQL method decorators working with Zod schemas.
|
|
316
|
+
- [`remix-domains`](https://github.com/SeasonedSoftware/remix-domains/): Improves end-to-end type safety in [Remix](https://remix.run/) by leveraging Zod to parse the framework's inputs such as FormData, URLSearchParams, etc.
|
|
284
317
|
|
|
285
318
|
#### Form integrations
|
|
286
319
|
|
|
@@ -306,7 +339,7 @@ There are a growing number of tools that are built atop or support Zod natively!
|
|
|
306
339
|
}
|
|
307
340
|
```
|
|
308
341
|
|
|
309
|
-
### Node/
|
|
342
|
+
### Node/npm
|
|
310
343
|
|
|
311
344
|
To install Zod v3:
|
|
312
345
|
|
|
@@ -318,7 +351,7 @@ pnpm add zod # pnpm
|
|
|
318
351
|
|
|
319
352
|
### Deno
|
|
320
353
|
|
|
321
|
-
Unlike Node, Deno relies on direct URL imports instead of a package manager like
|
|
354
|
+
Unlike Node, Deno relies on direct URL imports instead of a package manager like npm. Zod is available on [deno.land/x](deno.land/x). The latest version can be imported like so:
|
|
322
355
|
|
|
323
356
|
```ts
|
|
324
357
|
import { z } from "https://deno.land/x/zod/mod.ts";
|
|
@@ -330,7 +363,7 @@ You can also specify a particular version:
|
|
|
330
363
|
import { z } from from "https://deno.land/x/zod@v3.16.1/mod.ts"
|
|
331
364
|
```
|
|
332
365
|
|
|
333
|
-
> The rest of this README assumes you are using
|
|
366
|
+
> The rest of this README assumes you are using npm and importing directly from the `"zod"` package.
|
|
334
367
|
|
|
335
368
|
## Basic usage
|
|
336
369
|
|
|
@@ -420,6 +453,8 @@ z.string().url();
|
|
|
420
453
|
z.string().uuid();
|
|
421
454
|
z.string().cuid();
|
|
422
455
|
z.string().regex(regex);
|
|
456
|
+
z.string().startsWith(string);
|
|
457
|
+
z.string().endsWith(string);
|
|
423
458
|
|
|
424
459
|
// trim whitespace
|
|
425
460
|
z.string().trim();
|
|
@@ -433,7 +468,7 @@ z.string().nonempty({ message: "Can't be empty" });
|
|
|
433
468
|
|
|
434
469
|
> Check out [validator.js](https://github.com/validatorjs/validator.js) for a bunch of other useful string validation functions.
|
|
435
470
|
|
|
436
|
-
You can customize some common
|
|
471
|
+
You can customize some common error messages when creating a string schema.
|
|
437
472
|
|
|
438
473
|
```ts
|
|
439
474
|
const name = z.string({
|
|
@@ -451,6 +486,8 @@ z.string().length(5, { message: "Must be exactly 5 characters long" });
|
|
|
451
486
|
z.string().email({ message: "Invalid email address" });
|
|
452
487
|
z.string().url({ message: "Invalid url" });
|
|
453
488
|
z.string().uuid({ message: "Invalid UUID" });
|
|
489
|
+
z.string().startsWith("https://", { message: "Must provide secure URL" });
|
|
490
|
+
z.string().endsWith(".com", { message: "Only .com domains allowed" });
|
|
454
491
|
```
|
|
455
492
|
|
|
456
493
|
## Numbers
|
|
@@ -547,7 +584,7 @@ const VALUES = ["Salmon", "Tuna", "Trout"] as const;
|
|
|
547
584
|
const FishEnum = z.enum(VALUES);
|
|
548
585
|
```
|
|
549
586
|
|
|
550
|
-
This is not allowed, since Zod isn't able to infer the exact values of each
|
|
587
|
+
This is not allowed, since Zod isn't able to infer the exact values of each element.
|
|
551
588
|
|
|
552
589
|
```ts
|
|
553
590
|
const fish = ["Salmon", "Tuna", "Trout"];
|
|
@@ -728,7 +765,7 @@ Dog.shape.age; // => number schema
|
|
|
728
765
|
|
|
729
766
|
### `.extend`
|
|
730
767
|
|
|
731
|
-
You can add additional fields an object schema with the `.extend` method.
|
|
768
|
+
You can add additional fields to an object schema with the `.extend` method.
|
|
732
769
|
|
|
733
770
|
```ts
|
|
734
771
|
const DogWithBreed = Dog.extend({
|
|
@@ -848,7 +885,7 @@ const deepPartialUser = user.deepPartial();
|
|
|
848
885
|
|
|
849
886
|
### `.passthrough`
|
|
850
887
|
|
|
851
|
-
By default Zod
|
|
888
|
+
By default Zod object schemas strip out unrecognized keys during parsing.
|
|
852
889
|
|
|
853
890
|
```ts
|
|
854
891
|
const person = z.object({
|
|
@@ -875,7 +912,7 @@ person.passthrough().parse({
|
|
|
875
912
|
|
|
876
913
|
### `.strict`
|
|
877
914
|
|
|
878
|
-
By default Zod
|
|
915
|
+
By default Zod object schemas strip out unrecognized keys during parsing. You can _disallow_ unknown keys with `.strict()` . If there are any unknown keys in the input, Zod will throw an error.
|
|
879
916
|
|
|
880
917
|
```ts
|
|
881
918
|
const person = z
|
|
@@ -1035,7 +1072,7 @@ const item = z
|
|
|
1035
1072
|
|
|
1036
1073
|
Record schemas are used to validate types such as `{ [k: string]: number }`.
|
|
1037
1074
|
|
|
1038
|
-
If you want to validate the _values_ of an object against some schema but don't care about the keys, use `
|
|
1075
|
+
If you want to validate the _values_ of an object against some schema but don't care about the keys, use `z.record(valueType)`:
|
|
1039
1076
|
|
|
1040
1077
|
```ts
|
|
1041
1078
|
const NumberCache = z.record(z.number());
|
|
@@ -1058,9 +1095,22 @@ userStore["77d2586b-9e8e-4ecf-8b21-ea7e0530eadd"] = {
|
|
|
1058
1095
|
}; // TypeError
|
|
1059
1096
|
```
|
|
1060
1097
|
|
|
1098
|
+
### Record key type
|
|
1099
|
+
|
|
1100
|
+
If you want to validate both the keys and the values, use
|
|
1101
|
+
`z.record(keyType, valueType)`:
|
|
1102
|
+
|
|
1103
|
+
```ts
|
|
1104
|
+
const NoEmptyKeysSchema = z.record(z.string().min(1), z.number());
|
|
1105
|
+
NoEmptyKeysSchema.parse({ count: 1 }); // => { 'count': 1 }
|
|
1106
|
+
NoEmptyKeysSchema.parse({ "": 1 }); // fails
|
|
1107
|
+
```
|
|
1108
|
+
|
|
1109
|
+
_(Notice how when passing two arguments, `valueType` is the second argument)_
|
|
1110
|
+
|
|
1061
1111
|
**A note on numerical keys**
|
|
1062
1112
|
|
|
1063
|
-
|
|
1113
|
+
While `z.record(keyType, valueType)` is able to accept numerical key types and TypeScript's built-in Record type is `Record<KeyType, ValueType>`, it's hard to represent the TypeScript type `Record<number, any>` in Zod.
|
|
1064
1114
|
|
|
1065
1115
|
As it turns out, TypeScript's behavior surrounding `[k: number]` is a little unintuitive:
|
|
1066
1116
|
|
|
@@ -1310,7 +1360,7 @@ type myFunction = z.infer<typeof myFunction>;
|
|
|
1310
1360
|
// => (arg0: string)=>number
|
|
1311
1361
|
``` -->
|
|
1312
1362
|
|
|
1313
|
-
Function schemas have an `.implement()` method which accepts a function and returns a new function that automatically validates
|
|
1363
|
+
Function schemas have an `.implement()` method which accepts a function and returns a new function that automatically validates its inputs and outputs.
|
|
1314
1364
|
|
|
1315
1365
|
```ts
|
|
1316
1366
|
const trimmedLength = z
|
|
@@ -1528,7 +1578,7 @@ const userId = z.string().refine(async (id) => {
|
|
|
1528
1578
|
});
|
|
1529
1579
|
```
|
|
1530
1580
|
|
|
1531
|
-
> ⚠️If you use async refinements, you must use the `.parseAsync` method to parse data! Otherwise Zod will throw an error.
|
|
1581
|
+
> ⚠️ If you use async refinements, you must use the `.parseAsync` method to parse data! Otherwise Zod will throw an error.
|
|
1532
1582
|
|
|
1533
1583
|
#### Relationship to transforms
|
|
1534
1584
|
|
|
@@ -1584,7 +1634,7 @@ const Strings = z.array(z.string()).superRefine((val, ctx) => {
|
|
|
1584
1634
|
if (val.length !== new Set(val).size) {
|
|
1585
1635
|
ctx.addIssue({
|
|
1586
1636
|
code: z.ZodIssueCode.custom,
|
|
1587
|
-
message: `No
|
|
1637
|
+
message: `No duplicates allowed.`,
|
|
1588
1638
|
});
|
|
1589
1639
|
}
|
|
1590
1640
|
});
|
|
@@ -1977,13 +2027,13 @@ Branded -->
|
|
|
1977
2027
|
* Missing support for parsing cyclical data (maybe)
|
|
1978
2028
|
* Missing error customization -->
|
|
1979
2029
|
|
|
1980
|
-
|
|
2030
|
+
### Joi
|
|
1981
2031
|
|
|
1982
2032
|
[https://github.com/hapijs/joi](https://github.com/hapijs/joi)
|
|
1983
2033
|
|
|
1984
2034
|
Doesn't support static type inference 😕
|
|
1985
2035
|
|
|
1986
|
-
|
|
2036
|
+
### Yup
|
|
1987
2037
|
|
|
1988
2038
|
[https://github.com/jquense/yup](https://github.com/jquense/yup)
|
|
1989
2039
|
|
|
@@ -1999,7 +2049,7 @@ Yup is a full-featured library that was implemented first in vanilla JS, and lat
|
|
|
1999
2049
|
|
|
2000
2050
|
<!-- ¹Yup has a strange interpretation of the word `required`. Instead of meaning "not undefined", Yup uses it to mean "not empty". So `yup.string().required()` will not accept an empty string, and `yup.array(yup.string()).required()` will not accept an empty array. Instead, Yup us Zod arrays there is a dedicated `.nonempty()` method to indicate this, or you can implement it with a custom refinement. -->
|
|
2001
2051
|
|
|
2002
|
-
|
|
2052
|
+
### io-ts
|
|
2003
2053
|
|
|
2004
2054
|
[https://github.com/gcanti/io-ts](https://github.com/gcanti/io-ts)
|
|
2005
2055
|
|
|
@@ -2050,7 +2100,7 @@ This more declarative API makes schema definitions vastly more concise.
|
|
|
2050
2100
|
- Missing promise schemas
|
|
2051
2101
|
- Missing function schemas
|
|
2052
2102
|
|
|
2053
|
-
|
|
2103
|
+
### Runtypes
|
|
2054
2104
|
|
|
2055
2105
|
[https://github.com/pelotom/runtypes](https://github.com/pelotom/runtypes)
|
|
2056
2106
|
|
|
@@ -2063,7 +2113,7 @@ Good type inference support, but limited options for object type masking (no `.p
|
|
|
2063
2113
|
- Missing promise schemas
|
|
2064
2114
|
- Missing error customization
|
|
2065
2115
|
|
|
2066
|
-
|
|
2116
|
+
### Ow
|
|
2067
2117
|
|
|
2068
2118
|
[https://github.com/sindresorhus/ow](https://github.com/sindresorhus/ow)
|
|
2069
2119
|
|
package/lib/ZodError.d.ts
CHANGED
|
@@ -68,7 +68,11 @@ export interface ZodInvalidReturnTypeIssue extends ZodIssueBase {
|
|
|
68
68
|
export interface ZodInvalidDateIssue extends ZodIssueBase {
|
|
69
69
|
code: typeof ZodIssueCode.invalid_date;
|
|
70
70
|
}
|
|
71
|
-
export declare type StringValidation = "email" | "url" | "uuid" | "regex" | "cuid"
|
|
71
|
+
export declare type StringValidation = "email" | "url" | "uuid" | "regex" | "cuid" | {
|
|
72
|
+
startsWith: string;
|
|
73
|
+
} | {
|
|
74
|
+
endsWith: string;
|
|
75
|
+
};
|
|
72
76
|
export interface ZodInvalidStringIssue extends ZodIssueBase {
|
|
73
77
|
code: typeof ZodIssueCode.invalid_string;
|
|
74
78
|
validation: StringValidation;
|
package/lib/ZodError.js
CHANGED
|
@@ -165,10 +165,23 @@ const defaultErrorMap = (issue, _ctx) => {
|
|
|
165
165
|
message = `Invalid date`;
|
|
166
166
|
break;
|
|
167
167
|
case exports.ZodIssueCode.invalid_string:
|
|
168
|
-
if (issue.validation
|
|
168
|
+
if (typeof issue.validation === "object") {
|
|
169
|
+
if ("startsWith" in issue.validation) {
|
|
170
|
+
message = `Invalid input: must start with "${issue.validation.startsWith}"`;
|
|
171
|
+
}
|
|
172
|
+
else if ("endsWith" in issue.validation) {
|
|
173
|
+
message = `Invalid input: must start with "${issue.validation.endsWith}"`;
|
|
174
|
+
}
|
|
175
|
+
else {
|
|
176
|
+
util_1.util.assertNever(issue.validation);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
else if (issue.validation !== "regex") {
|
|
169
180
|
message = `Invalid ${issue.validation}`;
|
|
170
|
-
|
|
181
|
+
}
|
|
182
|
+
else {
|
|
171
183
|
message = "Invalid";
|
|
184
|
+
}
|
|
172
185
|
break;
|
|
173
186
|
case exports.ZodIssueCode.too_small:
|
|
174
187
|
if (issue.type === "array")
|
package/lib/external.js
CHANGED
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
3
|
if (k2 === undefined) k2 = k;
|
|
4
|
-
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
4
|
+
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
|
9
5
|
}) : (function(o, m, k, k2) {
|
|
10
6
|
if (k2 === undefined) k2 = k;
|
|
11
7
|
o[k2] = m[k];
|
|
@@ -2,8 +2,12 @@ export declare namespace errorUtil {
|
|
|
2
2
|
type ErrMessage = string | {
|
|
3
3
|
message?: string;
|
|
4
4
|
};
|
|
5
|
-
const errToObj: (message?:
|
|
5
|
+
const errToObj: (message?: string | {
|
|
6
|
+
message?: string | undefined;
|
|
7
|
+
} | undefined) => {
|
|
6
8
|
message?: string | undefined;
|
|
7
9
|
};
|
|
8
|
-
const toString: (message?:
|
|
10
|
+
const toString: (message?: string | {
|
|
11
|
+
message?: string | undefined;
|
|
12
|
+
} | undefined) => string | undefined;
|
|
9
13
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import type { IssueData, ZodErrorMap, ZodIssue } from "../ZodError";
|
|
2
|
+
import type { ZodParsedType } from "./util";
|
|
3
3
|
export declare const makeIssue: (params: {
|
|
4
4
|
data: any;
|
|
5
5
|
path: (string | number)[];
|
package/lib/helpers/parseUtil.js
CHANGED
|
@@ -26,7 +26,7 @@ const makeIssue = (params) => {
|
|
|
26
26
|
exports.makeIssue = makeIssue;
|
|
27
27
|
exports.EMPTY_PATH = [];
|
|
28
28
|
function addIssueToContext(ctx, issueData) {
|
|
29
|
-
const issue =
|
|
29
|
+
const issue = exports.makeIssue({
|
|
30
30
|
issueData: issueData,
|
|
31
31
|
data: ctx.data,
|
|
32
32
|
path: ctx.path,
|
|
@@ -34,7 +34,7 @@ function addIssueToContext(ctx, issueData) {
|
|
|
34
34
|
ctx.common.contextualErrorMap,
|
|
35
35
|
ctx.schemaErrorMap,
|
|
36
36
|
ZodError_1.overrideErrorMap,
|
|
37
|
-
ZodError_1.defaultErrorMap,
|
|
37
|
+
ZodError_1.defaultErrorMap,
|
|
38
38
|
].filter((x) => !!x),
|
|
39
39
|
});
|
|
40
40
|
ctx.common.issues.push(issue);
|
package/lib/index.js
CHANGED
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
3
|
if (k2 === undefined) k2 = k;
|
|
4
|
-
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
4
|
+
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
|
9
5
|
}) : (function(o, m, k, k2) {
|
|
10
6
|
if (k2 === undefined) k2 = k;
|
|
11
7
|
o[k2] = m[k];
|
package/lib/index.mjs
CHANGED
|
@@ -278,10 +278,23 @@ const defaultErrorMap = (issue, _ctx) => {
|
|
|
278
278
|
message = `Invalid date`;
|
|
279
279
|
break;
|
|
280
280
|
case ZodIssueCode.invalid_string:
|
|
281
|
-
if (issue.validation
|
|
281
|
+
if (typeof issue.validation === "object") {
|
|
282
|
+
if ("startsWith" in issue.validation) {
|
|
283
|
+
message = `Invalid input: must start with "${issue.validation.startsWith}"`;
|
|
284
|
+
}
|
|
285
|
+
else if ("endsWith" in issue.validation) {
|
|
286
|
+
message = `Invalid input: must start with "${issue.validation.endsWith}"`;
|
|
287
|
+
}
|
|
288
|
+
else {
|
|
289
|
+
util.assertNever(issue.validation);
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
else if (issue.validation !== "regex") {
|
|
282
293
|
message = `Invalid ${issue.validation}`;
|
|
283
|
-
|
|
294
|
+
}
|
|
295
|
+
else {
|
|
284
296
|
message = "Invalid";
|
|
297
|
+
}
|
|
285
298
|
break;
|
|
286
299
|
case ZodIssueCode.too_small:
|
|
287
300
|
if (issue.type === "array")
|
|
@@ -354,7 +367,7 @@ function addIssueToContext(ctx, issueData) {
|
|
|
354
367
|
ctx.common.contextualErrorMap,
|
|
355
368
|
ctx.schemaErrorMap,
|
|
356
369
|
overrideErrorMap,
|
|
357
|
-
defaultErrorMap,
|
|
370
|
+
defaultErrorMap,
|
|
358
371
|
].filter((x) => !!x),
|
|
359
372
|
});
|
|
360
373
|
ctx.common.issues.push(issue);
|
|
@@ -823,6 +836,28 @@ class ZodString extends ZodType {
|
|
|
823
836
|
else if (check.kind === "trim") {
|
|
824
837
|
input.data = input.data.trim();
|
|
825
838
|
}
|
|
839
|
+
else if (check.kind === "startsWith") {
|
|
840
|
+
if (!input.data.startsWith(check.value)) {
|
|
841
|
+
ctx = this._getOrReturnCtx(input, ctx);
|
|
842
|
+
addIssueToContext(ctx, {
|
|
843
|
+
code: ZodIssueCode.invalid_string,
|
|
844
|
+
validation: { startsWith: check.value },
|
|
845
|
+
message: check.message,
|
|
846
|
+
});
|
|
847
|
+
status.dirty();
|
|
848
|
+
}
|
|
849
|
+
}
|
|
850
|
+
else if (check.kind === "endsWith") {
|
|
851
|
+
if (!input.data.endsWith(check.value)) {
|
|
852
|
+
ctx = this._getOrReturnCtx(input, ctx);
|
|
853
|
+
addIssueToContext(ctx, {
|
|
854
|
+
code: ZodIssueCode.invalid_string,
|
|
855
|
+
validation: { endsWith: check.value },
|
|
856
|
+
message: check.message,
|
|
857
|
+
});
|
|
858
|
+
status.dirty();
|
|
859
|
+
}
|
|
860
|
+
}
|
|
826
861
|
else {
|
|
827
862
|
util.assertNever(check);
|
|
828
863
|
}
|
|
@@ -854,6 +889,20 @@ class ZodString extends ZodType {
|
|
|
854
889
|
...errorUtil.errToObj(message),
|
|
855
890
|
});
|
|
856
891
|
}
|
|
892
|
+
startsWith(value, message) {
|
|
893
|
+
return this._addCheck({
|
|
894
|
+
kind: "startsWith",
|
|
895
|
+
value: value,
|
|
896
|
+
...errorUtil.errToObj(message),
|
|
897
|
+
});
|
|
898
|
+
}
|
|
899
|
+
endsWith(value, message) {
|
|
900
|
+
return this._addCheck({
|
|
901
|
+
kind: "endsWith",
|
|
902
|
+
value: value,
|
|
903
|
+
...errorUtil.errToObj(message),
|
|
904
|
+
});
|
|
905
|
+
}
|
|
857
906
|
min(minLength, message) {
|
|
858
907
|
return this._addCheck({
|
|
859
908
|
kind: "min",
|
|
@@ -884,25 +933,23 @@ class ZodString extends ZodType {
|
|
|
884
933
|
return !!this._def.checks.find((ch) => ch.kind === "cuid");
|
|
885
934
|
}
|
|
886
935
|
get minLength() {
|
|
887
|
-
let min =
|
|
888
|
-
this._def.checks
|
|
936
|
+
let min = null;
|
|
937
|
+
for (const ch of this._def.checks) {
|
|
889
938
|
if (ch.kind === "min") {
|
|
890
|
-
if (min === null || ch.value > min)
|
|
939
|
+
if (min === null || ch.value > min)
|
|
891
940
|
min = ch.value;
|
|
892
|
-
}
|
|
893
941
|
}
|
|
894
|
-
}
|
|
942
|
+
}
|
|
895
943
|
return min;
|
|
896
944
|
}
|
|
897
945
|
get maxLength() {
|
|
898
946
|
let max = null;
|
|
899
|
-
this._def.checks
|
|
947
|
+
for (const ch of this._def.checks) {
|
|
900
948
|
if (ch.kind === "max") {
|
|
901
|
-
if (max === null || ch.value < max)
|
|
949
|
+
if (max === null || ch.value < max)
|
|
902
950
|
max = ch.value;
|
|
903
|
-
}
|
|
904
951
|
}
|
|
905
|
-
}
|
|
952
|
+
}
|
|
906
953
|
return max;
|
|
907
954
|
}
|
|
908
955
|
}
|
|
@@ -1388,7 +1435,7 @@ var objectUtil;
|
|
|
1388
1435
|
objectUtil.mergeShapes = (first, second) => {
|
|
1389
1436
|
return {
|
|
1390
1437
|
...first,
|
|
1391
|
-
...second,
|
|
1438
|
+
...second,
|
|
1392
1439
|
};
|
|
1393
1440
|
};
|
|
1394
1441
|
})(objectUtil || (objectUtil = {}));
|
package/lib/index.umd.js
CHANGED
|
@@ -284,10 +284,23 @@
|
|
|
284
284
|
message = `Invalid date`;
|
|
285
285
|
break;
|
|
286
286
|
case ZodIssueCode.invalid_string:
|
|
287
|
-
if (issue.validation
|
|
287
|
+
if (typeof issue.validation === "object") {
|
|
288
|
+
if ("startsWith" in issue.validation) {
|
|
289
|
+
message = `Invalid input: must start with "${issue.validation.startsWith}"`;
|
|
290
|
+
}
|
|
291
|
+
else if ("endsWith" in issue.validation) {
|
|
292
|
+
message = `Invalid input: must start with "${issue.validation.endsWith}"`;
|
|
293
|
+
}
|
|
294
|
+
else {
|
|
295
|
+
util.assertNever(issue.validation);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
else if (issue.validation !== "regex") {
|
|
288
299
|
message = `Invalid ${issue.validation}`;
|
|
289
|
-
|
|
300
|
+
}
|
|
301
|
+
else {
|
|
290
302
|
message = "Invalid";
|
|
303
|
+
}
|
|
291
304
|
break;
|
|
292
305
|
case ZodIssueCode.too_small:
|
|
293
306
|
if (issue.type === "array")
|
|
@@ -360,7 +373,7 @@
|
|
|
360
373
|
ctx.common.contextualErrorMap,
|
|
361
374
|
ctx.schemaErrorMap,
|
|
362
375
|
exports.overrideErrorMap,
|
|
363
|
-
defaultErrorMap,
|
|
376
|
+
defaultErrorMap,
|
|
364
377
|
].filter((x) => !!x),
|
|
365
378
|
});
|
|
366
379
|
ctx.common.issues.push(issue);
|
|
@@ -829,6 +842,28 @@
|
|
|
829
842
|
else if (check.kind === "trim") {
|
|
830
843
|
input.data = input.data.trim();
|
|
831
844
|
}
|
|
845
|
+
else if (check.kind === "startsWith") {
|
|
846
|
+
if (!input.data.startsWith(check.value)) {
|
|
847
|
+
ctx = this._getOrReturnCtx(input, ctx);
|
|
848
|
+
addIssueToContext(ctx, {
|
|
849
|
+
code: ZodIssueCode.invalid_string,
|
|
850
|
+
validation: { startsWith: check.value },
|
|
851
|
+
message: check.message,
|
|
852
|
+
});
|
|
853
|
+
status.dirty();
|
|
854
|
+
}
|
|
855
|
+
}
|
|
856
|
+
else if (check.kind === "endsWith") {
|
|
857
|
+
if (!input.data.endsWith(check.value)) {
|
|
858
|
+
ctx = this._getOrReturnCtx(input, ctx);
|
|
859
|
+
addIssueToContext(ctx, {
|
|
860
|
+
code: ZodIssueCode.invalid_string,
|
|
861
|
+
validation: { endsWith: check.value },
|
|
862
|
+
message: check.message,
|
|
863
|
+
});
|
|
864
|
+
status.dirty();
|
|
865
|
+
}
|
|
866
|
+
}
|
|
832
867
|
else {
|
|
833
868
|
util.assertNever(check);
|
|
834
869
|
}
|
|
@@ -860,6 +895,20 @@
|
|
|
860
895
|
...errorUtil.errToObj(message),
|
|
861
896
|
});
|
|
862
897
|
}
|
|
898
|
+
startsWith(value, message) {
|
|
899
|
+
return this._addCheck({
|
|
900
|
+
kind: "startsWith",
|
|
901
|
+
value: value,
|
|
902
|
+
...errorUtil.errToObj(message),
|
|
903
|
+
});
|
|
904
|
+
}
|
|
905
|
+
endsWith(value, message) {
|
|
906
|
+
return this._addCheck({
|
|
907
|
+
kind: "endsWith",
|
|
908
|
+
value: value,
|
|
909
|
+
...errorUtil.errToObj(message),
|
|
910
|
+
});
|
|
911
|
+
}
|
|
863
912
|
min(minLength, message) {
|
|
864
913
|
return this._addCheck({
|
|
865
914
|
kind: "min",
|
|
@@ -890,25 +939,23 @@
|
|
|
890
939
|
return !!this._def.checks.find((ch) => ch.kind === "cuid");
|
|
891
940
|
}
|
|
892
941
|
get minLength() {
|
|
893
|
-
let min =
|
|
894
|
-
this._def.checks
|
|
942
|
+
let min = null;
|
|
943
|
+
for (const ch of this._def.checks) {
|
|
895
944
|
if (ch.kind === "min") {
|
|
896
|
-
if (min === null || ch.value > min)
|
|
945
|
+
if (min === null || ch.value > min)
|
|
897
946
|
min = ch.value;
|
|
898
|
-
}
|
|
899
947
|
}
|
|
900
|
-
}
|
|
948
|
+
}
|
|
901
949
|
return min;
|
|
902
950
|
}
|
|
903
951
|
get maxLength() {
|
|
904
952
|
let max = null;
|
|
905
|
-
this._def.checks
|
|
953
|
+
for (const ch of this._def.checks) {
|
|
906
954
|
if (ch.kind === "max") {
|
|
907
|
-
if (max === null || ch.value < max)
|
|
955
|
+
if (max === null || ch.value < max)
|
|
908
956
|
max = ch.value;
|
|
909
|
-
}
|
|
910
957
|
}
|
|
911
|
-
}
|
|
958
|
+
}
|
|
912
959
|
return max;
|
|
913
960
|
}
|
|
914
961
|
}
|
|
@@ -1394,7 +1441,7 @@
|
|
|
1394
1441
|
objectUtil.mergeShapes = (first, second) => {
|
|
1395
1442
|
return {
|
|
1396
1443
|
...first,
|
|
1397
|
-
...second,
|
|
1444
|
+
...second,
|
|
1398
1445
|
};
|
|
1399
1446
|
};
|
|
1400
1447
|
})(exports.objectUtil || (exports.objectUtil = {}));
|