zod 4.1.0-canary.20250723T221600 → 4.1.0-canary.20250724T211341

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.
Files changed (60) hide show
  1. package/package.json +1 -1
  2. package/src/v3/types.ts +3 -1
  3. package/src/v4/classic/errors.ts +9 -2
  4. package/src/v4/classic/schemas.ts +10 -7
  5. package/src/v4/classic/tests/error-utils.test.ts +43 -0
  6. package/src/v4/classic/tests/file.test.ts +0 -1
  7. package/src/v4/classic/tests/literal.test.ts +25 -0
  8. package/src/v4/classic/tests/partial.test.ts +193 -0
  9. package/src/v4/classic/tests/pickomit.test.ts +5 -5
  10. package/src/v4/classic/tests/preprocess.test.ts +4 -15
  11. package/src/v4/classic/tests/record.test.ts +15 -1
  12. package/src/v4/classic/tests/recursive-types.test.ts +67 -0
  13. package/src/v4/classic/tests/string.test.ts +77 -0
  14. package/src/v4/classic/tests/template-literal.test.ts +3 -0
  15. package/src/v4/classic/tests/to-json-schema.test.ts +1 -0
  16. package/src/v4/classic/tests/transform.test.ts +104 -0
  17. package/src/v4/classic/tests/union.test.ts +90 -3
  18. package/src/v4/core/checks.ts +2 -2
  19. package/src/v4/core/errors.ts +8 -15
  20. package/src/v4/core/registries.ts +3 -2
  21. package/src/v4/core/schemas.ts +93 -95
  22. package/src/v4/core/tests/extend.test.ts +18 -0
  23. package/src/v4/core/to-json-schema.ts +1 -0
  24. package/src/v4/core/util.ts +135 -98
  25. package/src/v4/core/versions.ts +1 -1
  26. package/src/v4/mini/schemas.ts +3 -1
  27. package/v3/types.cjs +2 -0
  28. package/v3/types.d.cts +4 -1
  29. package/v3/types.d.ts +4 -1
  30. package/v3/types.js +2 -0
  31. package/v4/classic/errors.cjs +9 -2
  32. package/v4/classic/errors.js +9 -2
  33. package/v4/classic/schemas.cjs +5 -3
  34. package/v4/classic/schemas.d.cts +2 -1
  35. package/v4/classic/schemas.d.ts +2 -1
  36. package/v4/classic/schemas.js +5 -3
  37. package/v4/core/checks.d.cts +2 -2
  38. package/v4/core/checks.d.ts +2 -2
  39. package/v4/core/errors.cjs +4 -9
  40. package/v4/core/errors.d.cts +4 -6
  41. package/v4/core/errors.d.ts +4 -6
  42. package/v4/core/errors.js +4 -9
  43. package/v4/core/registries.cjs +2 -1
  44. package/v4/core/registries.d.cts +1 -1
  45. package/v4/core/registries.d.ts +1 -1
  46. package/v4/core/registries.js +2 -1
  47. package/v4/core/schemas.cjs +51 -88
  48. package/v4/core/schemas.d.cts +8 -3
  49. package/v4/core/schemas.d.ts +8 -3
  50. package/v4/core/schemas.js +51 -88
  51. package/v4/core/to-json-schema.cjs +1 -0
  52. package/v4/core/to-json-schema.js +1 -0
  53. package/v4/core/util.cjs +123 -97
  54. package/v4/core/util.d.cts +2 -0
  55. package/v4/core/util.d.ts +2 -0
  56. package/v4/core/util.js +121 -97
  57. package/v4/core/versions.cjs +1 -1
  58. package/v4/core/versions.js +1 -1
  59. package/v4/mini/schemas.cjs +3 -1
  60. package/v4/mini/schemas.js +3 -1
