zod 4.6.1 → 4.6.3

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 (68) hide show
  1. package/README.md +2 -2
  2. package/package.json +1 -1
  3. package/src/v4/classic/checks.ts +1 -0
  4. package/src/v4/classic/schemas.ts +3 -25
  5. package/src/v4/classic/tests/cyclic-data.test.ts +2 -11
  6. package/src/v4/classic/tests/firstparty.test.ts +0 -4
  7. package/src/v4/classic/tests/instanceof.test.ts +1 -1
  8. package/src/v4/classic/tests/prefault.test.ts +70 -0
  9. package/src/v4/classic/tests/properties.test.ts +34 -137
  10. package/src/v4/core/api.ts +4 -7
  11. package/src/v4/core/checks.ts +61 -1
  12. package/src/v4/core/compile.ts +16 -24
  13. package/src/v4/core/json-schema-processors.ts +0 -50
  14. package/src/v4/core/memoizer.ts +2 -5
  15. package/src/v4/core/schemas.ts +10 -107
  16. package/src/v4/core/to-json-schema.ts +1 -1
  17. package/src/v4/core/util.ts +0 -4
  18. package/src/v4/core/versions.ts +1 -1
  19. package/src/v4/core/visit.ts +0 -11
  20. package/src/v4/mini/checks.ts +1 -0
  21. package/src/v4/mini/schemas.ts +1 -20
  22. package/src/v4/mini/tests/index.test.ts +22 -0
  23. package/v4/classic/checks.cjs +2 -1
  24. package/v4/classic/checks.d.cts +1 -1
  25. package/v4/classic/checks.d.ts +1 -1
  26. package/v4/classic/checks.js +1 -1
  27. package/v4/classic/schemas.cjs +2 -11
  28. package/v4/classic/schemas.d.cts +1 -6
  29. package/v4/classic/schemas.d.ts +1 -6
  30. package/v4/classic/schemas.js +1 -9
  31. package/v4/core/api.cjs +2 -3
  32. package/v4/core/api.d.cts +2 -2
  33. package/v4/core/api.d.ts +2 -2
  34. package/v4/core/api.js +2 -3
  35. package/v4/core/checks.cjs +32 -1
  36. package/v4/core/checks.d.cts +16 -0
  37. package/v4/core/checks.d.ts +16 -0
  38. package/v4/core/checks.js +31 -0
  39. package/v4/core/compile.cjs +12 -17
  40. package/v4/core/compile.js +12 -17
  41. package/v4/core/json-schema-processors.cjs +1 -34
  42. package/v4/core/json-schema-processors.d.cts +0 -1
  43. package/v4/core/json-schema-processors.d.ts +0 -1
  44. package/v4/core/json-schema-processors.js +1 -33
  45. package/v4/core/memoizer.cjs +2 -5
  46. package/v4/core/memoizer.js +2 -5
  47. package/v4/core/schemas.cjs +10 -70
  48. package/v4/core/schemas.d.cts +3 -20
  49. package/v4/core/schemas.d.ts +3 -20
  50. package/v4/core/schemas.js +9 -69
  51. package/v4/core/to-json-schema.cjs +0 -1
  52. package/v4/core/to-json-schema.d.cts +0 -3
  53. package/v4/core/to-json-schema.d.ts +0 -3
  54. package/v4/core/to-json-schema.js +1 -1
  55. package/v4/core/util.cjs +0 -4
  56. package/v4/core/util.js +0 -4
  57. package/v4/core/versions.cjs +1 -1
  58. package/v4/core/versions.js +1 -1
  59. package/v4/core/visit.cjs +0 -12
  60. package/v4/core/visit.js +0 -12
  61. package/v4/mini/checks.cjs +2 -1
  62. package/v4/mini/checks.d.cts +1 -1
  63. package/v4/mini/checks.d.ts +1 -1
  64. package/v4/mini/checks.js +1 -1
  65. package/v4/mini/schemas.cjs +1 -9
  66. package/v4/mini/schemas.d.cts +1 -5
  67. package/v4/mini/schemas.d.ts +1 -5
  68. package/v4/mini/schemas.js +0 -7
package/v4/core/api.d.cts CHANGED
@@ -216,8 +216,8 @@ export type $ZodCheckPropertyParams = CheckParams<checks.$ZodCheckProperty, "pro
216
216
  export declare function _property<K extends string, T extends schemas.$ZodType>(property: K, schema: T, params?: string | $ZodCheckPropertyParams): checks.$ZodCheckProperty<{
217
217
  [k in K]: util.Widen<core.input<T>>;
218
218
  }>;
219
- export type $ZodPropertiesParams = CheckTypeParams<schemas.$ZodProperties, "shape" | "when">;
220
- export declare function _properties<Shape extends schemas.$ZodShape>(Class: util.SchemaClass<schemas.$ZodProperties>, shape: Shape, params?: string | $ZodPropertiesParams): schemas.$ZodProperties<Shape>;
219
+ export type $ZodCheckPropertiesParams = CheckParams<checks.$ZodCheckProperties, "shape" | "when">;
220
+ export declare function _properties<Shape extends schemas.$ZodShape>(shape: Shape, params?: string | $ZodCheckPropertiesParams): checks.$ZodCheckProperties<Shape>;
221
221
  export type $ZodCheckMimeTypeParams = CheckParams<checks.$ZodCheckMimeType, "mime" | "when">;
222
222
  export declare function _mime(types: util.MimeTypes[], params?: string | $ZodCheckMimeTypeParams): checks.$ZodCheckMimeType;
223
223
  export declare function _overwrite<T>(tx: (input: T) => T): checks.$ZodCheckOverwrite<T>;
package/v4/core/api.d.ts CHANGED
@@ -216,8 +216,8 @@ export type $ZodCheckPropertyParams = CheckParams<checks.$ZodCheckProperty, "pro
216
216
  export declare function _property<K extends string, T extends schemas.$ZodType>(property: K, schema: T, params?: string | $ZodCheckPropertyParams): checks.$ZodCheckProperty<{
217
217
  [k in K]: util.Widen<core.input<T>>;
218
218
  }>;
