zod 4.1.0-canary.20250730T051934 → 4.1.0-canary.20250804T184136

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zod",
3
- "version": "4.1.0-canary.20250730T051934",
3
+ "version": "4.1.0-canary.20250804T184136",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "author": "Colin McDonnell <zod@colinhacks.com>",
@@ -1149,7 +1149,7 @@ export function object<T extends core.$ZodLooseShape = Partial<Record<never, cor
1149
1149
  const def: core.$ZodObjectDef = {
1150
1150
  type: "object",
1151
1151
  get shape() {
1152
- util.assignProp(this, "shape", { ...shape });
1152
+ util.assignProp(this, "shape", shape ? util.objectClone(shape) : {});
1153
1153
  return this.shape;
1154
1154
  },
1155
1155
  ...util.normalizeParams(params),
@@ -1166,7 +1166,7 @@ export function strictObject<T extends core.$ZodLooseShape>(
1166
1166
  return new ZodObject({
1167
1167
  type: "object",
1168
1168
  get shape() {
1169
- util.assignProp(this, "shape", { ...shape });
1169
+ util.assignProp(this, "shape", util.objectClone(shape));
1170
1170
  return this.shape;
1171
1171
  },
1172
1172
  catchall: never(),
@@ -1183,7 +1183,7 @@ export function looseObject<T extends core.$ZodLooseShape>(
1183
1183
  return new ZodObject({
1184
1184
  type: "object",
1185
1185
  get shape() {
1186
- util.assignProp(this, "shape", { ...shape });
1186
+ util.assignProp(this, "shape", util.objectClone(shape));
1187
1187
  return this.shape;
1188
1188
  },
1189
1189
  catchall: unknown(),
@@ -366,6 +366,21 @@ test("object utilities with recursive types", () => {
366
366
  ]);
367
367
  });
368
368
 
369
+ test("tuple with recursive types", () => {
370
+ const TaskListNodeSchema = z.strictObject({
371
+ type: z.literal("taskList"),
372
+ get content() {
373
+ return z.array(z.tuple([TaskListNodeSchema, z.union([TaskListNodeSchema])])).min(1);
374
+ },
375
+ });
376
+ type TaskListNodeSchema = z.infer<typeof TaskListNodeSchema>;
377
+ type _TaskListNodeSchema = {
378
+ type: "taskList";
379
+ content: [_TaskListNodeSchema, _TaskListNodeSchema][];
380
+ };
381
+ expectTypeOf<TaskListNodeSchema>().toEqualTypeOf<_TaskListNodeSchema>();
382
+ });
383
+
369
384
  test("recursion compatibility", () => {
370
385
  // array
371
386
  const A = z.object({
@@ -431,6 +446,68 @@ test("recursion compatibility", () => {
431
446
  });
432
447
  });
433
448
 
449
+ test("recursive object with .check()", () => {
450
+ const Category = z
451
+ .object({
452
+ id: z.string(),
453
+ name: z.string(),
454
+ get subcategories() {
455
+ return z.array(Category).optional();
456
+ },
457
+ })
458
+ .check((ctx) => {
459
+ // Check for duplicate IDs among direct subcategories
460
+ if (ctx.value.subcategories) {
461
+ const siblingIds = new Set<string>();
462
+ ctx.value.subcategories.forEach((sub, index) => {
463
+ if (siblingIds.has(sub.id)) {
464
+ ctx.issues.push({
465
+ code: "custom",
466
+ message: `Duplicate sibling ID found: ${sub.id}`,
467
+ path: ["subcategories", index, "id"],
468
+ input: ctx.value,
469
+ });
470
+ }
471
+ siblingIds.add(sub.id);
472
+ });
473
+ }
474
+ });
475
+
476
+ // Valid - siblings have unique IDs
477
+ const validData = {
478
+ id: "electronics",
479
+ name: "Electronics",
480
+ subcategories: [
481
+ {
482
+ id: "computers",
483
+ name: "Computers",
484
+ subcategories: [
485
+ { id: "laptops", name: "Laptops" },
486
+ { id: "desktops", name: "Desktops" },
487
+ ],
488
+ },
489
+ {
490
+ id: "phones",
491
+ name: "Phones",
492
+ },
493
+ ],
494
+ };
495
+
496
+ // Invalid - duplicate sibling IDs
497
+ const invalidData = {
498
+ id: "electronics",
499
+ name: "Electronics",
500
+ subcategories: [
501
+ { id: "computers", name: "Computers" },
502
+ { id: "phones", name: "Phones" },
503
+ { id: "computers", name: "Computers Again" }, // Duplicate at index 2
504
+ ],
505
+ };
506
+
507
+ expect(() => Category.parse(validData)).not.toThrow();
508
+ expect(() => Category.parse(invalidData)).toThrow();
509
+ });
510
+
434
511
  // biome-ignore lint: sadf
435
512
  export type RecursiveA = z.ZodUnion<
436
513
  [
@@ -314,8 +314,8 @@ export function _ksuid<T extends schemas.$ZodKSUID>(
314
314
  }
315
315
 
316
316
  // IPv4
317
- export type $ZodIPv4Params = StringFormatParams<schemas.$ZodIPv4, "pattern" | "when">;
318
- export type $ZodCheckIPv4Params = CheckStringFormatParams<schemas.$ZodIPv4, "pattern" | "when">;
317
+ export type $ZodIPv4Params = StringFormatParams<schemas.$ZodIPv4, "pattern" | "when" | "version">;
318
+ export type $ZodCheckIPv4Params = CheckStringFormatParams<schemas.$ZodIPv4, "pattern" | "when" | "version">;
319
319
  export function _ipv4<T extends schemas.$ZodIPv4>(
320
320
  Class: util.SchemaClass<T>,
321
321
  params?: string | $ZodIPv4Params | $ZodCheckIPv4Params
@@ -330,8 +330,8 @@ export function _ipv4<T extends schemas.$ZodIPv4>(
330
330
  }
331
331
 
332
332
  // IPv6
333
- export type $ZodIPv6Params = StringFormatParams<schemas.$ZodIPv6, "pattern" | "when">;
334
- export type $ZodCheckIPv6Params = CheckStringFormatParams<schemas.$ZodIPv6, "pattern" | "when">;
333
+ export type $ZodIPv6Params = StringFormatParams<schemas.$ZodIPv6, "pattern" | "when" | "version">;
334
+ export type $ZodCheckIPv6Params = CheckStringFormatParams<schemas.$ZodIPv6, "pattern" | "when" | "version">;
335
335
  export function _ipv6<T extends schemas.$ZodIPv6>(
336
336
  Class: util.SchemaClass<T>,
337
337
  params?: string | $ZodIPv6Params | $ZodCheckIPv6Params
@@ -1701,6 +1701,8 @@ export interface $ZodObjectInternals<
1701
1701
  propValues: util.PropValues;
1702
1702
  output: $InferObjectOutput<Shape, Config["out"]>;
1703
1703
  input: $InferObjectInput<Shape, Config["in"]>;
1704
+ optin?: "optional" | undefined;
1705
+ optout?: "optional" | undefined;
1704
1706
  }
1705
1707
  export type $ZodLooseShape = Record<string, any>;
1706
1708
 
@@ -2282,9 +2284,12 @@ type TupleOutputTypeWithOptionals<T extends util.TupleItems> = T extends readonl
2282
2284
  export interface $ZodTupleInternals<
2283
2285
  T extends util.TupleItems = readonly $ZodType[],
2284
2286
  Rest extends SomeType | null = $ZodType | null,
2285
- > extends $ZodTypeInternals<$InferTupleOutputType<T, Rest>, $InferTupleInputType<T, Rest>> {
2287
+ > extends _$ZodTypeInternals {
2286
2288
  def: $ZodTupleDef<T, Rest>;
2287
2289
  isst: errors.$ZodIssueInvalidType | errors.$ZodIssueTooBig<unknown[]> | errors.$ZodIssueTooSmall<unknown[]>;
2290
+ // $ZodTypeInternals<$InferTupleOutputType<T, Rest>, $InferTupleInputType<T, Rest>>
2291
+ output: $InferTupleOutputType<T, Rest>;
2292
+ input: $InferTupleInputType<T, Rest>;
2288
2293
  }
2289
2294
 
2290
2295
  export interface $ZodTuple<
@@ -3746,11 +3751,18 @@ export interface $ZodLazy<T extends SomeType = $ZodType> extends $ZodType {
3746
3751
  export const $ZodLazy: core.$constructor<$ZodLazy> = /*@__PURE__*/ core.$constructor("$ZodLazy", (inst, def) => {
3747
3752
  $ZodType.init(inst, def);
3748
3753
 
3754
+ // let _innerType!: any;
3755
+ // util.defineLazy(def, "getter", () => {
3756
+ // if (!_innerType) {
3757
+ // _innerType = def.getter();
3758
+ // }
3759
+ // return () => _innerType;
3760
+ // });
3749
3761
  util.defineLazy(inst._zod, "innerType", () => def.getter() as $ZodType);
3750
3762
  util.defineLazy(inst._zod, "pattern", () => inst._zod.innerType._zod.pattern);
3751
3763
  util.defineLazy(inst._zod, "propValues", () => inst._zod.innerType._zod.propValues);
3752
- util.defineLazy(inst._zod, "optin", () => inst._zod.innerType._zod.optin);
3753
- util.defineLazy(inst._zod, "optout", () => inst._zod.innerType._zod.optout);
3764
+ util.defineLazy(inst._zod, "optin", () => inst._zod.innerType._zod.optin ?? undefined);
3765
+ util.defineLazy(inst._zod, "optout", () => inst._zod.innerType._zod.optout ?? undefined);
3754
3766
  inst._zod.parse = (payload, ctx) => {
3755
3767
  const inner = inst._zod.innerType;
3756
3768
  return inner._zod.run(payload, ctx);
@@ -257,16 +257,21 @@ export function floatSafeRemainder(val: number, step: number): number {
257
257
  return (valInt % stepInt) / 10 ** decCount;
258
258
  }
259
259
 
260
+ const EVALUATING = Symbol("evaluating");
261
+
260
262
  export function defineLazy<T, K extends keyof T>(object: T, key: K, getter: () => T[K]): void {
261
- const set = false;
263
+ let value: T[K] | typeof EVALUATING | undefined = undefined;
262
264
  Object.defineProperty(object, key, {
263
265
  get() {
264
- if (!set) {
265
- const value = getter();
266
- object[key] = value;
267
- return value;
266
+ if (value === EVALUATING) {
267
+ // Circular reference detected, return undefined to break the cycle
268
+ return undefined as T[K];
268
269
  }
269
- throw new Error("cached value already set");
270
+ if (value === undefined) {
271
+ value = EVALUATING;
272
+ value = getter();
273
+ }
274
+ return value;
270
275
  },
271
276
  set(v) {
272
277
  Object.defineProperty(object, key, {
@@ -279,6 +284,10 @@ export function defineLazy<T, K extends keyof T>(object: T, key: K, getter: () =
279
284
  });
280
285
  }
281
286
 
287
+ export function objectClone(obj: object) {
288
+ return Object.create(Object.getPrototypeOf(obj), Object.getOwnPropertyDescriptors(obj));
289
+ }
290
+
282
291
  export function assignProp<T extends object, K extends PropertyKey>(
283
292
  target: T,
284
293
  prop: K,
@@ -1,5 +1,5 @@
1
1
  export const version = {
2
2
  major: 4,
3
3
  minor: 0,
4
- patch: 13 as number,
4
+ patch: 14 as number,
5
5
  } as const;
@@ -615,7 +615,7 @@ function object(shape, params) {
615
615
  const def = {
616
616
  type: "object",
617
617
  get shape() {
618
- index_js_1.util.assignProp(this, "shape", { ...shape });
618
+ index_js_1.util.assignProp(this, "shape", shape ? index_js_1.util.objectClone(shape) : {});
619
619
  return this.shape;
620
620
  },
621
621
  ...index_js_1.util.normalizeParams(params),
@@ -627,7 +627,7 @@ function strictObject(shape, params) {
627
627
  return new exports.ZodObject({
628
628
  type: "object",
629
629
  get shape() {
630
- index_js_1.util.assignProp(this, "shape", { ...shape });
630
+ index_js_1.util.assignProp(this, "shape", index_js_1.util.objectClone(shape));
631
631
  return this.shape;
632
632
  },
633
633
  catchall: never(),
@@ -639,7 +639,7 @@ function looseObject(shape, params) {
639
639
  return new exports.ZodObject({
640
640
  type: "object",
641
641
  get shape() {
642
- index_js_1.util.assignProp(this, "shape", { ...shape });
642
+ index_js_1.util.assignProp(this, "shape", index_js_1.util.objectClone(shape));
643
643
  return this.shape;
644
644
  },
645
645
  catchall: unknown(),
@@ -509,7 +509,7 @@ export function object(shape, params) {
509
509
  const def = {
510
510
  type: "object",
511
511
  get shape() {
512
- util.assignProp(this, "shape", { ...shape });
512
+ util.assignProp(this, "shape", shape ? util.objectClone(shape) : {});
513
513
  return this.shape;
514
514
  },
515
515
  ...util.normalizeParams(params),
@@ -521,7 +521,7 @@ export function strictObject(shape, params) {
521
521
  return new ZodObject({
522
522
  type: "object",
523
523
  get shape() {
524
- util.assignProp(this, "shape", { ...shape });
524
+ util.assignProp(this, "shape", util.objectClone(shape));
525
525
  return this.shape;
526
526
  },
527
527
  catchall: never(),
@@ -533,7 +533,7 @@ export function looseObject(shape, params) {
533
533
  return new ZodObject({
534
534
  type: "object",
535
535
  get shape() {
536
- util.assignProp(this, "shape", { ...shape });
536
+ util.assignProp(this, "shape", util.objectClone(shape));
537
537
  return this.shape;
538
538
  },
539
539
  catchall: unknown(),
package/v4/core/api.d.cts CHANGED
@@ -63,11 +63,11 @@ export declare function _xid<T extends schemas.$ZodXID>(Class: util.SchemaClass<
63
63
  export type $ZodKSUIDParams = StringFormatParams<schemas.$ZodKSUID, "when">;
64
64
  export type $ZodCheckKSUIDParams = CheckStringFormatParams<schemas.$ZodKSUID, "when">;
65
65
  export declare function _ksuid<T extends schemas.$ZodKSUID>(Class: util.SchemaClass<T>, params?: string | $ZodKSUIDParams | $ZodCheckKSUIDParams): T;
66
- export type $ZodIPv4Params = StringFormatParams<schemas.$ZodIPv4, "pattern" | "when">;
67
- export type $ZodCheckIPv4Params = CheckStringFormatParams<schemas.$ZodIPv4, "pattern" | "when">;
66
+ export type $ZodIPv4Params = StringFormatParams<schemas.$ZodIPv4, "pattern" | "when" | "version">;
67
+ export type $ZodCheckIPv4Params = CheckStringFormatParams<schemas.$ZodIPv4, "pattern" | "when" | "version">;
68
68
  export declare function _ipv4<T extends schemas.$ZodIPv4>(Class: util.SchemaClass<T>, params?: string | $ZodIPv4Params | $ZodCheckIPv4Params): T;
69
- export type $ZodIPv6Params = StringFormatParams<schemas.$ZodIPv6, "pattern" | "when">;
70
- export type $ZodCheckIPv6Params = CheckStringFormatParams<schemas.$ZodIPv6, "pattern" | "when">;
69
+ export type $ZodIPv6Params = StringFormatParams<schemas.$ZodIPv6, "pattern" | "when" | "version">;
70
+ export type $ZodCheckIPv6Params = CheckStringFormatParams<schemas.$ZodIPv6, "pattern" | "when" | "version">;
71
71
  export declare function _ipv6<T extends schemas.$ZodIPv6>(Class: util.SchemaClass<T>, params?: string | $ZodIPv6Params | $ZodCheckIPv6Params): T;
72
72
  export type $ZodCIDRv4Params = StringFormatParams<schemas.$ZodCIDRv4, "pattern" | "when">;
73
73
  export type $ZodCheckCIDRv4Params = CheckStringFormatParams<schemas.$ZodCIDRv4, "pattern" | "when">;
package/v4/core/api.d.ts CHANGED
@@ -63,11 +63,11 @@ export declare function _xid<T extends schemas.$ZodXID>(Class: util.SchemaClass<
63
63
  export type $ZodKSUIDParams = StringFormatParams<schemas.$ZodKSUID, "when">;
64
64
  export type $ZodCheckKSUIDParams = CheckStringFormatParams<schemas.$ZodKSUID, "when">;
65
65
  export declare function _ksuid<T extends schemas.$ZodKSUID>(Class: util.SchemaClass<T>, params?: string | $ZodKSUIDParams | $ZodCheckKSUIDParams): T;
66
- export type $ZodIPv4Params = StringFormatParams<schemas.$ZodIPv4, "pattern" | "when">;
67
- export type $ZodCheckIPv4Params = CheckStringFormatParams<schemas.$ZodIPv4, "pattern" | "when">;
66
+ export type $ZodIPv4Params = StringFormatParams<schemas.$ZodIPv4, "pattern" | "when" | "version">;
67
+ export type $ZodCheckIPv4Params = CheckStringFormatParams<schemas.$ZodIPv4, "pattern" | "when" | "version">;
68
68
  export declare function _ipv4<T extends schemas.$ZodIPv4>(Class: util.SchemaClass<T>, params?: string | $ZodIPv4Params | $ZodCheckIPv4Params): T;
69
- export type $ZodIPv6Params = StringFormatParams<schemas.$ZodIPv6, "pattern" | "when">;
70
- export type $ZodCheckIPv6Params = CheckStringFormatParams<schemas.$ZodIPv6, "pattern" | "when">;
69
+ export type $ZodIPv6Params = StringFormatParams<schemas.$ZodIPv6, "pattern" | "when" | "version">;
70
+ export type $ZodCheckIPv6Params = CheckStringFormatParams<schemas.$ZodIPv6, "pattern" | "when" | "version">;
71
71
  export declare function _ipv6<T extends schemas.$ZodIPv6>(Class: util.SchemaClass<T>, params?: string | $ZodIPv6Params | $ZodCheckIPv6Params): T;
72
72
  export type $ZodCIDRv4Params = StringFormatParams<schemas.$ZodCIDRv4, "pattern" | "when">;
73
73
  export type $ZodCheckCIDRv4Params = CheckStringFormatParams<schemas.$ZodCIDRv4, "pattern" | "when">;
@@ -1684,11 +1684,18 @@ exports.$ZodPromise = core.$constructor("$ZodPromise", (inst, def) => {
1684
1684
  });
1685
1685
  exports.$ZodLazy = core.$constructor("$ZodLazy", (inst, def) => {
1686
1686
  exports.$ZodType.init(inst, def);
1687
+ // let _innerType!: any;
1688
+ // util.defineLazy(def, "getter", () => {
1689
+ // if (!_innerType) {
1690
+ // _innerType = def.getter();
1691
+ // }
1692
+ // return () => _innerType;
1693
+ // });
1687
1694
  util.defineLazy(inst._zod, "innerType", () => def.getter());
1688
1695
  util.defineLazy(inst._zod, "pattern", () => inst._zod.innerType._zod.pattern);
1689
1696
  util.defineLazy(inst._zod, "propValues", () => inst._zod.innerType._zod.propValues);
1690
- util.defineLazy(inst._zod, "optin", () => inst._zod.innerType._zod.optin);
1691
- util.defineLazy(inst._zod, "optout", () => inst._zod.innerType._zod.optout);
1697
+ util.defineLazy(inst._zod, "optin", () => inst._zod.innerType._zod.optin ?? undefined);
1698
+ util.defineLazy(inst._zod, "optout", () => inst._zod.innerType._zod.optout ?? undefined);
1692
1699
  inst._zod.parse = (payload, ctx) => {
1693
1700
  const inner = inst._zod.innerType;
1694
1701
  return inner._zod.run(payload, ctx);
@@ -587,6 +587,8 @@ out Shape extends Readonly<$ZodShape> = Readonly<$ZodShape>, out Config extends
587
587
  propValues: util.PropValues;
588
588
  output: $InferObjectOutput<Shape, Config["out"]>;
589
589
  input: $InferObjectInput<Shape, Config["in"]>;
590
+ optin?: "optional" | undefined;
591
+ optout?: "optional" | undefined;
590
592
  }
591
593
  export type $ZodLooseShape = Record<string, any>;
592
594
  export interface $ZodObject<
@@ -673,9 +675,11 @@ type TupleOutputTypeWithOptionals<T extends util.TupleItems> = T extends readonl
673
675
  ...infer Prefix extends SomeType[],
674
676
  infer Tail extends SomeType
675
677
  ] ? Tail["_zod"]["optout"] extends "optional" ? [...TupleOutputTypeWithOptionals<Prefix>, core.output<Tail>?] : TupleOutputTypeNoOptionals<T> : [];
676
- export interface $ZodTupleInternals<T extends util.TupleItems = readonly $ZodType[], Rest extends SomeType | null = $ZodType | null> extends $ZodTypeInternals<$InferTupleOutputType<T, Rest>, $InferTupleInputType<T, Rest>> {
678
+ export interface $ZodTupleInternals<T extends util.TupleItems = readonly $ZodType[], Rest extends SomeType | null = $ZodType | null> extends _$ZodTypeInternals {
677
679
  def: $ZodTupleDef<T, Rest>;
678
680
  isst: errors.$ZodIssueInvalidType | errors.$ZodIssueTooBig<unknown[]> | errors.$ZodIssueTooSmall<unknown[]>;
681
+ output: $InferTupleOutputType<T, Rest>;
682
+ input: $InferTupleInputType<T, Rest>;
679
683
  }
680
684
  export interface $ZodTuple<T extends util.TupleItems = readonly $ZodType[], Rest extends SomeType | null = $ZodType | null> extends $ZodType {
681
685
  _zod: $ZodTupleInternals<T, Rest>;
@@ -587,6 +587,8 @@ out Shape extends Readonly<$ZodShape> = Readonly<$ZodShape>, out Config extends
587
587
  propValues: util.PropValues;
588
588
  output: $InferObjectOutput<Shape, Config["out"]>;
589
589
  input: $InferObjectInput<Shape, Config["in"]>;
590
+ optin?: "optional" | undefined;
591
+ optout?: "optional" | undefined;
590
592
  }
591
593
  export type $ZodLooseShape = Record<string, any>;
592
594
  export interface $ZodObject<
@@ -673,9 +675,11 @@ type TupleOutputTypeWithOptionals<T extends util.TupleItems> = T extends readonl
673
675
  ...infer Prefix extends SomeType[],
674
676
  infer Tail extends SomeType
675
677
  ] ? Tail["_zod"]["optout"] extends "optional" ? [...TupleOutputTypeWithOptionals<Prefix>, core.output<Tail>?] : TupleOutputTypeNoOptionals<T> : [];
676
- export interface $ZodTupleInternals<T extends util.TupleItems = readonly $ZodType[], Rest extends SomeType | null = $ZodType | null> extends $ZodTypeInternals<$InferTupleOutputType<T, Rest>, $InferTupleInputType<T, Rest>> {
678
+ export interface $ZodTupleInternals<T extends util.TupleItems = readonly $ZodType[], Rest extends SomeType | null = $ZodType | null> extends _$ZodTypeInternals {
677
679
  def: $ZodTupleDef<T, Rest>;
678
680
  isst: errors.$ZodIssueInvalidType | errors.$ZodIssueTooBig<unknown[]> | errors.$ZodIssueTooSmall<unknown[]>;
681
+ output: $InferTupleOutputType<T, Rest>;
682
+ input: $InferTupleInputType<T, Rest>;
679
683
  }
680
684
  export interface $ZodTuple<T extends util.TupleItems = readonly $ZodType[], Rest extends SomeType | null = $ZodType | null> extends $ZodType {
681
685
  _zod: $ZodTupleInternals<T, Rest>;
@@ -1653,11 +1653,18 @@ export const $ZodPromise = /*@__PURE__*/ core.$constructor("$ZodPromise", (inst,
1653
1653
  });
1654
1654
  export const $ZodLazy = /*@__PURE__*/ core.$constructor("$ZodLazy", (inst, def) => {
1655
1655
  $ZodType.init(inst, def);
1656
+ // let _innerType!: any;
1657
+ // util.defineLazy(def, "getter", () => {
1658
+ // if (!_innerType) {
1659
+ // _innerType = def.getter();
1660
+ // }
1661
+ // return () => _innerType;
1662
+ // });
1656
1663
  util.defineLazy(inst._zod, "innerType", () => def.getter());
1657
1664
  util.defineLazy(inst._zod, "pattern", () => inst._zod.innerType._zod.pattern);
1658
1665
  util.defineLazy(inst._zod, "propValues", () => inst._zod.innerType._zod.propValues);
1659
- util.defineLazy(inst._zod, "optin", () => inst._zod.innerType._zod.optin);
1660
- util.defineLazy(inst._zod, "optout", () => inst._zod.innerType._zod.optout);
1666
+ util.defineLazy(inst._zod, "optin", () => inst._zod.innerType._zod.optin ?? undefined);
1667
+ util.defineLazy(inst._zod, "optout", () => inst._zod.innerType._zod.optout ?? undefined);
1661
1668
  inst._zod.parse = (payload, ctx) => {
1662
1669
  const inner = inst._zod.innerType;
1663
1670
  return inner._zod.run(payload, ctx);
package/v4/core/util.cjs CHANGED
@@ -14,6 +14,7 @@ exports.nullish = nullish;
14
14
  exports.cleanRegex = cleanRegex;
15
15
  exports.floatSafeRemainder = floatSafeRemainder;
16
16
  exports.defineLazy = defineLazy;
17
+ exports.objectClone = objectClone;
17
18
  exports.assignProp = assignProp;
18
19
  exports.mergeDefs = mergeDefs;
19
20
  exports.cloneDef = cloneDef;
@@ -107,16 +108,20 @@ function floatSafeRemainder(val, step) {
107
108
  const stepInt = Number.parseInt(step.toFixed(decCount).replace(".", ""));
108
109
  return (valInt % stepInt) / 10 ** decCount;
109
110
  }
111
+ const EVALUATING = Symbol("evaluating");
110
112
  function defineLazy(object, key, getter) {
111
- const set = false;
113
+ let value = undefined;
112
114
  Object.defineProperty(object, key, {
113
115
  get() {
114
- if (!set) {
115
- const value = getter();
116
- object[key] = value;
117
- return value;
116
+ if (value === EVALUATING) {
117
+ // Circular reference detected, return undefined to break the cycle
118
+ return undefined;
118
119
  }
119
- throw new Error("cached value already set");
120
+ if (value === undefined) {
121
+ value = EVALUATING;
122
+ value = getter();
123
+ }
124
+ return value;
120
125
  },
121
126
  set(v) {
122
127
  Object.defineProperty(object, key, {
@@ -128,6 +133,9 @@ function defineLazy(object, key, getter) {
128
133
  configurable: true,
129
134
  });
130
135
  }
136
+ function objectClone(obj) {
137
+ return Object.create(Object.getPrototypeOf(obj), Object.getOwnPropertyDescriptors(obj));
138
+ }
131
139
  function assignProp(target, prop, value) {
132
140
  Object.defineProperty(target, prop, {
133
141
  value,
@@ -120,6 +120,7 @@ export declare function nullish(input: any): boolean;
120
120
  export declare function cleanRegex(source: string): string;
121
121
  export declare function floatSafeRemainder(val: number, step: number): number;
122
122
  export declare function defineLazy<T, K extends keyof T>(object: T, key: K, getter: () => T[K]): void;
123
+ export declare function objectClone(obj: object): any;
123
124
  export declare function assignProp<T extends object, K extends PropertyKey>(target: T, prop: K, value: K extends keyof T ? T[K] : any): void;
124
125
  export declare function mergeDefs(...defs: Record<string, any>[]): any;
125
126
  export declare function cloneDef(schema: schemas.$ZodType): any;
package/v4/core/util.d.ts CHANGED
@@ -120,6 +120,7 @@ export declare function nullish(input: any): boolean;
120
120
  export declare function cleanRegex(source: string): string;
121
121
  export declare function floatSafeRemainder(val: number, step: number): number;
122
122
  export declare function defineLazy<T, K extends keyof T>(object: T, key: K, getter: () => T[K]): void;
123
+ export declare function objectClone(obj: object): any;
123
124
  export declare function assignProp<T extends object, K extends PropertyKey>(target: T, prop: K, value: K extends keyof T ? T[K] : any): void;
124
125
  export declare function mergeDefs(...defs: Record<string, any>[]): any;
125
126
  export declare function cloneDef(schema: schemas.$ZodType): any;
package/v4/core/util.js CHANGED
@@ -61,16 +61,20 @@ export function floatSafeRemainder(val, step) {
61
61
  const stepInt = Number.parseInt(step.toFixed(decCount).replace(".", ""));
62
62
  return (valInt % stepInt) / 10 ** decCount;
63
63
  }
64
+ const EVALUATING = Symbol("evaluating");
64
65
  export function defineLazy(object, key, getter) {
65
- const set = false;
66
+ let value = undefined;
66
67
  Object.defineProperty(object, key, {
67
68
  get() {
68
- if (!set) {
69
- const value = getter();
70
- object[key] = value;
71
- return value;
69
+ if (value === EVALUATING) {
70
+ // Circular reference detected, return undefined to break the cycle
71
+ return undefined;
72
72
  }
73
- throw new Error("cached value already set");
73
+ if (value === undefined) {
74
+ value = EVALUATING;
75
+ value = getter();
76
+ }
77
+ return value;
74
78
  },
75
79
  set(v) {
76
80
  Object.defineProperty(object, key, {
@@ -82,6 +86,9 @@ export function defineLazy(object, key, getter) {
82
86
  configurable: true,
83
87
  });
84
88
  }
89
+ export function objectClone(obj) {
90
+ return Object.create(Object.getPrototypeOf(obj), Object.getOwnPropertyDescriptors(obj));
91
+ }
85
92
  export function assignProp(target, prop, value) {
86
93
  Object.defineProperty(target, prop, {
87
94
  value,
@@ -4,5 +4,5 @@ exports.version = void 0;
4
4
  exports.version = {
5
5
  major: 4,
6
6
  minor: 0,
7
- patch: 13,
7
+ patch: 14,
8
8
  };
@@ -1,5 +1,5 @@
1
1
  export const version = {
2
2
  major: 4,
3
3
  minor: 0,
4
- patch: 13,
4
+ patch: 14,
5
5
  };