@@ -1952,6 +1952,7 @@ test("input type", () => {
1952
1952
  "required": [
1953
1953
  "a",
1954
1954
  "d",
1955
+ "f",
1955
1956
  "g",
1956
1957
  ],
1957
1958
  "type": "object",
@@ -248,3 +248,107 @@ test("async short circuit on dirty", async () => {
248
248
  ]]
249
249
  `);
250
250
  });
251
+
252
+ test("do not continue by default", () => {
253
+ const A = z
254
+ .string()
255
+ .transform((val, ctx) => {
256
+ ctx.addIssue({
257
+ code: "custom",
258
+ message: `custom error`,
259
+ });
260
+ ctx.addIssue({
261
+ code: "custom",
262
+ message: `custom error`,
263
+ });
264
+ return val;
265
+ })
266
+ .pipe(z.number() as any);
267
+ expect(A.safeParse("asdf")).toMatchInlineSnapshot(`
268
+ {
269
+ "error": [ZodError: [
270
+ {
271
+ "code": "custom",
272
+ "message": "custom error",
273
+ "path": []
274
+ },
275
+ {
276
+ "code": "custom",
277
+ "message": "custom error",
278
+ "path": []
279
+ }
280
+ ]],
281
+ "success": false,
282
+ }
283
+ `);
284
+
285
+ const B = z
286
+ .string()
287
+ .transform((val, ctx) => {
288
+ ctx.issues.push({
289
+ code: "custom",
290
+ message: `custom error`,
291
+ input: val,
292
+ });
293
+ ctx.issues.push({
294
+ code: "custom",
295
+ message: `custom error`,
296
+ input: val,
297
+ });
298
+ return val;
299
+ })
300
+ .pipe(z.number() as any);
301
+ expect(B.safeParse("asdf")).toMatchInlineSnapshot(`
302
+ {
303
+ "error": [ZodError: [
304
+ {
305
+ "code": "custom",
306
+ "message": "custom error",
307
+ "path": []
308
+ },
309
+ {
310
+ "code": "custom",
311
+ "message": "custom error",
312
+ "path": []
313
+ }
314
+ ]],
315
+ "success": false,
316
+ }
317
+ `);
318
+
319
+ const C = z
320
+ .string()
321
+ .transform((val, ctx) => {
322
+ ctx.issues.push({
323
+ code: "custom",
324
+ message: `custom error`,
325
+ input: val,
326
+ continue: true,
327
+ });
328
+ ctx.issues.push({
329
+ code: "custom",
330
+ message: `custom error`,
331
+ input: val,
332
+ continue: true,
333
+ });
334
+ return val;
335
+ })
336
+ .pipe(z.number() as any);
337
+ expect(C.safeParse("asdf")).toMatchInlineSnapshot(`
338
+ {
339
+ "error": [ZodError: [
340
+ {
341
+ "code": "custom",
342
+ "message": "custom error",
343
+ "path": []
344
+ },
345
+ {
346
+ "code": "custom",
347
+ "message": "custom error",
348
+ "path": []
349
+ }
350
+ ]],
351
+ "success": false,
352
+ }
353
+ `);
354
+ });
@@ -27,7 +27,7 @@ test("return valid over invalid", () => {
27
27
  });
28
28
 
29
29
  test("return errors from both union arms", () => {
30
- const result = z.union([z.number(), z.string().refine(() => false)]).safeParse("a");
30
+ const result = z.union([z.number(), z.boolean()]).safeParse("a");
31
31
  expect(result.success).toEqual(false);
32
32
  if (!result.success) {
33
33
  expect(result.error.issues).toMatchInlineSnapshot(`
@@ -45,8 +45,9 @@ test("return errors from both union arms", () => {
45
45
  ],
46
46
  [
47
47
  {
48
- "code": "custom",
49
- "message": "Invalid input",
48
+ "code": "invalid_type",
49
+ "expected": "boolean",
50
+ "message": "Invalid input: expected boolean, received string",
50
51
  "path": [],
51
52
  },
52
53
  ],
@@ -92,3 +93,89 @@ test("union values", () => {
92
93
  }
93
94
  `);
94
95
  });
96
+
97
+ test("non-aborted errors", () => {
98
+ const zItemTest = z.union([
99
+ z.object({
100
+ date: z.number(),
101
+ startDate: z.optional(z.null()),
102
+ endDate: z.optional(z.null()),
103
+ }),
104
+ z
105
+ .object({
106
+ date: z.optional(z.null()),
107
+ startDate: z.number(),
108
+ endDate: z.number(),
109
+ })
110
+ .refine((data) => data.startDate !== data.endDate, {
111
+ error: "startDate and endDate must be different",
112
+ path: ["endDate"],
113
+ }),
114
+ ]);
115
+
116
+ const res = zItemTest.safeParse({
117
+ date: null,
118
+ startDate: 1,
119
+ endDate: 1,
120
+ });
121
+
122
+ expect(res).toMatchInlineSnapshot(`
123
+ {
124
+ "error": [ZodError: [
125
+ {
126
+ "code": "custom",
127
+ "path": [
128
+ "endDate"
129
+ ],
130
+ "message": "startDate and endDate must be different"
131
+ }
132
+ ]],
133
+ "success": false,
134
+ }
135
+ `);
136
+ });
137
+
138
+ test("surface continuable errors only if they exist", () => {
139
+ const schema = z.union([z.boolean(), z.uuid(), z.jwt()]);
140
+
141
+ expect(schema.safeParse("asdf")).toMatchInlineSnapshot(`
142
+ {
143
+ "error": [ZodError: [
144
+ {
145
+ "code": "invalid_union",
146
+ "errors": [
147
+ [
148
+ {
149
+ "expected": "boolean",
150
+ "code": "invalid_type",
151
+ "path": [],
152
+ "message": "Invalid input: expected boolean, received string"
153
+ }
154
+ ],
155
+ [
156
+ {
157
+ "origin": "string",
158
+ "code": "invalid_format",
159
+ "format": "uuid",
160
+ "pattern": "/^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000)$/",
161
+ "path": [],
162
+ "message": "Invalid UUID"
163
+ }
164
+ ],
165
+ [
166
+ {
167
+ "code": "invalid_format",
168
+ "format": "jwt",
169
+ "path": [],
170
+ "message": "Invalid JWT"
171
+ }
172
+ ]
173
+ ],
174
+ "path": [],
175
+ "message": "Invalid input"
176
+ }
177
+ ]],
178
+ "success": false,
179
+ }
180
+ `);
181
+ });
@@ -1128,12 +1128,12 @@ export interface $ZodCheckMimeTypeDef extends $ZodCheckDef {
1128
1128
  mime: util.MimeTypes[];
1129
1129
  }
1130
1130
 
1131
- export interface $ZodCheckMimeTypeInternals<T extends File = File> extends $ZodCheckInternals<T> {
1131
+ export interface $ZodCheckMimeTypeInternals<T extends schemas.File = schemas.File> extends $ZodCheckInternals<T> {
1132
1132
  def: $ZodCheckMimeTypeDef;
1133
1133
  issc: errors.$ZodIssueInvalidValue;
1134
1134
  }
1135
1135
 
1136
- export interface $ZodCheckMimeType<T extends File = File> extends $ZodCheck<T> {
1136
+ export interface $ZodCheckMimeType<T extends schemas.File = schemas.File> extends $ZodCheck<T> {
1137
1137
  _zod: $ZodCheckMimeTypeInternals<T>;
1138
1138
  }
1139
1139
 
@@ -1,6 +1,7 @@
1
1
  import type { $ZodCheck, $ZodStringFormats } from "./checks.js";
2
2
  import { $constructor } from "./core.js";
3
3
  import type { $ZodType } from "./schemas.js";
4
+ import type { StandardSchemaV1 } from "./standard-schema.js";
4
5
  import * as util from "./util.js";
5
6
 
6
7
  ///////////////////////////
@@ -162,7 +163,7 @@ type RawIssue<T extends $ZodIssueBase> = util.Flatten<
162
163
  readonly input?: unknown;
163
164
  /** The schema or check that originated this issue. */
164
165
  readonly inst?: $ZodType | $ZodCheck;
165
- /** @deprecated Internal use only. If `true`, Zod will continue executing validation despite this issue. */
166
+ /** If `true`, Zod will continue executing validation despite this issue. */
166
167
  readonly continue?: boolean | undefined;
167
168
  } & Record<string, any>
168
169
  >;
@@ -196,13 +197,8 @@ const initializer = (inst: $ZodError, def: $ZodIssue[]): void => {
196
197
  value: def,
197
198
  enumerable: false,
198
199
  });
199
- Object.defineProperty(inst, "message", {
200
- get() {
201
- return JSON.stringify(def, util.jsonStringifyReplacer, 2);
202
- },
203
- enumerable: true,
204
- // configurable: false,
205
- });
200
+ inst.message = JSON.stringify(def, util.jsonStringifyReplacer, 2);
201
+
206
202
  Object.defineProperty(inst, "toString", {
207
203
  value: () => inst.message,
208
204
  enumerable: false,
@@ -391,8 +387,9 @@ export function treeifyError<T>(error: $ZodError, _mapper?: any) {
391
387
  * ✖ Invalid input: expected number
392
388
  * ```
393
389
  */
394
- export function toDotPath(path: (string | number | symbol)[]): string {
390
+ export function toDotPath(_path: readonly (string | number | symbol | StandardSchemaV1.PathSegment)[]): string {
395
391
  const segs: string[] = [];
392
+ const path: PropertyKey[] = _path.map((seg: any) => (typeof seg === "object" ? seg.key : seg));
396
393
  for (const seg of path) {
397
394
  if (typeof seg === "number") segs.push(`[${seg}]`);
398
395
  else if (typeof seg === "symbol") segs.push(`[${JSON.stringify(String(seg))}]`);
@@ -406,14 +403,10 @@ export function toDotPath(path: (string | number | symbol)[]): string {
406
403
  return segs.join("");
407
404
  }
408
405
 
409
- interface BaseError {
410
- issues: $ZodIssueBase[];
411
- }
412
-
413
- export function prettifyError(error: BaseError): string {
406
+ export function prettifyError(error: StandardSchemaV1.FailureResult): string {
414
407
  const lines: string[] = [];
415
408
  // sort by path length
416
- const issues = [...error.issues].sort((a, b) => a.path.length - b.path.length);
409
+ const issues = [...error.issues].sort((a, b) => (a.path ?? []).length - (b.path ?? []).length);
417
410
 
418
411
  // Process each issue
419
412
  for (const issue of issues) {
@@ -23,7 +23,7 @@ export type $replace<Meta, S extends $ZodType> = Meta extends $output
23
23
  ? { [K in keyof Meta]: $replace<Meta[K], S> }
24
24
  : Meta;
25
25
 
26
- type MetadataType = Record<string, unknown> | undefined;
26
+ type MetadataType = object | undefined;
27
27
  export class $ZodRegistry<Meta extends MetadataType = MetadataType, Schema extends $ZodType = $ZodType> {
28
28
  _meta!: Meta;
29
29
  _schema!: Schema;
@@ -68,7 +68,8 @@ export class $ZodRegistry<Meta extends MetadataType = MetadataType, Schema exten
68
68
  if (p) {
69
69
  const pm: any = { ...(this.get(p) ?? {}) };
70
70
  delete pm.id; // do not inherit id
71
- return { ...pm, ...this._map.get(schema) } as any;
71
+ const f = { ...pm, ...this._map.get(schema) } as any;
72
+ return Object.keys(f).length ? f : undefined;
72
73
  }
73
74
  return this._map.get(schema) as any;
74
75
  }
@@ -121,6 +121,9 @@ export interface _$ZodTypeInternals {
121
121
  */
122
122
  values?: util.PrimitiveSet | undefined;
123
123
 
124
+ /** Default value bubbled up from */
125
+ // default?: unknown | undefined;
126
+
124
127
  /** @internal A set of literal discriminators used for the fast path in discriminated unions. */
125
128
  propValues?: util.PropValues | undefined;
126
129
 
@@ -414,6 +417,7 @@ export const $ZodEmail: core.$constructor<$ZodEmail> = /*@__PURE__*/ core.$const
414
417
  export interface $ZodURLDef extends $ZodStringFormatDef<"url"> {
415
418
  hostname?: RegExp | undefined;
416
419
  protocol?: RegExp | undefined;
420
+ normalize?: boolean | undefined;
417
421
  }
418
422
  export interface $ZodURLInternals extends $ZodStringFormatInternals<"url"> {
419
423
  def: $ZodURLDef;
@@ -427,9 +431,10 @@ export const $ZodURL: core.$constructor<$ZodURL> = /*@__PURE__*/ core.$construct
427
431
  $ZodStringFormat.init(inst, def);
428
432
  inst._zod.check = (payload) => {
429
433
  try {
430
- const orig = payload.value;
431
- const url = new URL(orig);
432
- const href = url.href;
434
+ // Trim whitespace from input
435
+ const trimmed = payload.value.trim();
436
+ // @ts-ignore
437
+ const url = new URL(trimmed);
433
438
 
434
439
  if (def.hostname) {
435
440
  def.hostname.lastIndex = 0;
@@ -461,11 +466,13 @@ export const $ZodURL: core.$constructor<$ZodURL> = /*@__PURE__*/ core.$construct
461
466
  }
462
467
  }
463
468
 
464
- // payload.value = url.href;
465
- if (!orig.endsWith("/") && href.endsWith("/")) {
466
- payload.value = href.slice(0, -1);
469
+ // Set the output value based on normalize flag
470
+ if (def.normalize) {
471
+ // Use normalized URL
472
+ payload.value = url.href;
467
473
  } else {
468
- payload.value = href;
474
+ // Preserve the original input (trimmed)
475
+ payload.value = trimmed;
469
476
  }
470
477
 
471
478
  return;
@@ -719,6 +726,7 @@ export const $ZodIPv6: core.$constructor<$ZodIPv6> = /*@__PURE__*/ core.$constru
719
726
 
720
727
  inst._zod.check = (payload) => {
721
728
  try {
729
+ // @ts-ignore
722
730
  new URL(`http://[${payload.value}]`);
723
731
  // return;
724
732
  } catch {
@@ -782,6 +790,7 @@ export const $ZodCIDRv6: core.$constructor<$ZodCIDRv6> = /*@__PURE__*/ core.$con
782
790
  const prefixNum = Number(prefix);
783
791
  if (`${prefixNum}` !== prefix) throw new Error();
784
792
  if (prefixNum < 0 || prefixNum > 128) throw new Error();
793
+ // @ts-ignore
785
794
  new URL(`http://[${address}]`);
786
795
  } catch {
787
796
  payload.issues.push({
@@ -801,6 +810,7 @@ export function isValidBase64(data: string): boolean {
801
810
  if (data === "") return true;
802
811
  if (data.length % 4 !== 0) return false;
803
812
  try {
813
+ // @ts-ignore
804
814
  atob(data);
805
815
  return true;
806
816
  } catch {
@@ -900,6 +910,7 @@ export function isValidJWT(token: string, algorithm: util.JWTAlgorithm | null =
900
910
  if (tokensParts.length !== 3) return false;
901
911
  const [header] = tokensParts;
902
912
  if (!header) return false;
913
+ // @ts-ignore
903
914
  const parsedHeader = JSON.parse(atob(header));
904
915
  if ("typ" in parsedHeader && parsedHeader?.typ !== "JWT") return false;
905
916
  if (!parsedHeader.alg) return false;
@@ -1582,6 +1593,36 @@ export type $InferObjectOutput<T extends $ZodLooseShape, Extra extends Record<st
1582
1593
  } & Extra
1583
1594
  >;
1584
1595
 
1596
+ // experimental
1597
+ // export type $InferObjectOutput<T extends $ZodLooseShape, Extra extends Record<string, unknown>> = keyof (T &
1598
+ // Extra) extends never
1599
+ // ? Record<string, never>
1600
+ // : string extends keyof T
1601
+ // ? util.Prettify<
1602
+ // {
1603
+ // [k: string]: util.IsAny<T[string]["_zod"]["output"]> extends true ? unknown : T[string]["_zod"]["output"];
1604
+ // } & $InferObjectOutputNoIndex<util.OmitIndexSignature<T>, Extra>
1605
+ // >
1606
+ // : util.Prettify<$InferObjectOutputNoIndex<T, Extra>>;
1607
+
1608
+ // export type $InferObjectOutputNoIndex<T extends $ZodLooseShape, Extra extends Record<string, unknown>> = {
1609
+ // [k in keyof T as string extends k
1610
+ // ? never
1611
+ // : k extends string
1612
+ // ? T[k] extends OptionalOutSchema
1613
+ // ? never
1614
+ // : k
1615
+ // : never]: T[k]["_zod"]["output"];
1616
+ // } & {
1617
+ // [k in keyof T as string extends k
1618
+ // ? never
1619
+ // : k extends string
1620
+ // ? T[k] extends OptionalOutSchema
1621
+ // ? k
1622
+ // : never
1623
+ // : never]?: T[k]["_zod"]["output"];
1624
+ // } & Extra;
1625
+
1585
1626
  export type $InferObjectInput<T extends $ZodLooseShape, Extra extends Record<string, unknown>> = string extends keyof T
1586
1627
  ? util.IsAny<T[keyof T]> extends true
1587
1628
  ? Record<string, unknown>
@@ -1596,33 +1637,16 @@ export type $InferObjectInput<T extends $ZodLooseShape, Extra extends Record<str
1596
1637
  } & Extra
1597
1638
  >;
1598
1639
 
1599
- function handleObjectResult(result: ParsePayload, final: ParsePayload, key: PropertyKey) {
1600
- // if(isOptional)
1640
+ function handlePropertyResult(result: ParsePayload, final: ParsePayload, key: PropertyKey, input: any) {
1601
1641
  if (result.issues.length) {
1602
1642
  final.issues.push(...util.prefixIssues(key, result.issues));
1603
1643
  }
1604
1644
 
1605
- (final.value as any)[key] = result.value;
1606
- }
1607
-
1608
- function handleOptionalObjectResult(result: ParsePayload, final: ParsePayload, key: PropertyKey, input: any) {
1609
- if (result.issues.length) {
1610
- // validation failed against value schema
1611
- if (input[key] === undefined) {
1612
- // if input was undefined, ignore the error
1613
- if (key in input) {
1614
- (final.value as any)[key] = undefined;
1615
- } else {
1616
- (final.value as any)[key] = result.value;
1617
- }
1618
- } else {
1619
- final.issues.push(...util.prefixIssues(key, result.issues));
1645
+ if (result.value === undefined) {
1646
+ if (key in input) {
1647
+ (final.value as any)[key] = undefined;
1620
1648
  }
1621
- } else if (result.value === undefined) {
1622
- // validation returned `undefined`
1623
- if (key in input) (final.value as any)[key] = undefined;
1624
1649
  } else {
1625
- // non-undefined value
1626
1650
  (final.value as any)[key] = result.value;
1627
1651
  }
1628
1652
  }
@@ -1732,41 +1756,25 @@ export const $ZodObject: core.$constructor<$ZodObject> = /*@__PURE__*/ core.$con
1732
1756
  // A: preserve key order {
1733
1757
  doc.write(`const newResult = {}`);
1734
1758
  for (const key of normalized.keys) {
1735
- if (normalized.optionalKeys.has(key)) {
1736
- const id = ids[key];
1737
- doc.write(`const ${id} = ${parseStr(key)};`);
1738
- const k = util.esc(key);
1739
- doc.write(`
1759
+ const id = ids[key];
1760
+ const k = util.esc(key);
1761
+ doc.write(`const ${id} = ${parseStr(key)};`);
1762
+ doc.write(`
1740
1763
  if (${id}.issues.length) {
1741
- if (input[${k}] === undefined) {
1742
- if (${k} in input) {
1743
- newResult[${k}] = undefined;
1744
- }
1745
- } else {
1746
- payload.issues = payload.issues.concat(
1747
- ${id}.issues.map((iss) => ({
1748
- ...iss,
1749
- path: iss.path ? [${k}, ...iss.path] : [${k}],
1750
- }))
1751
- );
1764
+ payload.issues = payload.issues.concat(${id}.issues.map(iss => ({
1765
+ ...iss,
1766
+ path: iss.path ? [${k}, ...iss.path] : [${k}]
1767
+ })));
1768
+ }
1769
+
1770
+ if (${id}.value === undefined) {
1771
+ if (${k} in input) {
1772
+ newResult[${k}] = undefined;
1752
1773
  }
1753
- } else if (${id}.value === undefined) {
1754
- if (${k} in input) newResult[${k}] = undefined;
1755
1774
  } else {
1756
1775
  newResult[${k}] = ${id}.value;
1757
1776
  }
1758
- `);
1759
- } else {
1760
- const id = ids[key];
1761
- // const id = ids[key];
1762
- doc.write(`const ${id} = ${parseStr(key)};`);
1763
- doc.write(`
1764
- if (${id}.issues.length) payload.issues = payload.issues.concat(${id}.issues.map(iss => ({
1765
- ...iss,
1766
- path: iss.path ? [${util.esc(key)}, ...iss.path] : [${util.esc(key)}]
1767
- })));`);
1768
- doc.write(`newResult[${util.esc(key)}] = ${id}.value`);
1769
- }
1777
+ `);
1770
1778
  }
1771
1779
 
1772
1780
  doc.write(`payload.value = newResult;`);
@@ -1811,39 +1819,16 @@ export const $ZodObject: core.$constructor<$ZodObject> = /*@__PURE__*/ core.$con
1811
1819
  const shape = value.shape;
1812
1820
  for (const key of value.keys) {
1813
1821
  const el = shape[key]!;
1814
-
1815
- // do not add omitted optional keys
1816
- // if (!(key in input)) {
1817
- // if (optionalKeys.has(key)) continue;
1818
- // payload.issues.push({
1819
- // code: "invalid_type",
1820
- // path: [key],
1821
- // expected: "nonoptional",
1822
- // note: `Missing required key: "${key}"`,
1823
- // input,
1824
- // inst,
1825
- // });
1826
- // }
1827
-
1828
1822
  const r = el._zod.run({ value: input[key], issues: [] }, ctx);
1829
- const isOptional = el._zod.optin === "optional" && el._zod.optout === "optional";
1830
-
1831
1823
  if (r instanceof Promise) {
1832
- proms.push(
1833
- r.then((r) =>
1834
- isOptional ? handleOptionalObjectResult(r, payload, key, input) : handleObjectResult(r, payload, key)
1835
- )
1836
- );
1837
- } else if (isOptional) {
1838
- handleOptionalObjectResult(r, payload, key, input);
1824
+ proms.push(r.then((r) => handlePropertyResult(r, payload, key, input)));
1839
1825
  } else {
1840
- handleObjectResult(r, payload, key);
1826
+ handlePropertyResult(r, payload, key, input);
1841
1827
  }
1842
1828
  }
1843
1829
  }
1844
1830
 
1845
1831
  if (!catchall) {
1846
- // return payload;
1847
1832
  return proms.length ? Promise.all(proms).then(() => payload) : payload;
1848
1833
  }
1849
1834
  const unrecognized: string[] = [];
@@ -1860,9 +1845,9 @@ export const $ZodObject: core.$constructor<$ZodObject> = /*@__PURE__*/ core.$con
1860
1845
  const r = _catchall.run({ value: input[key], issues: [] }, ctx);
1861
1846
 
1862
1847
  if (r instanceof Promise) {
1863
- proms.push(r.then((r) => handleObjectResult(r, payload, key)));
1848
+ proms.push(r.then((r) => handlePropertyResult(r, payload, key, input)));
1864
1849
  } else {
1865
- handleObjectResult(r, payload, key);
1850
+ handlePropertyResult(r, payload, key, input);
1866
1851
  }
1867
1852
  }
1868
1853
 
@@ -1925,6 +1910,12 @@ function handleUnionResults(results: ParsePayload[], final: ParsePayload, inst:
1925
1910
  }
1926
1911
  }
1927
1912
 
1913
+ const nonaborted = results.filter((r) => !util.aborted(r));
1914
+ if (nonaborted.length === 1) {
1915
+ final.value = nonaborted[0].value;
1916
+ return nonaborted[0];
1917
+ }
1918
+
1928
1919
  final.issues.push({
1929
1920
  code: "invalid_union",
1930
1921
  input: final.value,
@@ -2737,8 +2728,8 @@ export const $ZodEnum: core.$constructor<$ZodEnum> = /*@__PURE__*/ core.$constru
2737
2728
  $ZodType.init(inst, def);
2738
2729
 
2739
2730
  const values = util.getEnumValues(def.entries);
2740
-
2741
- inst._zod.values = new Set<util.Primitive>(values);
2731
+ const valuesSet = new Set<util.Primitive>(values);
2732
+ inst._zod.values = valuesSet;
2742
2733
 
2743
2734
  inst._zod.pattern = new RegExp(
2744
2735
  `^(${values
@@ -2749,7 +2740,7 @@ export const $ZodEnum: core.$constructor<$ZodEnum> = /*@__PURE__*/ core.$constru
2749
2740
 
2750
2741
  inst._zod.parse = (payload, _ctx) => {
2751
2742
  const input = payload.value;
2752
- if (inst._zod.values.has(input)) {
2743
+ if (valuesSet.has(input)) {
2753
2744
  return payload;
2754
2745
  }
2755
2746
  payload.issues.push({
@@ -2790,12 +2781,15 @@ export const $ZodLiteral: core.$constructor<$ZodLiteral> = /*@__PURE__*/ core.$c
2790
2781
  "$ZodLiteral",
2791
2782
  (inst, def) => {
2792
2783
  $ZodType.init(inst, def);
2784
+ if (def.values.length === 0) {
2785
+ throw new Error("Cannot create literal schema with no valid values");
2786
+ }
2793
2787
 
2794
2788
  inst._zod.values = new Set<util.Literal>(def.values);
2795
2789
  inst._zod.pattern = new RegExp(
2796
2790
  `^(${def.values
2797
2791
 
2798
- .map((o) => (typeof o === "string" ? util.escapeRegex(o) : o ? o.toString() : String(o)))
2792
+ .map((o) => (typeof o === "string" ? util.escapeRegex(o) : o ? util.escapeRegex(o.toString()) : String(o)))
2799
2793
  .join("|")})$`
2800
2794
  );
2801
2795
 
@@ -2865,10 +2859,12 @@ export const $ZodLiteral: core.$constructor<$ZodLiteral> = /*@__PURE__*/ core.$c
2865
2859
  //////////////////////////////////////////
2866
2860
 
2867
2861
  // provide a fallback in case the File interface isn't provided in the environment
2868
- type _File = typeof globalThis extends { File: new (...args: any[]) => any }
2869
- ? InstanceType<typeof globalThis.File>
2870
- : {};
2871
- interface File extends _File {}
2862
+ type _File = typeof globalThis extends { File: infer F extends new (...args: any[]) => any } ? InstanceType<F> : {};
2863
+ /** Do not reference this directly. */
2864
+ export interface File extends _File {
2865
+ type: string;
2866
+ size: number;
2867
+ }
2872
2868
 
2873
2869
  export interface $ZodFileDef extends $ZodTypeDef {
2874
2870
  type: "file";
@@ -2893,6 +2889,7 @@ export const $ZodFile: core.$constructor<$ZodFile> = /*@__PURE__*/ core.$constru
2893
2889
 
2894
2890
  inst._zod.parse = (payload, _ctx) => {
2895
2891
  const input = payload.value;
2892
+ // @ts-ignore
2896
2893
  if (input instanceof File) return payload;
2897
2894
  payload.issues.push({
2898
2895
  expected: "file",
@@ -3329,7 +3326,7 @@ export interface $ZodCatch<T extends SomeType = $ZodType> extends $ZodType {
3329
3326
 
3330
3327
  export const $ZodCatch: core.$constructor<$ZodCatch> = /*@__PURE__*/ core.$constructor("$ZodCatch", (inst, def) => {
3331
3328
  $ZodType.init(inst, def);
3332
- inst._zod.optin = "optional";
3329
+ util.defineLazy(inst._zod, "optin", () => def.innerType._zod.optin);
3333
3330
  util.defineLazy(inst._zod, "optout", () => def.innerType._zod.optout);
3334
3331
  util.defineLazy(inst._zod, "values", () => def.innerType._zod.values);
3335
3332
 
@@ -3362,6 +3359,7 @@ export const $ZodCatch: core.$constructor<$ZodCatch> = /*@__PURE__*/ core.$const
3362
3359
  },
3363
3360
  input: payload.value,
3364
3361
  });
3362
+
3365
3363
  payload.issues = [];
3366
3364
  }
3367
3365
 
@@ -3450,7 +3448,7 @@ export const $ZodPipe: core.$constructor<$ZodPipe> = /*@__PURE__*/ core.$constru
3450
3448
  });
3451
3449
 
3452
3450
  function handlePipeResult(left: ParsePayload, def: $ZodPipeDef, ctx: ParseContext) {
3453
- if (util.aborted(left)) {
3451
+ if (left.issues.length) {
3454
3452
  return left;
3455
3453
  }
3456
3454
  return def.out._zod.run({ value: left.value, issues: left.issues }, ctx);