219
- export type $ZodPropertiesParams = CheckTypeParams<schemas.$ZodProperties, "shape" | "when">;
220
- export declare function _properties<Shape extends schemas.$ZodShape>(Class: util.SchemaClass<schemas.$ZodProperties>, shape: Shape, params?: string | $ZodPropertiesParams): schemas.$ZodProperties<Shape>;
219
+ export type $ZodCheckPropertiesParams = CheckParams<checks.$ZodCheckProperties, "shape" | "when">;
220
+ export declare function _properties<Shape extends schemas.$ZodShape>(shape: Shape, params?: string | $ZodCheckPropertiesParams): checks.$ZodCheckProperties<Shape>;
221
221
  export type $ZodCheckMimeTypeParams = CheckParams<checks.$ZodCheckMimeType, "mime" | "when">;
222
222
  export declare function _mime(types: util.MimeTypes[], params?: string | $ZodCheckMimeTypeParams): checks.$ZodCheckMimeType;
223
223
  export declare function _overwrite<T>(tx: (input: T) => T): checks.$ZodCheckOverwrite<T>;
package/v4/core/api.js CHANGED
@@ -688,9 +688,8 @@ export function _property(property, schema, params) {
688
688
  });
689
689
  }
690
690
  // @__NO_SIDE_EFFECTS__
691
- export function _properties(Class, shape, params) {
692
- return new Class({
693
- type: "properties",
691
+ export function _properties(shape, params) {
692
+ return new checks.$ZodCheckProperties({
694
693
  check: "properties",
695
694
  shape,
696
695
  ...util.normalizeParams(params),
@@ -24,7 +24,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
24
24
  return result;
25
25
  };
26
26
  Object.defineProperty(exports, "__esModule", { value: true });
27
- exports.$ZodCheckOverwrite = exports.$ZodCheckMimeType = exports.$ZodCheckProperty = exports.$ZodCheckEndsWith = exports.$ZodCheckStartsWith = exports.$ZodCheckIncludes = exports.$ZodCheckUpperCase = exports.$ZodCheckLowerCase = exports.$ZodCheckRegex = exports.$ZodCheckStringFormat = exports.$ZodCheckLengthEquals = exports.$ZodCheckMinLength = exports.$ZodCheckMaxLength = exports.$ZodCheckSizeEquals = exports.$ZodCheckMinSize = exports.$ZodCheckMaxSize = exports.$ZodCheckBigIntFormat = exports.$ZodCheckNumberFormat = exports.$ZodCheckMultipleOf = exports.$ZodCheckGreaterThan = exports.$ZodCheckLessThan = exports.$ZodCheck = void 0;
27
+ exports.$ZodCheckOverwrite = exports.$ZodCheckMimeType = exports.$ZodCheckProperties = exports.$ZodCheckProperty = exports.$ZodCheckEndsWith = exports.$ZodCheckStartsWith = exports.$ZodCheckIncludes = exports.$ZodCheckUpperCase = exports.$ZodCheckLowerCase = exports.$ZodCheckRegex = exports.$ZodCheckStringFormat = exports.$ZodCheckLengthEquals = exports.$ZodCheckMinLength = exports.$ZodCheckMaxLength = exports.$ZodCheckSizeEquals = exports.$ZodCheckMinSize = exports.$ZodCheckMaxSize = exports.$ZodCheckBigIntFormat = exports.$ZodCheckNumberFormat = exports.$ZodCheckMultipleOf = exports.$ZodCheckGreaterThan = exports.$ZodCheckLessThan = exports.$ZodCheck = void 0;
28
28
  const core = __importStar(require("./core.cjs"));
29
29
  const regexes = __importStar(require("./regexes.cjs"));
30
30
  const util = __importStar(require("./util.cjs"));
@@ -488,6 +488,37 @@ exports.$ZodCheckProperty = core.$constructor("$ZodCheckProperty", (inst, def) =
488
488
  return;
489
489
  };
490
490
  });
491
+ exports.$ZodCheckProperties = core.$constructor("$ZodCheckProperties", (inst, def) => {
492
+ exports.$ZodCheck.init(inst, def);
493
+ util.hide(inst, Symbol.iterator, function* () {
494
+ yield inst;
495
+ });
496
+ // key and schema snapshotted together: reading one live and the other cached lets a later mutation of the caller's shape object pair a stale key with a missing schema
497
+ let entries;
498
+ inst._zod.check = (payload) => {
499
+ // the base schema already typed the value, so only a nullish one is rejected here: the properties read on a primitive too, matching z.property() on a string's length
500
+ if (payload.value == null) {
501
+ payload.issues.push({ expected: "object", code: "invalid_type", input: payload.value, inst });
502
+ return undefined;
503
+ }
504
+ entries ?? (entries = Reflect.ownKeys(def.shape).map((key) => [key, def.shape[key]]));
505
+ const input = payload.value;
506
+ let proms;
507
+ for (const [key, schema] of entries) {
508
+ const result = schema._zod.run({ value: input[key], issues: [] }, {});
509
+ if (result instanceof Promise) {
510
+ proms ?? (proms = []);
511
+ proms.push(result.then((result) => handleCheckPropertyResult(result, payload, key)));
512
+ }
513
+ else {
514
+ handleCheckPropertyResult(result, payload, key);
515
+ }
516
+ }
517
+ if (proms)
518
+ return Promise.all(proms).then(() => undefined);
519
+ return undefined;
520
+ };
521
+ });
491
522
  exports.$ZodCheckMimeType = core.$constructor("$ZodCheckMimeType", (inst, def) => {
492
523
  exports.$ZodCheck.init(inst, def);
493
524
  const mimeSet = new Set(def.mime);
@@ -250,6 +250,22 @@ export interface $ZodCheckProperty<T extends object = object> extends $ZodCheck<
250
250
  _zod: $ZodCheckPropertyInternals<T>;
251
251
  }
252
252
  export declare const $ZodCheckProperty: core.$constructor<$ZodCheckProperty>;
253
+ export interface $ZodCheckPropertiesDef<Shape extends schemas.$ZodShape = schemas.$ZodShape> extends $ZodCheckDef {
254
+ check: "properties";
255
+ shape: Shape;
256
+ }
257
+ export type $ZodCheckPropertiesInput<Shape extends schemas.$ZodShape = schemas.$ZodShape> = {
258
+ -readonly [k in keyof Shape]: util.Widen<core.input<Shape[k]>>;
259
+ };
260
+ export interface $ZodCheckPropertiesInternals<Shape extends schemas.$ZodShape = schemas.$ZodShape> extends $ZodCheckInternals<$ZodCheckPropertiesInput<Shape>> {
261
+ def: $ZodCheckPropertiesDef<Shape>;
262
+ issc: errors.$ZodIssue;
263
+ }
264
+ export interface $ZodCheckProperties<Shape extends schemas.$ZodShape = schemas.$ZodShape> extends $ZodCheck<$ZodCheckPropertiesInput<Shape>> {
265
+ _zod: $ZodCheckPropertiesInternals<Shape>;
266
+ [Symbol.iterator](): Iterator<this>;
267
+ }
268
+ export declare const $ZodCheckProperties: core.$constructor<$ZodCheckProperties>;
253
269
  export interface $ZodCheckMimeTypeDef extends $ZodCheckDef {
254
270
  check: "mime_type";
255
271
  mime: util.MimeTypes[];
@@ -250,6 +250,22 @@ export interface $ZodCheckProperty<T extends object = object> extends $ZodCheck<
250
250
  _zod: $ZodCheckPropertyInternals<T>;
251
251
  }
252
252
  export declare const $ZodCheckProperty: core.$constructor<$ZodCheckProperty>;
253
+ export interface $ZodCheckPropertiesDef<Shape extends schemas.$ZodShape = schemas.$ZodShape> extends $ZodCheckDef {
254
+ check: "properties";
255
+ shape: Shape;
256
+ }
257
+ export type $ZodCheckPropertiesInput<Shape extends schemas.$ZodShape = schemas.$ZodShape> = {
258
+ -readonly [k in keyof Shape]: util.Widen<core.input<Shape[k]>>;
259
+ };
260
+ export interface $ZodCheckPropertiesInternals<Shape extends schemas.$ZodShape = schemas.$ZodShape> extends $ZodCheckInternals<$ZodCheckPropertiesInput<Shape>> {
261
+ def: $ZodCheckPropertiesDef<Shape>;
262
+ issc: errors.$ZodIssue;
263
+ }
264
+ export interface $ZodCheckProperties<Shape extends schemas.$ZodShape = schemas.$ZodShape> extends $ZodCheck<$ZodCheckPropertiesInput<Shape>> {
265
+ _zod: $ZodCheckPropertiesInternals<Shape>;
266
+ [Symbol.iterator](): Iterator<this>;
267
+ }
268
+ export declare const $ZodCheckProperties: core.$constructor<$ZodCheckProperties>;
253
269
  export interface $ZodCheckMimeTypeDef extends $ZodCheckDef {
254
270
  check: "mime_type";
255
271
  mime: util.MimeTypes[];
package/v4/core/checks.js CHANGED
@@ -462,6 +462,37 @@ export const $ZodCheckProperty = /*@__PURE__*/ core.$constructor("$ZodCheckPrope
462
462
  return;
463
463
  };
464
464
  });
465
+ export const $ZodCheckProperties = /*@__PURE__*/ core.$constructor("$ZodCheckProperties", (inst, def) => {
466
+ $ZodCheck.init(inst, def);
467
+ util.hide(inst, Symbol.iterator, function* () {
468
+ yield inst;
469
+ });
470
+ // key and schema snapshotted together: reading one live and the other cached lets a later mutation of the caller's shape object pair a stale key with a missing schema
471
+ let entries;
472
+ inst._zod.check = (payload) => {
473
+ // the base schema already typed the value, so only a nullish one is rejected here: the properties read on a primitive too, matching z.property() on a string's length
474
+ if (payload.value == null) {
475
+ payload.issues.push({ expected: "object", code: "invalid_type", input: payload.value, inst });
476
+ return undefined;
477
+ }
478
+ entries ?? (entries = Reflect.ownKeys(def.shape).map((key) => [key, def.shape[key]]));
479
+ const input = payload.value;
480
+ let proms;
481
+ for (const [key, schema] of entries) {
482
+ const result = schema._zod.run({ value: input[key], issues: [] }, {});
483
+ if (result instanceof Promise) {
484
+ proms ?? (proms = []);
485
+ proms.push(result.then((result) => handleCheckPropertyResult(result, payload, key)));
486
+ }
487
+ else {
488
+ handleCheckPropertyResult(result, payload, key);
489
+ }
490
+ }
491
+ if (proms)
492
+ return Promise.all(proms).then(() => undefined);
493
+ return undefined;
494
+ };
495
+ });
465
496
  export const $ZodCheckMimeType = /*@__PURE__*/ core.$constructor("$ZodCheckMimeType", (inst, def) => {
466
497
  $ZodCheck.init(inst, def);
467
498
  const mimeSet = new Set(def.mime);
@@ -361,7 +361,7 @@ function generateChecks(doc, ctx, schema, accessor) {
361
361
  generatePropertyCheck(doc, ctx, def, currentAccessor);
362
362
  break;
363
363
  case "properties":
364
- generatePropertiesChecks(doc, ctx, def, currentAccessor, false);
364
+ generatePropertiesChecks(doc, ctx, def, currentAccessor);
365
365
  break;
366
366
  case "overwrite": {
367
367
  // Overwrite transforms the value - create new variable for transformed result
@@ -489,15 +489,13 @@ function generateMimeTypeCheck(doc, ctx, def, accessor) {
489
489
  }
490
490
  }
491
491
  // asserts each named property in place; children compile assert-only because z.properties never rebuilds its input
492
- function generatePropertiesChecks(doc, ctx, def, accessor, schemaRole) {
493
- // a custom `when` gates the assertion at runtime; inside a union a wrongly-run branch is absorbed as a branch failure rather than falling back, so refuse at codegen the way the check role does
492
+ function generatePropertiesChecks(doc, ctx, def, accessor) {
493
+ // a custom `when` gates the assertion at runtime; inside a union a wrongly-run branch is absorbed as a branch failure rather than falling back, so refuse at codegen
494
494
  if (def.when) {
495
495
  throw new ZodCompileUnsupportedError(`check with a custom "when" condition`);
496
496
  }
497
- // matches the runtime gate for whichever role this is: a schema rejects a primitive outright, a check only a nullish value
498
- doc.write(schemaRole
499
- ? `if (${accessor} === null || (typeof ${accessor} !== "object" && typeof ${accessor} !== "function")) return INVALID;`
500
- : `if (${accessor} == null) return INVALID;`);
497
+ // matches the runtime gate: the base schema already typed the value, so only a nullish one is rejected
498
+ doc.write(`if (${accessor} == null) return INVALID;`);
501
499
  const shape = def.shape;
502
500
  for (const key of Reflect.ownKeys(shape)) {
503
501
  // a symbol has no source literal, so it is hoisted as a constant
@@ -848,10 +846,6 @@ function generateCheck(doc, ctx, schema, accessor, needsValue = true) {
848
846
  case "custom":
849
847
  typeAccessor = generateCustomCheck(doc, ctx, schema, accessor);
850
848
  break;
851
- case "properties":
852
- generatePropertiesChecks(doc, ctx, schema._zod.def, accessor, true);
853
- typeAccessor = accessor;
854
- break;
855
849
  case "transform":
856
850
  typeAccessor = generateTransformCheck(doc, ctx, schema, accessor);
857
851
  break;
@@ -1010,9 +1004,9 @@ function generateObjectCheck(doc, ctx, schema, accessor, buildsValue = true) {
1010
1004
  }
1011
1005
  }
1012
1006
  // else: strip mode (no catchall) - unknown keys ignored, only include known keys
1013
- // Shape keys in declared order, then unknown keys in for...in order. A middle-rung key is included iff present on the input, else iff its output is not undefined.
1007
+ // defaulted required outputs keep their keys even when undefined
1014
1008
  const outputVar = newVar(ctx);
1015
- const hasConditionalKeys = allKeys.some((k) => mayOutputUndefined(propShape[k]) || dropsWhenAbsent(propShape[k]));
1009
+ const hasConditionalKeys = allKeys.some((k) => mayOmitUndefined(propShape[k]) || dropsWhenAbsent(propShape[k]));
1016
1010
  // Assert mode: every declared key is validated above, so the output literal and the unknown-key copy are pure waste. A `never` catchall already emitted its rejection loop; a schema catchall still has to validate the values it would otherwise have stored.
1017
1011
  if (!buildsValue) {
1018
1012
  if (unknownKeysMode === "schema") {
@@ -1042,7 +1036,7 @@ function generateObjectCheck(doc, ctx, schema, accessor, buildsValue = true) {
1042
1036
  if (dropsWhenAbsent(propShape[k])) {
1043
1037
  doc.write(`if (${kx} in ${accessor}) ${outputVar}[${kx}] = ${out};`);
1044
1038
  }
1045
- else if (mayOutputUndefined(propShape[k])) {
1039
+ else if (mayOmitUndefined(propShape[k])) {
1046
1040
  doc.write(`if (${out} !== undefined || ${kx} in ${accessor}) ${outputVar}[${kx}] = ${out};`);
1047
1041
  }
1048
1042
  else {
@@ -1185,9 +1179,10 @@ function fastPathAcceptsAbsence(schema) {
1185
1179
  function dropsWhenAbsent(schema) {
1186
1180
  return schema._zod.optin === "optional" && schema._zod.optout === "optional";
1187
1181
  }
1188
- // Whether a schema's success-path output can be `undefined`. Object output
1189
- // assembly gives such props the runtime's value-or-presence inclusion rule;
1190
- // everything else keeps the unconditional object-literal slot.
1182
+ function mayOmitUndefined(schema) {
1183
+ return (schema._zod.optin !== "defaulted" || schema._zod.optout === "optional") && mayOutputUndefined(schema);
1184
+ }
1185
+ // whether a schema's success-path output can be undefined
1191
1186
  function mayOutputUndefined(schema) {
1192
1187
  const def = schema._zod.def;
1193
1188
  switch (def.type) {
@@ -330,7 +330,7 @@ function generateChecks(doc, ctx, schema, accessor) {
330
330
  generatePropertyCheck(doc, ctx, def, currentAccessor);
331
331
  break;
332
332
  case "properties":
333
- generatePropertiesChecks(doc, ctx, def, currentAccessor, false);
333
+ generatePropertiesChecks(doc, ctx, def, currentAccessor);
334
334
  break;
335
335
  case "overwrite": {
336
336
  // Overwrite transforms the value - create new variable for transformed result
@@ -458,15 +458,13 @@ function generateMimeTypeCheck(doc, ctx, def, accessor) {
458
458
  }
459
459
  }
460
460
  // asserts each named property in place; children compile assert-only because z.properties never rebuilds its input
461
- function generatePropertiesChecks(doc, ctx, def, accessor, schemaRole) {
462
- // a custom `when` gates the assertion at runtime; inside a union a wrongly-run branch is absorbed as a branch failure rather than falling back, so refuse at codegen the way the check role does
461
+ function generatePropertiesChecks(doc, ctx, def, accessor) {
462
+ // a custom `when` gates the assertion at runtime; inside a union a wrongly-run branch is absorbed as a branch failure rather than falling back, so refuse at codegen
463
463
  if (def.when) {
464
464
  throw new ZodCompileUnsupportedError(`check with a custom "when" condition`);
465
465
  }
466
- // matches the runtime gate for whichever role this is: a schema rejects a primitive outright, a check only a nullish value
467
- doc.write(schemaRole
468
- ? `if (${accessor} === null || (typeof ${accessor} !== "object" && typeof ${accessor} !== "function")) return INVALID;`
469
- : `if (${accessor} == null) return INVALID;`);
466
+ // matches the runtime gate: the base schema already typed the value, so only a nullish one is rejected
467
+ doc.write(`if (${accessor} == null) return INVALID;`);
470
468
  const shape = def.shape;
471
469
  for (const key of Reflect.ownKeys(shape)) {
472
470
  // a symbol has no source literal, so it is hoisted as a constant
@@ -817,10 +815,6 @@ function generateCheck(doc, ctx, schema, accessor, needsValue = true) {
817
815
  case "custom":
818
816
  typeAccessor = generateCustomCheck(doc, ctx, schema, accessor);
819
817
  break;
820
- case "properties":
821
- generatePropertiesChecks(doc, ctx, schema._zod.def, accessor, true);
822
- typeAccessor = accessor;
823
- break;
824
818
  case "transform":
825
819
  typeAccessor = generateTransformCheck(doc, ctx, schema, accessor);
826
820
  break;
@@ -979,9 +973,9 @@ function generateObjectCheck(doc, ctx, schema, accessor, buildsValue = true) {
979
973
  }
980
974
  }
981
975
  // else: strip mode (no catchall) - unknown keys ignored, only include known keys
982
- // Shape keys in declared order, then unknown keys in for...in order. A middle-rung key is included iff present on the input, else iff its output is not undefined.
976
+ // defaulted required outputs keep their keys even when undefined
983
977
  const outputVar = newVar(ctx);
984
- const hasConditionalKeys = allKeys.some((k) => mayOutputUndefined(propShape[k]) || dropsWhenAbsent(propShape[k]));
978
+ const hasConditionalKeys = allKeys.some((k) => mayOmitUndefined(propShape[k]) || dropsWhenAbsent(propShape[k]));
985
979
  // Assert mode: every declared key is validated above, so the output literal and the unknown-key copy are pure waste. A `never` catchall already emitted its rejection loop; a schema catchall still has to validate the values it would otherwise have stored.
986
980
  if (!buildsValue) {
987
981
  if (unknownKeysMode === "schema") {
@@ -1011,7 +1005,7 @@ function generateObjectCheck(doc, ctx, schema, accessor, buildsValue = true) {
1011
1005
  if (dropsWhenAbsent(propShape[k])) {
1012
1006
  doc.write(`if (${kx} in ${accessor}) ${outputVar}[${kx}] = ${out};`);
1013
1007
  }
1014
- else if (mayOutputUndefined(propShape[k])) {
1008
+ else if (mayOmitUndefined(propShape[k])) {
1015
1009
  doc.write(`if (${out} !== undefined || ${kx} in ${accessor}) ${outputVar}[${kx}] = ${out};`);
1016
1010
  }
1017
1011
  else {
@@ -1154,9 +1148,10 @@ function fastPathAcceptsAbsence(schema) {
1154
1148
  function dropsWhenAbsent(schema) {
1155
1149
  return schema._zod.optin === "optional" && schema._zod.optout === "optional";
1156
1150
  }
1157
- // Whether a schema's success-path output can be `undefined`. Object output
1158
- // assembly gives such props the runtime's value-or-presence inclusion rule;
1159
- // everything else keeps the unconditional object-literal slot.
1151
+ function mayOmitUndefined(schema) {
1152
+ return (schema._zod.optin !== "defaulted" || schema._zod.optout === "optional") && mayOutputUndefined(schema);
1153
+ }
1154
+ // whether a schema's success-path output can be undefined
1160
1155
  function mayOutputUndefined(schema) {
1161
1156
  const def = schema._zod.def;
1162
1157
  switch (def.type) {
@@ -23,7 +23,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
23
23
  return result;
24
24
  };
25
25
  Object.defineProperty(exports, "__esModule", { value: true });
26
- exports.allProcessors = exports.lazyProcessor = exports.optionalProcessor = exports.promiseProcessor = exports.readonlyProcessor = exports.pipeProcessor = exports.catchProcessor = exports.prefaultProcessor = exports.defaultProcessor = exports.nonoptionalProcessor = exports.nullableProcessor = exports.recordProcessor = exports.tupleProcessor = exports.intersectionProcessor = exports.unionProcessor = exports.propertiesProcessor = exports.objectProcessor = exports.arrayProcessor = exports.setProcessor = exports.mapProcessor = exports.transformProcessor = exports.functionProcessor = exports.customProcessor = exports.successProcessor = exports.fileProcessor = exports.templateLiteralProcessor = exports.nanProcessor = exports.literalProcessor = exports.enumProcessor = exports.dateProcessor = exports.unknownProcessor = exports.anyProcessor = exports.neverProcessor = exports.voidProcessor = exports.undefinedProcessor = exports.nullProcessor = exports.symbolProcessor = exports.bigintProcessor = exports.booleanProcessor = exports.numberProcessor = exports.stringProcessor = void 0;
26
+ exports.allProcessors = exports.lazyProcessor = exports.optionalProcessor = exports.promiseProcessor = exports.readonlyProcessor = exports.pipeProcessor = exports.catchProcessor = exports.prefaultProcessor = exports.defaultProcessor = exports.nonoptionalProcessor = exports.nullableProcessor = exports.recordProcessor = exports.tupleProcessor = exports.intersectionProcessor = exports.unionProcessor = exports.objectProcessor = exports.arrayProcessor = exports.setProcessor = exports.mapProcessor = exports.transformProcessor = exports.functionProcessor = exports.customProcessor = exports.successProcessor = exports.fileProcessor = exports.templateLiteralProcessor = exports.nanProcessor = exports.literalProcessor = exports.enumProcessor = exports.dateProcessor = exports.unknownProcessor = exports.anyProcessor = exports.neverProcessor = exports.voidProcessor = exports.undefinedProcessor = exports.nullProcessor = exports.symbolProcessor = exports.bigintProcessor = exports.booleanProcessor = exports.numberProcessor = exports.stringProcessor = void 0;
27
27
  exports.aggregateChecks = aggregateChecks;
28
28
  exports.toJSONSchema = toJSONSchema;
29
29
  const regexes = __importStar(require("./regexes.cjs"));
@@ -478,38 +478,6 @@ const objectProcessor = (schema, ctx, _json, params) => {
478
478
  }
479
479
  };
480
480
  exports.objectProcessor = objectProcessor;
481
- // asserts named properties in place and passes everything else through, so no additionalProperties constraint is emitted
482
- const propertiesProcessor = (schema, ctx, _json, params) => {
483
- const json = _json;
484
- const def = schema._zod.def;
485
- // dropping a symbol key silently would emit a schema that asserts less than this one does
486
- if (Object.getOwnPropertySymbols(def.shape).length &&
487
- (0, to_json_schema_js_1.handleUnrepresentable)(schema, ctx, json, params, "Symbol keys cannot be represented in JSON Schema")) {
488
- return;
489
- }
490
- // the parsed value is the input, so an output-mode emission would describe a transformed value this schema never returns
491
- if (ctx.io === "output") {
492
- for (const key in def.shape) {
493
- if ((0, to_json_schema_js_1.isTransforming)(def.shape[key]) &&
494
- (0, to_json_schema_js_1.handleUnrepresentable)(schema, ctx, json, params, `z.properties() returns its input, so the output of a transforming schema at key "${key}" cannot be represented in JSON Schema`)) {
495
- return;
496
- }
497
- }
498
- }
499
- json.type = "object";
500
- json.properties = {};
501
- for (const key in def.shape) {
502
- (0, util_js_1.assignProp)(json.properties, key, (0, to_json_schema_js_1.processSchema)(def.shape[key], ctx, {
503
- ...params,
504
- path: [...params.path, "properties", key],
505
- }));
506
- }
507
- // input-side optionality in both modes: the parsed value is the input, so a defaulted key that stays absent must not be required of the output either
508
- const required = Object.keys(def.shape).filter((key) => inputOptin(def.shape[key]) === undefined);
509
- if (required.length > 0)
510
- json.required = required;
511
- };
512
- exports.propertiesProcessor = propertiesProcessor;
513
481
  const unionProcessor = (schema, ctx, json, params) => {
514
482
  const def = schema._zod.def;
515
483
  // Exclusive unions (inclusive === false) use oneOf (exactly one match) instead of anyOf (one or more matches). This includes both z.xor() and discriminated unions
@@ -883,7 +851,6 @@ exports.allProcessors = {
883
851
  file: exports.fileProcessor,
884
852
  success: exports.successProcessor,
885
853
  custom: exports.customProcessor,
886
- properties: exports.propertiesProcessor,
887
854
  function: exports.functionProcessor,
888
855
  transform: exports.transformProcessor,
889
856
  map: exports.mapProcessor,
@@ -41,7 +41,6 @@ export declare const mapProcessor: Processor<schemas.$ZodMap>;
41
41
  export declare const setProcessor: Processor<schemas.$ZodSet>;
42
42
  export declare const arrayProcessor: Processor<schemas.$ZodArray>;
43
43
  export declare const objectProcessor: Processor<schemas.$ZodObject>;
44
- export declare const propertiesProcessor: Processor<schemas.$ZodProperties>;
45
44
  export declare const unionProcessor: Processor<schemas.$ZodUnion>;
46
45
  export declare const intersectionProcessor: Processor<schemas.$ZodIntersection>;
47
46
  export declare const tupleProcessor: Processor<schemas.$ZodTuple>;
@@ -41,7 +41,6 @@ export declare const mapProcessor: Processor<schemas.$ZodMap>;
41
41
  export declare const setProcessor: Processor<schemas.$ZodSet>;
42
42
  export declare const arrayProcessor: Processor<schemas.$ZodArray>;
43
43
  export declare const objectProcessor: Processor<schemas.$ZodObject>;
44
- export declare const propertiesProcessor: Processor<schemas.$ZodProperties>;
45
44
  export declare const unionProcessor: Processor<schemas.$ZodUnion>;
46
45
  export declare const intersectionProcessor: Processor<schemas.$ZodIntersection>;
47
46
  export declare const tupleProcessor: Processor<schemas.$ZodTuple>;
@@ -1,6 +1,6 @@
1
1
  import * as regexes from "./regexes.js";
2
2
  import { base64Charset, base64urlCharset } from "./schemas.js";
3
- import { extractDefs, finalize, handleUnrepresentable, initializeContext, isTransforming, processSchema, } from "./to-json-schema.js";
3
+ import { extractDefs, finalize, handleUnrepresentable, initializeContext, processSchema, } from "./to-json-schema.js";
4
4
  import { BIGINT_FORMAT_RANGES, NUMBER_FORMAT_RANGES, assignProp, getEnumValues } from "./util.js";
5
5
  const narrowMin = (agg, key, value) => {
6
6
  if (agg[key] === undefined || value > agg[key])
@@ -425,37 +425,6 @@ export const objectProcessor = (schema, ctx, _json, params) => {
425
425
  });
426
426
  }
427
427
  };
428
- // asserts named properties in place and passes everything else through, so no additionalProperties constraint is emitted
429
- export const propertiesProcessor = (schema, ctx, _json, params) => {
430
- const json = _json;
431
- const def = schema._zod.def;
432
- // dropping a symbol key silently would emit a schema that asserts less than this one does
433
- if (Object.getOwnPropertySymbols(def.shape).length &&
434
- handleUnrepresentable(schema, ctx, json, params, "Symbol keys cannot be represented in JSON Schema")) {
435
- return;
436
- }
437
- // the parsed value is the input, so an output-mode emission would describe a transformed value this schema never returns
438
- if (ctx.io === "output") {
439
- for (const key in def.shape) {
440
- if (isTransforming(def.shape[key]) &&
441
- handleUnrepresentable(schema, ctx, json, params, `z.properties() returns its input, so the output of a transforming schema at key "${key}" cannot be represented in JSON Schema`)) {
442
- return;
443
- }
444
- }
445
- }
446
- json.type = "object";
447
- json.properties = {};
448
- for (const key in def.shape) {
449
- assignProp(json.properties, key, processSchema(def.shape[key], ctx, {
450
- ...params,
451
- path: [...params.path, "properties", key],
452
- }));
453
- }
454
- // input-side optionality in both modes: the parsed value is the input, so a defaulted key that stays absent must not be required of the output either
455
- const required = Object.keys(def.shape).filter((key) => inputOptin(def.shape[key]) === undefined);
456
- if (required.length > 0)
457
- json.required = required;
458
- };
459
428
  export const unionProcessor = (schema, ctx, json, params) => {
460
429
  const def = schema._zod.def;
461
430
  // Exclusive unions (inclusive === false) use oneOf (exactly one match) instead of anyOf (one or more matches). This includes both z.xor() and discriminated unions
@@ -815,7 +784,6 @@ export const allProcessors = {
815
784
  file: fileProcessor,
816
785
  success: successProcessor,
817
786
  custom: customProcessor,
818
- properties: propertiesProcessor,
819
787
  function: functionProcessor,
820
788
  transform: transformProcessor,
821
789
  map: mapProcessor,
@@ -38,9 +38,9 @@ exports.$ZodCyclicError = $ZodCyclicError;
38
38
  /** Keyed off the context object every schema in one parse call already shares. */
39
39
  const STATE = "~memo";
40
40
  const NO_ISSUES = [];
41
- // a value a cycle can close through; callables count, since z.properties asserts on one
41
+ // a value a cycle can close through
42
42
  function isRef(value) {
43
- return value !== null && (typeof value === "object" || typeof value === "function");
43
+ return value !== null && typeof value === "object";
44
44
  }
45
45
  // Receivers prefix paths in place, so the cache and every hand-out need their own copies.
46
46
  function cloneIssues(issues) {
@@ -97,9 +97,6 @@ function isRecursive(inst, stack, resolve) {
97
97
  check(def.catchall);
98
98
  break;
99
99
  }
100
- case "properties":
101
- merge(shape(def.shape, false));
102
- break;
103
100
  case "array":
104
101
  check(def.element);
105
102
  break;
@@ -8,9 +8,9 @@ export class $ZodCyclicError extends Error {
8
8
  /** Keyed off the context object every schema in one parse call already shares. */
9
9
  const STATE = "~memo";
10
10
  const NO_ISSUES = [];
11
- // a value a cycle can close through; callables count, since z.properties asserts on one
11
+ // a value a cycle can close through
12
12
  function isRef(value) {
13
- return value !== null && (typeof value === "object" || typeof value === "function");
13
+ return value !== null && typeof value === "object";
14
14
  }
15
15
  // Receivers prefix paths in place, so the cache and every hand-out need their own copies.
16
16
  function cloneIssues(issues) {
@@ -67,9 +67,6 @@ function isRecursive(inst, stack, resolve) {
67
67
  check(def.catchall);
68
68
  break;
69
69
  }
70
- case "properties":
71
- merge(shape(def.shape, false));
72
- break;
73
70
  case "array":
74
71
  check(def.element);
75
72
  break;
@@ -24,7 +24,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
24
24
  };
25
25
  Object.defineProperty(exports, "__esModule", { value: true });
26
26
  exports.$ZodObject = exports.$ZodArray = exports.$ZodDate = exports.$ZodVoid = exports.$ZodNever = exports.$ZodUnknown = exports.$ZodAny = exports.$ZodNull = exports.$ZodUndefined = exports.$ZodSymbol = exports.$ZodBigIntFormat = exports.$ZodBigInt = exports.$ZodBoolean = exports.$ZodNumberFormat = exports.$ZodNumber = exports.$ZodCustomStringFormat = exports.$ZodJWT = exports.$ZodIBAN = exports.$ZodCreditCard = exports.$ZodE164 = exports.$ZodBase64URL = exports.base64urlCharset = exports.$ZodBase64 = exports.base64Charset = exports.$ZodCIDRv6 = exports.$ZodCIDRv4 = exports.$ZodMAC = exports.$ZodIPv6 = exports.$ZodIPv4 = exports.$ZodISODuration = exports.$ZodISOTime = exports.$ZodISODate = exports.$ZodISODateTime = exports.$ZodKSUID = exports.$ZodXID = exports.$ZodULID = exports.$ZodCUID2 = exports.$ZodCUID = exports.$ZodNanoID = exports.$ZodEmoji = exports.$ZodURL = exports.URL_UNPARSEABLE = exports.URL_BAD_FORMAT = exports.$ZodEmail = exports.$ZodUUID = exports.$ZodGUID = exports.$ZodStringFormat = exports.$ZodString = exports.clone = exports.$ZodType = void 0;
27
- exports.$ZodProperties = exports.$ZodCustom = exports.$ZodLazy = exports.$ZodPromise = exports.$ZodFunction = exports.$ZodTemplateLiteral = exports.$ZodReadonly = exports.$ZodPreprocess = exports.$ZodCodec = exports.$ZodPipe = exports.$ZodNaN = exports.$ZodCatch = exports.$ZodSuccess = exports.$ZodNonOptional = exports.$ZodPrefault = exports.$ZodDefault = exports.$ZodNullable = exports.$ZodExactOptional = exports.$ZodOptional = exports.$ZodTransform = exports.$ZodFile = exports.$ZodLiteral = exports.$ZodEnum = exports.$ZodSet = exports.$ZodMap = exports.$ZodRecord = exports.$ZodTuple = exports.$ZodIntersection = exports.$ZodDiscriminatedUnion = exports.$ZodXor = exports.$ZodUnion = exports.$ZodObjectJIT = void 0;
27
+ exports.$ZodCustom = exports.$ZodLazy = exports.$ZodPromise = exports.$ZodFunction = exports.$ZodTemplateLiteral = exports.$ZodReadonly = exports.$ZodPreprocess = exports.$ZodCodec = exports.$ZodPipe = exports.$ZodNaN = exports.$ZodCatch = exports.$ZodSuccess = exports.$ZodNonOptional = exports.$ZodPrefault = exports.$ZodDefault = exports.$ZodNullable = exports.$ZodExactOptional = exports.$ZodOptional = exports.$ZodTransform = exports.$ZodFile = exports.$ZodLiteral = exports.$ZodEnum = exports.$ZodSet = exports.$ZodMap = exports.$ZodRecord = exports.$ZodTuple = exports.$ZodIntersection = exports.$ZodDiscriminatedUnion = exports.$ZodXor = exports.$ZodUnion = exports.$ZodObjectJIT = void 0;
28
28
  exports.standardProps = standardProps;
29
29
  exports.parseURLObject = parseURLObject;
30
30
  exports.stripTabAndNewline = stripTabAndNewline;
@@ -911,7 +911,7 @@ function handlePropertyResult(result, final, key, input, optin, optout) {
911
911
  return;
912
912
  }
913
913
  if (result.value === undefined) {
914
- if (isPresent) {
914
+ if (isPresent || (optin === "defaulted" && !isOptionalOut)) {
915
915
  final.value[key] = undefined;
916
916
  }
917
917
  }
@@ -1166,16 +1166,17 @@ exports.$ZodObjectJIT = core.$constructor("$ZodObjectJIT", (inst, def) => {
1166
1166
  doc.write(`
1167
1167
  if (${id}.issues.length) {${prefixStr(id, k)}
1168
1168
  }
1169
-
1170
- if (${id}.value === undefined) {
1171
- if (${isPresent}) {
1172
- newResult[${k}] = undefined;
1173
- }
1174
- } else {
1169
+ `);
1170
+ if (optin === "defaulted") {
1171
+ doc.write(`newResult[${k}] = ${id}.value;`);
1172
+ }
1173
+ else {
1174
+ doc.write(`
1175
+ if (${id}.value !== undefined || ${isPresent}) {
1175
1176
  newResult[${k}] = ${id}.value;
1176
1177
  }
1177
-
1178
1178
  `);
1179
+ }
1179
1180
  }
1180
1181
  }
1181
1182
  doc.write(`payload.value = newResult;`);
@@ -2626,67 +2627,6 @@ function handleRefineResult(result, payload, input, inst) {
2626
2627
  payload.issues.push(util.issue(_iss));
2627
2628
  }
2628
2629
  }
2629
- // asserts in place: the child result's value is discarded, matching z.property(), because a nested object or array schema rebuilds its output even when nothing transformed
2630
- function handlePropertiesResult(result, payload, key) {
2631
- if (result.issues.length) {
2632
- payload.issues.push(...util.prefixIssues(key, result.issues));
2633
- }
2634
- }
2635
- exports.$ZodProperties = core.$constructor("$ZodProperties", (inst, def) => {
2636
- // $ZodType.init prepends an instance that already carries the $ZodCheck trait to its own `checks`, which would run the shape a second time and cost the parse context. Initializing the check trait after it keeps the schema role in `parse`, where the context arrives.
2637
- exports.$ZodType.init(inst, def);
2638
- checks.$ZodCheck.init(inst, def);
2639
- const memo = core.globalConfig.memoizer;
2640
- memo?.attach(inst);
2641
- // key and schema snapshotted together: reading one live and the other cached lets a later mutation of the caller's shape object pair a stale key with a missing schema
2642
- let entries;
2643
- const runShape = (payload, ctx) => {
2644
- entries ?? (entries = Reflect.ownKeys(def.shape).map((key) => [key, def.shape[key]]));
2645
- const input = payload.value;
2646
- let proms;
2647
- for (const [key, schema] of entries) {
2648
- const result = schema._zod.run({ value: input[key], issues: [] }, ctx);
2649
- if (result instanceof Promise) {
2650
- proms ?? (proms = []);
2651
- proms.push(result.then((result) => handlePropertiesResult(result, payload, key)));
2652
- }
2653
- else {
2654
- handlePropertiesResult(result, payload, key);
2655
- }
2656
- }
2657
- if (proms)
2658
- return Promise.all(proms).then(() => undefined);
2659
- return undefined;
2660
- };
2661
- inst._zod.parse = (payload, ctx) => {
2662
- const input = payload.value;
2663
- // as a schema this is the type gate, and it infers an object shape, so a primitive is a type error. A function passes: its properties read like any other object's, and z.instanceof allows one.
2664
- if (input === null || (typeof input !== "object" && typeof input !== "function")) {
2665
- payload.issues.push({ expected: "object", code: "invalid_type", input, inst });
2666
- return payload;
2667
- }
2668
- // both sides declare the shape's input type, so the assertion runs forward in either direction; encoding the children backward would reject the very type this schema claims to take
2669
- if (ctx.direction === "backward")
2670
- ctx = { ...ctx, direction: "forward" };
2671
- // the input is its own output here, so it registers as its own memo entry: a cycle re-entering this node hits the bucket instead of recursing forever
2672
- if (memo)
2673
- memo.alloc(inst, payload, input, ctx);
2674
- const result = runShape(payload, ctx);
2675
- return result instanceof Promise ? result.then(() => payload) : payload;
2676
- };
2677
- // as a check the base schema already typed the value, so this only asserts the properties — which read on a primitive too, matching z.property() on a string's length. It gets no context of its own, so a cycle through a spread schema is not tracked.
2678
- inst._zod.check = (payload) => {
2679
- if (payload.value == null) {
2680
- payload.issues.push({ expected: "object", code: "invalid_type", input: payload.value, inst });
2681
- return undefined;
2682
- }
2683
- return runShape(payload, {});
2684
- };
2685
- }, {
2686
- *[Symbol.iterator]() {
2687
- yield this;
2688
- },
2689
- });
2690
2630
 
2691
2631
  // seal-cjs-exports
2692
2632
  (function () {