@es-joy/jsoe 0.26.0 → 0.27.0

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 (130) hide show
  1. package/.gitignore +10 -0
  2. package/.npmignore +9 -0
  3. package/CHANGES.md +53 -0
  4. package/README.md +3 -3
  5. package/badges/coverage-badge.svg +1 -1
  6. package/dist/formats/schema.d.ts.map +1 -1
  7. package/dist/fundamentalTypes/arrayReferenceType.d.ts.map +1 -1
  8. package/dist/fundamentalTypes/arrayType.d.ts.map +1 -1
  9. package/dist/fundamentalTypes/regexpType.d.ts.map +1 -1
  10. package/dist/fundamentalTypes/stringType.d.ts.map +1 -1
  11. package/dist/index.js +2 -2
  12. package/dist/index.js.map +1 -1
  13. package/dist/typeChoices.d.ts.map +1 -1
  14. package/dist/types.d.ts +12 -3
  15. package/dist/types.d.ts.map +1 -1
  16. package/eslint.config.js +36 -26
  17. package/package.json +13 -11
  18. package/pnpm-workspace.yaml +3 -2
  19. package/src/formatAndTypeChoices.js +9 -9
  20. package/src/formats/schema.js +70 -19
  21. package/src/fundamentalTypes/arrayReferenceType.js +3 -2
  22. package/src/fundamentalTypes/arrayType.js +34 -9
  23. package/src/fundamentalTypes/regexpType.js +9 -1
  24. package/src/fundamentalTypes/stringType.js +5 -0
  25. package/src/typeChoices.js +17 -8
  26. package/src/types.js +19 -8
  27. package/vendor/typeson-registry/dist/index.js +83 -10
  28. package/vendor/zod/classic/checks.d.ts +1 -1
  29. package/vendor/zod/classic/checks.js +1 -1
  30. package/vendor/zod/classic/external.d.ts +1 -1
  31. package/vendor/zod/classic/external.js +1 -1
  32. package/vendor/zod/classic/from-json-schema.js +245 -24
  33. package/vendor/zod/classic/schemas.d.ts +17 -1
  34. package/vendor/zod/classic/schemas.js +77 -29
  35. package/vendor/zod/core/api.d.ts +6 -4
  36. package/vendor/zod/core/api.js +17 -2
  37. package/vendor/zod/core/checks.d.ts +1 -1
  38. package/vendor/zod/core/checks.js +0 -96
  39. package/vendor/zod/core/compile.d.ts +18 -4
  40. package/vendor/zod/core/compile.js +146 -67
  41. package/vendor/zod/core/doc.js +7 -2
  42. package/vendor/zod/core/errors.js +2 -5
  43. package/vendor/zod/core/json-schema-generator.js +2 -2
  44. package/vendor/zod/core/json-schema-processors.d.ts +17 -0
  45. package/vendor/zod/core/json-schema-processors.js +195 -64
  46. package/vendor/zod/core/memoizer.js +72 -23
  47. package/vendor/zod/core/parse.js +37 -16
  48. package/vendor/zod/core/regexes.d.ts +2 -0
  49. package/vendor/zod/core/regexes.js +8 -4
  50. package/vendor/zod/core/schemas.d.ts +42 -7
  51. package/vendor/zod/core/schemas.js +301 -94
  52. package/vendor/zod/core/to-json-schema.d.ts +7 -3
  53. package/vendor/zod/core/to-json-schema.js +8 -7
  54. package/vendor/zod/core/util.d.ts +25 -4
  55. package/vendor/zod/core/util.js +160 -143
  56. package/vendor/zod/core/versions.d.ts +1 -1
  57. package/vendor/zod/core/versions.js +2 -2
  58. package/vendor/zod/core/visit.js +12 -0
  59. package/vendor/zod/locales/ar.js +1 -0
  60. package/vendor/zod/locales/az.js +1 -0
  61. package/vendor/zod/locales/be.js +1 -0
  62. package/vendor/zod/locales/bg.js +1 -0
  63. package/vendor/zod/locales/bn.js +1 -0
  64. package/vendor/zod/locales/ca.js +1 -0
  65. package/vendor/zod/locales/ckb.js +1 -0
  66. package/vendor/zod/locales/cs.js +1 -0
  67. package/vendor/zod/locales/da.js +1 -0
  68. package/vendor/zod/locales/de.js +1 -0
  69. package/vendor/zod/locales/el.js +1 -0
  70. package/vendor/zod/locales/en.js +1 -0
  71. package/vendor/zod/locales/eo.js +1 -0
  72. package/vendor/zod/locales/es.js +1 -0
  73. package/vendor/zod/locales/fa.js +1 -0
  74. package/vendor/zod/locales/fi.js +1 -0
  75. package/vendor/zod/locales/fr-CA.js +1 -0
  76. package/vendor/zod/locales/fr.js +1 -0
  77. package/vendor/zod/locales/gu.js +1 -0
  78. package/vendor/zod/locales/he.js +1 -0
  79. package/vendor/zod/locales/hi.js +1 -0
  80. package/vendor/zod/locales/hr.js +1 -0
  81. package/vendor/zod/locales/hu.js +1 -0
  82. package/vendor/zod/locales/hy.js +1 -0
  83. package/vendor/zod/locales/id.js +1 -0
  84. package/vendor/zod/locales/index.d.ts +1 -0
  85. package/vendor/zod/locales/index.js +1 -0
  86. package/vendor/zod/locales/is.js +1 -0
  87. package/vendor/zod/locales/it.js +1 -0
  88. package/vendor/zod/locales/ja.js +1 -0
  89. package/vendor/zod/locales/ka.js +1 -0
  90. package/vendor/zod/locales/km.js +1 -0
  91. package/vendor/zod/locales/kn.js +1 -0
  92. package/vendor/zod/locales/ko.js +1 -0
  93. package/vendor/zod/locales/lt.js +1 -0
  94. package/vendor/zod/locales/mk.js +1 -0
  95. package/vendor/zod/locales/ms.js +1 -0
  96. package/vendor/zod/locales/ne.js +1 -0
  97. package/vendor/zod/locales/nl.js +1 -0
  98. package/vendor/zod/locales/nn.js +1 -0
  99. package/vendor/zod/locales/no.js +1 -0
  100. package/vendor/zod/locales/ota.js +1 -0
  101. package/vendor/zod/locales/pl.js +1 -0
  102. package/vendor/zod/locales/ps.js +1 -0
  103. package/vendor/zod/locales/pt-BR.js +1 -0
  104. package/vendor/zod/locales/pt.js +1 -0
  105. package/vendor/zod/locales/ro.js +1 -0
  106. package/vendor/zod/locales/ru.js +1 -0
  107. package/vendor/zod/locales/sk.js +1 -0
  108. package/vendor/zod/locales/sl.js +1 -0
  109. package/vendor/zod/locales/sv.js +1 -0
  110. package/vendor/zod/locales/ta.js +1 -0
  111. package/vendor/zod/locales/tg.d.ts +4 -0
  112. package/vendor/zod/locales/tg.js +116 -0
  113. package/vendor/zod/locales/th.js +1 -0
  114. package/vendor/zod/locales/tk.js +1 -0
  115. package/vendor/zod/locales/tr.js +1 -0
  116. package/vendor/zod/locales/uk.js +1 -0
  117. package/vendor/zod/locales/ur.js +1 -0
  118. package/vendor/zod/locales/uz.js +1 -0
  119. package/vendor/zod/locales/vi.js +1 -0
  120. package/vendor/zod/locales/yo.js +1 -0
  121. package/vendor/zod/locales/zh-CN.js +1 -0
  122. package/vendor/zod/locales/zh-TW.js +1 -0
  123. package/vendor/zod/mini/checks.d.ts +1 -1
  124. package/vendor/zod/mini/checks.js +1 -1
  125. package/vendor/zod/mini/external.d.ts +1 -1
  126. package/vendor/zod/mini/external.js +1 -1
  127. package/vendor/zod/mini/schemas.d.ts +8 -0
  128. package/vendor/zod/mini/schemas.js +19 -2
  129. package/vendor/zodexy/dist/esm/index.js +34 -1
  130. package/vendor/zodexy/dist/schema.zodexy.json +18 -0
@@ -123,12 +123,13 @@ function resolveRef(ref, ctx) {
123
123
  throw new Error(`Reference not found: ${ref}`);
124
124
  }
125
125
  /**
126
- * Rejects every own key that fails `keySchema`, before `objectSchema` runs. The
127
- * guard has to see the raw input: an object parse drops `__proto__` and can add
128
- * keys from a property `default`, so its output is not the set of names the
129
- * instance actually carried.
126
+ * Enforces the keywords that constrain an object's own keys — `propertyNames`,
127
+ * `minProperties`, `maxProperties` before `objectSchema` runs. The guard has
128
+ * to see the raw input: an object parse drops `__proto__` and can add keys from
129
+ * a property `default`, so its output is not the set of names the instance
130
+ * actually carried.
130
131
  */
131
- function checkPropertyNames(objectSchema, keySchema) {
132
+ function checkObjectGuards(objectSchema, guards) {
132
133
  // An identity transform, not z.any(), so `toJSONSchema` reports the object on both the input and the output side of the pipe.
133
134
  const guard = z
134
135
  .transform((value) => value)
@@ -136,22 +137,209 @@ function checkPropertyNames(objectSchema, keySchema) {
136
137
  const value = payload.value;
137
138
  if (typeof value !== "object" || value === null || Array.isArray(value))
138
139
  return;
139
- for (const key of Object.getOwnPropertyNames(value)) {
140
- const result = keySchema.safeParse(key);
141
- if (result.success)
142
- continue;
140
+ const keys = Object.getOwnPropertyNames(value);
141
+ if (guards.minProperties !== undefined && keys.length < guards.minProperties) {
143
142
  payload.issues.push({
144
- code: "invalid_key",
145
- origin: "record",
146
- issues: result.error.issues,
147
- input: key,
148
- path: [key],
143
+ origin: "object",
144
+ code: "too_small",
145
+ minimum: guards.minProperties,
146
+ inclusive: true,
147
+ message: `Too small: expected object to have >=${guards.minProperties} properties`,
148
+ input: value,
149
+ inst: objectSchema,
149
150
  continue: true,
150
151
  });
151
152
  }
153
+ if (guards.maxProperties !== undefined && keys.length > guards.maxProperties) {
154
+ payload.issues.push({
155
+ origin: "object",
156
+ code: "too_big",
157
+ maximum: guards.maxProperties,
158
+ inclusive: true,
159
+ message: `Too big: expected object to have <=${guards.maxProperties} properties`,
160
+ input: value,
161
+ inst: objectSchema,
162
+ continue: true,
163
+ });
164
+ }
165
+ if (guards.keySchema) {
166
+ for (const key of keys) {
167
+ const result = guards.keySchema.safeParse(key);
168
+ if (result.success)
169
+ continue;
170
+ payload.issues.push({
171
+ code: "invalid_key",
172
+ origin: "record",
173
+ issues: result.error.issues,
174
+ input: key,
175
+ path: [key],
176
+ continue: true,
177
+ });
178
+ }
179
+ }
152
180
  });
153
181
  return guard.pipe(objectSchema);
154
182
  }
183
+ /**
184
+ * An injective string for JSON data: two values share a key exactly when `uniqueItems` calls them
185
+ * equal, so duplicate detection is a Map lookup rather than a pairwise walk. Strings and keys are
186
+ * length-prefixed so no value can spell another one. `null` means "never equal to anything" — a
187
+ * cycle or a NaN, neither of which JSON can express.
188
+ */
189
+ function canonicalKey(value, seen) {
190
+ if (value === null)
191
+ return "z";
192
+ const type = typeof value;
193
+ if (type !== "object") {
194
+ if (type === "number" && Number.isNaN(value))
195
+ return null;
196
+ const raw = String(value);
197
+ return `${type[0]}${raw.length}:${raw}`;
198
+ }
199
+ if (seen.has(value))
200
+ return null;
201
+ seen.add(value);
202
+ try {
203
+ if (Array.isArray(value)) {
204
+ const parts = [];
205
+ for (const item of value) {
206
+ const key = canonicalKey(item, seen);
207
+ if (key === null)
208
+ return null;
209
+ parts.push(key);
210
+ }
211
+ return `a${parts.length}:[${parts.join(",")}]`;
212
+ }
213
+ const keys = Object.keys(value).sort();
214
+ const parts = [];
215
+ for (const k of keys) {
216
+ const key = canonicalKey(value[k], seen);
217
+ if (key === null)
218
+ return null;
219
+ parts.push(`${k.length}:${k}=${key}`);
220
+ }
221
+ return `o${parts.length}:{${parts.join(",")}}`;
222
+ }
223
+ finally {
224
+ seen.delete(value);
225
+ }
226
+ }
227
+ // keywords whose value is a schema or an array of them
228
+ const SCHEMA_KEYWORDS = /*@__PURE__*/ new Set([
229
+ "items",
230
+ "prefixItems",
231
+ "additionalItems",
232
+ "additionalProperties",
233
+ "contains",
234
+ "propertyNames",
235
+ "not",
236
+ "if",
237
+ "then",
238
+ "else",
239
+ "allOf",
240
+ "anyOf",
241
+ "oneOf",
242
+ "unevaluatedItems",
243
+ "unevaluatedProperties",
244
+ "contentSchema",
245
+ ]);
246
+ // keywords whose value maps names to schemas. draft-7 `dependencies` also allows an array of property names, which holds no schema to walk
247
+ const SCHEMA_MAP_KEYWORDS = /*@__PURE__*/ new Set([
248
+ "properties",
249
+ "patternProperties",
250
+ "dependentSchemas",
251
+ "dependencies",
252
+ "$defs",
253
+ "definitions",
254
+ ]);
255
+ /**
256
+ * True when a subschema holds a `$ref` anywhere a schema can appear. Only those positions are
257
+ * walked: `$ref` under `default` or an `x-` annotation is instance data with an ordinary key, and
258
+ * reading it as a reference would drop a constraint that resolves perfectly well.
259
+ */
260
+ function containsRef(value) {
261
+ if (typeof value !== "object" || value === null)
262
+ return false;
263
+ if (Array.isArray(value))
264
+ return value.some(containsRef);
265
+ if (typeof value.$ref === "string")
266
+ return true;
267
+ return Object.entries(value).some(([key, sub]) => {
268
+ if (SCHEMA_KEYWORDS.has(key))
269
+ return containsRef(sub);
270
+ if (!SCHEMA_MAP_KEYWORDS.has(key) || typeof sub !== "object" || sub === null)
271
+ return false;
272
+ return Object.values(sub).some(containsRef);
273
+ });
274
+ }
275
+ function plural(n) {
276
+ return n === 1 ? "element" : "elements";
277
+ }
278
+ /**
279
+ * Enforces `uniqueItems` and the `contains` family before `arraySchema` runs, for the same reason
280
+ * `checkObjectGuards` runs pre-pipe: an item parse can apply a nested `default`, so the parsed
281
+ * array is not the instance the keywords are defined over. A guard issue aborts the pipe, so
282
+ * `minItems`/`maxItems` are not also reported on the same parse — instance correctness is worth
283
+ * more than co-reporting two issues.
284
+ */
285
+ function checkArrayGuards(arraySchema, guards) {
286
+ // An identity transform, not z.any(), so `toJSONSchema` reports the array on both the input and the output side of the pipe.
287
+ const guard = z
288
+ .transform((value) => value)
289
+ .check((payload) => {
290
+ const items = payload.value;
291
+ if (!Array.isArray(items))
292
+ return;
293
+ if (guards.uniqueItems === true) {
294
+ const firstSeen = new Map();
295
+ for (let i = 0; i < items.length; i++) {
296
+ const key = canonicalKey(items[i], new Set());
297
+ if (key === null)
298
+ continue;
299
+ const first = firstSeen.get(key);
300
+ if (first === undefined) {
301
+ firstSeen.set(key, i);
302
+ continue;
303
+ }
304
+ payload.issues.push({
305
+ code: "custom",
306
+ message: `Array items must be unique: element at index ${i} duplicates the one at index ${first}`,
307
+ input: items,
308
+ path: [i],
309
+ continue: true,
310
+ });
311
+ }
312
+ }
313
+ if (guards.containsSchema) {
314
+ const minContains = guards.minContains ?? 1;
315
+ // one past the ceiling already proves the failure, and nothing above it changes the verdict
316
+ const ceiling = guards.maxContains !== undefined ? guards.maxContains + 1 : Number.POSITIVE_INFINITY;
317
+ let matches = 0;
318
+ for (const item of items) {
319
+ if (guards.containsSchema.safeParse(item).success && ++matches >= ceiling)
320
+ break;
321
+ }
322
+ if (matches < minContains) {
323
+ // the scan ran to the end, so this count is exact
324
+ payload.issues.push({
325
+ code: "custom",
326
+ message: `Array must contain at least ${minContains} matching ${plural(minContains)}; found ${matches}`,
327
+ input: items,
328
+ continue: true,
329
+ });
330
+ }
331
+ if (guards.maxContains !== undefined && matches > guards.maxContains) {
332
+ payload.issues.push({
333
+ code: "custom",
334
+ message: `Array must contain at most ${guards.maxContains} matching ${plural(guards.maxContains)}`,
335
+ input: items,
336
+ continue: true,
337
+ });
338
+ }
339
+ }
340
+ });
341
+ return guard.pipe(arraySchema);
342
+ }
155
343
  function getTupleRest(restSchema, ctx) {
156
344
  if (restSchema === false) {
157
345
  return undefined;
@@ -316,6 +504,9 @@ function convertBaseSchema(schema, ctx) {
316
504
  else if (format === "credit_card") {
317
505
  stringSchema = stringSchema.check(z.creditCard());
318
506
  }
507
+ else if (format === "iban") {
508
+ stringSchema = stringSchema.check(z.iban());
509
+ }
319
510
  else if (format === "jwt") {
320
511
  stringSchema = stringSchema.check(z.jwt());
321
512
  }
@@ -483,17 +674,23 @@ function convertBaseSchema(schema, ctx) {
483
674
  }
484
675
  }
485
676
  // propertyNames constrains key *names* only, and says nothing about which keys are required or how their values validate. Layering it on top of the result keeps properties/patternProperties/additionalProperties composing underneath. `true` allows every name, so it needs no guard.
486
- if (schema.propertyNames !== undefined && schema.propertyNames !== true) {
487
- // Keys are always strings, so a propertyNames subschema that omits `type` still constrains them — without this it would convert to z.any().
488
- const keyJSONSchema = typeof schema.propertyNames === "object" && schema.propertyNames.type === undefined
489
- ? { type: "string", ...schema.propertyNames }
490
- : schema.propertyNames;
491
- zodSchema = checkPropertyNames(zodSchema, convertSchema(keyJSONSchema, ctx));
677
+ const hasKeyGuard = schema.propertyNames !== undefined && schema.propertyNames !== true;
678
+ const minProperties = typeof schema.minProperties === "number" ? schema.minProperties : undefined;
679
+ const maxProperties = typeof schema.maxProperties === "number" ? schema.maxProperties : undefined;
680
+ if (hasKeyGuard || minProperties !== undefined || maxProperties !== undefined) {
681
+ let keySchema;
682
+ if (hasKeyGuard) {
683
+ // Keys are always strings, so a propertyNames subschema that omits `type` still constrains them — without this it would convert to z.any().
684
+ const keyJSONSchema = typeof schema.propertyNames === "object" && schema.propertyNames.type === undefined
685
+ ? { type: "string", ...schema.propertyNames }
686
+ : schema.propertyNames;
687
+ keySchema = convertSchema(keyJSONSchema, ctx);
688
+ }
689
+ zodSchema = checkObjectGuards(zodSchema, { keySchema, minProperties, maxProperties });
492
690
  }
493
691
  break;
494
692
  }
495
693
  case "array": {
496
- // TODO: uniqueItems and contains/minContains/maxContains are not supported
497
694
  // Check if this is a tuple (prefixItems or items as array)
498
695
  const prefixItems = schema.prefixItems;
499
696
  const items = schema.items;
@@ -546,6 +743,15 @@ function convertBaseSchema(schema, ctx) {
546
743
  // No items specified - array of any
547
744
  zodSchema = z.array(z.any());
548
745
  }
746
+ // minContains/maxContains only constrain anything when `contains` itself is present
747
+ if (schema.uniqueItems === true || schema.contains !== undefined) {
748
+ zodSchema = checkArrayGuards(zodSchema, {
749
+ uniqueItems: schema.uniqueItems === true,
750
+ containsSchema: schema.contains !== undefined ? convertSchema(schema.contains, ctx) : undefined,
751
+ minContains: typeof schema.minContains === "number" ? schema.minContains : undefined,
752
+ maxContains: typeof schema.maxContains === "number" ? schema.maxContains : undefined,
753
+ });
754
+ }
549
755
  break;
550
756
  }
551
757
  default:
@@ -613,9 +819,24 @@ function convertSchema(schema, ctx) {
613
819
  extraMeta[key] = schema[key];
614
820
  }
615
821
  }
616
- // `propertyNames` is enforced by a key guard, which `toJSONSchema` cannot infer, so the original keyword is carried as metadata to keep the round-trip lossless. Only where it was actually applied: on any other type it is inert, and on a `$ref` the metadata would land on the target every reference shares.
617
- if (schema.propertyNames !== undefined && schema.type === "object" && schema.$ref === undefined) {
618
- extraMeta.propertyNames = schema.propertyNames;
822
+ // `propertyNames` and `contains` are enforced by a guard, which `toJSONSchema` cannot infer, so the original keyword is carried as metadata to keep the round-trip lossless. Only where it was actually applied: on any other type it is inert, and on a `$ref` the metadata would land on the target every reference shares. A carried subschema is copied verbatim while the root `$defs` stay behind, so one holding a `$ref` is dropped rather than emitted as a dangling reference.
823
+ if (schema.type === "object" && schema.$ref === undefined) {
824
+ if (schema.propertyNames !== undefined && !containsRef(schema.propertyNames)) {
825
+ extraMeta.propertyNames = schema.propertyNames;
826
+ }
827
+ for (const key of ["minProperties", "maxProperties"]) {
828
+ if (schema[key] !== undefined)
829
+ extraMeta[key] = schema[key];
830
+ }
831
+ }
832
+ if (schema.type === "array" && schema.$ref === undefined) {
833
+ if (schema.contains !== undefined && !containsRef(schema.contains)) {
834
+ extraMeta.contains = schema.contains;
835
+ }
836
+ for (const key of ["uniqueItems", "minContains", "maxContains"]) {
837
+ if (schema[key] !== undefined)
838
+ extraMeta[key] = schema[key];
839
+ }
619
840
  }
620
841
  for (const key of Object.keys(schema)) {
621
842
  if (!RECOGNIZED_KEYS.has(key)) {
@@ -28,6 +28,8 @@ export interface ZodType<out Output = unknown, out Input = unknown, out Internal
28
28
  parseAsync(data: unknown, params?: core.ParseContext<core.$ZodIssue>): Promise<core.output<this>>;
29
29
  safeParseAsync(data: unknown, params?: core.ParseContext<core.$ZodIssue>): Promise<parse.ZodSafeParseResult<core.output<this>>>;
30
30
  spa: (data: unknown, params?: core.ParseContext<core.$ZodIssue>) => Promise<parse.ZodSafeParseResult<core.output<this>>>;
31
+ validate(data: unknown, params?: core.ParseContext<core.$ZodIssue>): data is core.input<this>;
32
+ validateAsync(data: unknown, params?: core.ParseContext<core.$ZodIssue>): Promise<boolean>;
31
33
  encode(data: core.output<this>, params?: core.ParseContext<core.$ZodIssue>): core.input<this>;
32
34
  decode(data: core.input<this>, params?: core.ParseContext<core.$ZodIssue>): core.output<this>;
33
35
  encodeAsync(data: core.output<this>, params?: core.ParseContext<core.$ZodIssue>): Promise<core.input<this>>;
@@ -310,6 +312,11 @@ export interface ZodCreditCard extends ZodStringFormat<"credit_card"> {
310
312
  }
311
313
  export declare const ZodCreditCard: core.$constructor<ZodCreditCard>;
312
314
  export declare function creditCard(params?: string | core.$ZodCreditCardParams): ZodCreditCard;
315
+ export interface ZodIBAN extends ZodStringFormat<"iban"> {
316
+ _zod: core.$ZodIBANInternals;
317
+ }
318
+ export declare const ZodIBAN: core.$constructor<ZodIBAN>;
319
+ export declare function iban(params?: string | core.$ZodIBANParams): ZodIBAN;
313
320
  export interface ZodJWT extends ZodStringFormat<"jwt"> {
314
321
  _zod: core.$ZodJWTInternals;
315
322
  }
@@ -772,6 +779,11 @@ export interface ZodCustom<O = unknown, I = unknown> extends _ZodType<core.$ZodC
772
779
  "~standard": ZodStandardSchemaWithJSON<this>;
773
780
  }
774
781
  export declare const ZodCustom: core.$constructor<ZodCustom>;
782
+ export interface ZodProperties<Shape extends core.$ZodShape = core.$ZodShape> extends _ZodType<core.$ZodPropertiesInternals<Shape>>, core.$ZodProperties<Shape> {
783
+ "~standard": ZodStandardSchemaWithJSON<this>;
784
+ }
785
+ export declare const ZodProperties: core.$constructor<ZodProperties>;
786
+ export declare function properties<Shape extends core.$ZodShape>(shape: Shape, params?: string | core.$ZodPropertiesParams): ZodProperties<Shape>;
775
787
  export declare function check<O = unknown>(fn: core.CheckFn<O>): core.$ZodCheck<O>;
776
788
  export declare function custom<O>(fn?: (data: unknown) => unknown, _params?: string | core.$ZodCustomParams | undefined): ZodCustom<O, O>;
777
789
  export declare function refine<T>(fn: (arg: NoInfer<T>) => util.MaybeAsync<unknown>, _params?: string | core.$ZodCustomParams): core.$ZodCheck<T>;
@@ -779,7 +791,11 @@ export declare function superRefine<T>(fn: (arg: T, payload: core.$RefinementCtx
779
791
  export declare const describe: typeof core.describe;
780
792
  export declare const meta: typeof core.meta;
781
793
  type ZodInstanceOfParams = core.Params<ZodCustom, core.$ZodIssueCustom, "type" | "check" | "checks" | "fn" | "abort" | "error" | "params" | "path">;
782
- declare function _instanceof<T extends typeof util.Class>(cls: T, params?: ZodInstanceOfParams): ZodCustom<InstanceType<T>, InstanceType<T>>;
794
+ export interface ZodInstanceOf<T = unknown> extends ZodCustom<T, T> {
795
+ properties<Shape extends core.$ZodShape>(shape: Shape, params?: string | core.$ZodPropertiesParams): ZodInstanceOf<T & core.$InferObjectInput<Shape, {}>>;
796
+ }
797
+ export declare const ZodInstanceOf: core.$constructor<ZodInstanceOf>;
798
+ declare function _instanceof<T extends typeof util.Class>(cls: T, params?: ZodInstanceOfParams): ZodInstanceOf<InstanceType<T>>;
783
799
  export { _instanceof as instanceof };
784
800
  export declare const stringbool: (_params?: string | core.$ZodStringBoolParams) => ZodCodec<ZodString, ZodBoolean>;
785
801
  type _ZodJSONSchema = ZodUnion<[
@@ -149,6 +149,12 @@ export const ZodType = /*@__PURE__*/ core.$constructor("ZodType", (inst, def) =>
149
149
  set spa(value) {
150
150
  util.own(this, "spa", value);
151
151
  },
152
+ validate(data, params) {
153
+ return parse.validate(this, data, params);
154
+ },
155
+ validateAsync(data, params) {
156
+ return parse.validateAsync(this, data, params);
157
+ },
152
158
  encode: function _encode(data, params) {
153
159
  return parse.encode(this, data, params, { callee: _encode });
154
160
  },
@@ -190,10 +196,11 @@ export const _ZodString = /*@__PURE__*/ core.$constructor("_ZodString", (inst, d
190
196
  core.$ZodString.init(inst, def);
191
197
  ZodType.init(inst, def);
192
198
  inst._zod.processJSONSchema = (ctx, json, params) => processors.stringProcessor(inst, ctx, json, params);
193
- const bag = inst._zod.bag;
194
- inst.format = bag.format ?? null;
195
- inst.minLength = bag.minimum ?? null;
196
- inst.maxLength = bag.maximum ?? null;
199
+ },
200
+ /*@__PURE__*/ util.derived({
201
+ format: (inst) => processors.aggregateChecks(inst).format ?? null,
202
+ minLength: (inst) => processors.aggregateChecks(inst).minimum ?? null,
203
+ maxLength: (inst) => processors.aggregateChecks(inst).maximum ?? null,
197
204
  }, {
198
205
  regex(...args) {
199
206
  return this.check(checks.regex(...args));
@@ -240,7 +247,7 @@ export const _ZodString = /*@__PURE__*/ core.$constructor("_ZodString", (inst, d
240
247
  slugify() {
241
248
  return this.check(checks.slugify());
242
249
  },
243
- });
250
+ }));
244
251
  export const ZodString = /*@__PURE__*/ core.$constructor("ZodString", (inst, def) => {
245
252
  core.$ZodString.init(inst, def);
246
253
  _ZodString.init(inst, def);
@@ -534,6 +541,13 @@ export const ZodCreditCard = /*@__PURE__*/ core.$constructor("ZodCreditCard", (i
534
541
  export function creditCard(params) {
535
542
  return core._creditCard(ZodCreditCard, params);
536
543
  }
544
+ export const ZodIBAN = /*@__PURE__*/ core.$constructor("ZodIBAN", (inst, def) => {
545
+ core.$ZodIBAN.init(inst, def);
546
+ ZodStringFormat.init(inst, def);
547
+ });
548
+ export function iban(params) {
549
+ return core._iban(ZodIBAN, params);
550
+ }
537
551
  export const ZodJWT = /*@__PURE__*/ core.$constructor("ZodJWT", (inst, def) => {
538
552
  // ZodStringFormat.init(inst, def);
539
553
  core.$ZodJWT.init(inst, def);
@@ -568,14 +582,22 @@ export const ZodNumber = /*@__PURE__*/ core.$constructor("ZodNumber", (inst, def
568
582
  core.$ZodNumber.init(inst, def);
569
583
  ZodType.init(inst, def);
570
584
  inst._zod.processJSONSchema = (ctx, json, params) => processors.numberProcessor(inst, ctx, json, params);
571
- const bag = inst._zod.bag;
572
- inst.minValue =
573
- Math.max(bag.minimum ?? Number.NEGATIVE_INFINITY, bag.exclusiveMinimum ?? Number.NEGATIVE_INFINITY) ?? null;
574
- inst.maxValue =
575
- Math.min(bag.maximum ?? Number.POSITIVE_INFINITY, bag.exclusiveMaximum ?? Number.POSITIVE_INFINITY) ?? null;
576
- inst.isInt = (bag.format ?? "").includes("int") || Number.isSafeInteger(bag.multipleOf ?? 0.5);
577
585
  inst.isFinite = true;
578
- inst.format = bag.format ?? null;
586
+ },
587
+ /*@__PURE__*/ util.derived({
588
+ minValue: (inst) => {
589
+ const { minimum, exclusiveMinimum } = processors.aggregateChecks(inst);
590
+ return Math.max(minimum ?? Number.NEGATIVE_INFINITY, exclusiveMinimum ?? Number.NEGATIVE_INFINITY);
591
+ },
592
+ maxValue: (inst) => {
593
+ const { maximum, exclusiveMaximum } = processors.aggregateChecks(inst);
594
+ return Math.min(maximum ?? Number.POSITIVE_INFINITY, exclusiveMaximum ?? Number.POSITIVE_INFINITY);
595
+ },
596
+ isInt: (inst) => {
597
+ const { isInt, multipleOf } = processors.aggregateChecks(inst);
598
+ return !!isInt || !!multipleOf?.some(Number.isSafeInteger);
599
+ },
600
+ format: (inst) => processors.aggregateChecks(inst).format ?? null,
579
601
  }, {
580
602
  gt(value, params) {
581
603
  return this.check(checks.gt(value, params));
@@ -622,7 +644,7 @@ export const ZodNumber = /*@__PURE__*/ core.$constructor("ZodNumber", (inst, def
622
644
  finite() {
623
645
  return this;
624
646
  },
625
- });
647
+ }));
626
648
  export function number(params) {
627
649
  return core._number(ZodNumber, params);
628
650
  }
@@ -657,10 +679,11 @@ export const ZodBigInt = /*@__PURE__*/ core.$constructor("ZodBigInt", (inst, def
657
679
  core.$ZodBigInt.init(inst, def);
658
680
  ZodType.init(inst, def);
659
681
  inst._zod.processJSONSchema = (ctx, json, params) => processors.bigintProcessor(inst, ctx, json, params);
660
- const bag = inst._zod.bag;
661
- inst.minValue = bag.minimum ?? null;
662
- inst.maxValue = bag.maximum ?? null;
663
- inst.format = bag.format ?? null;
682
+ },
683
+ /*@__PURE__*/ util.derived({
684
+ minValue: (inst) => processors.aggregateChecks(inst).minimum ?? null,
685
+ maxValue: (inst) => processors.aggregateChecks(inst).maximum ?? null,
686
+ format: (inst) => processors.aggregateChecks(inst).format ?? null,
664
687
  }, {
665
688
  gte(value, params) {
666
689
  return this.check(checks.gte(value, params));
@@ -695,7 +718,7 @@ export const ZodBigInt = /*@__PURE__*/ core.$constructor("ZodBigInt", (inst, def
695
718
  multipleOf(value, params) {
696
719
  return this.check(checks.multipleOf(value, params));
697
720
  },
698
- });
721
+ }));
699
722
  export function bigint(params) {
700
723
  return core._bigint(ZodBigInt, params);
701
724
  }
@@ -774,10 +797,17 @@ export const ZodDate = /*@__PURE__*/ core.$constructor("ZodDate", (inst, def) =>
774
797
  inst._zod.processJSONSchema = (ctx, json, params) => processors.dateProcessor(inst, ctx, json, params);
775
798
  inst.min = (value, params) => inst.check(checks.gte(value, params));
776
799
  inst.max = (value, params) => inst.check(checks.lte(value, params));
777
- const c = inst._zod.bag;
778
- inst.minDate = c.minimum ? new Date(c.minimum) : null;
779
- inst.maxDate = c.maximum ? new Date(c.maximum) : null;
780
- });
800
+ },
801
+ /*@__PURE__*/ util.derived({
802
+ minDate: (inst) => {
803
+ const { minimum } = processors.aggregateChecks(inst);
804
+ return minimum ? new Date(minimum) : null;
805
+ },
806
+ maxDate: (inst) => {
807
+ const { maximum } = processors.aggregateChecks(inst);
808
+ return maximum ? new Date(maximum) : null;
809
+ },
810
+ }, {}));
781
811
  export function date(params) {
782
812
  return core._date(ZodDate, params);
783
813
  }
@@ -823,19 +853,20 @@ export const ZodObject = /*@__PURE__*/ core.$constructor("ZodObject", (inst, def
823
853
  return _enum(Object.keys(this._zod.def.shape));
824
854
  },
825
855
  catchall(catchall) {
826
- return this.clone({ ...this._zod.def, catchall: catchall });
856
+ // `mergeDefs` rather than a spread: spreading reads `shape`, and resolving it can mint a whole fresh subtree
857
+ return this.clone(util.mergeDefs(this._zod.def, { catchall: catchall }));
827
858
  },
828
859
  passthrough() {
829
- return this.clone({ ...this._zod.def, catchall: unknown() });
860
+ return this.clone(util.mergeDefs(this._zod.def, { catchall: unknown() }));
830
861
  },
831
862
  loose() {
832
- return this.clone({ ...this._zod.def, catchall: unknown() });
863
+ return this.clone(util.mergeDefs(this._zod.def, { catchall: unknown() }));
833
864
  },
834
865
  strict() {
835
- return this.clone({ ...this._zod.def, catchall: never() });
866
+ return this.clone(util.mergeDefs(this._zod.def, { catchall: never() }));
836
867
  },
837
868
  strip() {
838
- return this.clone({ ...this._zod.def, catchall: undefined });
869
+ return this.clone(util.mergeDefs(this._zod.def, { catchall: undefined }));
839
870
  },
840
871
  extend(incoming) {
841
872
  return util.extend(this, incoming);
@@ -1063,7 +1094,8 @@ export const ZodEnum = /*@__PURE__*/ core.$constructor("ZodEnum", (inst, def) =>
1063
1094
  ZodType.init(inst, def);
1064
1095
  inst._zod.processJSONSchema = (ctx, json, params) => processors.enumProcessor(inst, ctx, json, params);
1065
1096
  inst.enum = def.entries;
1066
- inst.options = Object.values(def.entries);
1097
+ // reuse the parsed value set so a numeric TS enum's reverse-mapping keys stay out
1098
+ inst.options = [...inst._zod.values];
1067
1099
  const keys = new Set(Object.keys(def.entries));
1068
1100
  inst.extract = (values, params) => {
1069
1101
  const newEntries = {};
@@ -1423,6 +1455,14 @@ export const ZodCustom = /*@__PURE__*/ core.$constructor("ZodCustom", (inst, def
1423
1455
  ZodType.init(inst, def);
1424
1456
  inst._zod.processJSONSchema = (ctx, json, params) => processors.customProcessor(inst, ctx, json, params);
1425
1457
  });
1458
+ export const ZodProperties = /*@__PURE__*/ core.$constructor("ZodProperties", (inst, def) => {
1459
+ _ensureDefaultMemoizer();
1460
+ core.$ZodProperties.init(inst, def);
1461
+ ZodType.init(inst, def);
1462
+ });
1463
+ export function properties(shape, params) {
1464
+ return core._properties(ZodProperties, shape, params);
1465
+ }
1426
1466
  // custom checks
1427
1467
  export function check(fn) {
1428
1468
  const ch = new core.$ZodCheck({
@@ -1445,8 +1485,16 @@ export function superRefine(fn, params) {
1445
1485
  // Re-export describe and meta from core
1446
1486
  export const describe = core.describe;
1447
1487
  export const meta = core.meta;
1488
+ export const ZodInstanceOf = /*@__PURE__*/ core.$constructor("ZodInstanceOf", (inst, def) => {
1489
+ ZodCustom.init(inst, def);
1490
+ }, {
1491
+ properties(shape, params) {
1492
+ // asserts in place, so the narrowed output type is truthful without a wrapper
1493
+ return this.check(properties(shape, params));
1494
+ },
1495
+ });
1448
1496
  function _instanceof(cls, params = {}) {
1449
- const inst = new ZodCustom({
1497
+ const inst = new ZodInstanceOf({
1450
1498
  type: "custom",
1451
1499
  check: "custom",
1452
1500
  fn: (data) => data instanceof cls,
@@ -106,6 +106,9 @@ export declare function _e164<T extends schemas.$ZodE164>(Class: util.SchemaClas
106
106
  export type $ZodCreditCardParams = StringFormatParams<schemas.$ZodCreditCard, "pattern" | "when">;
107
107
  export type $ZodCheckCreditCardParams = CheckStringFormatParams<schemas.$ZodCreditCard, "pattern" | "when">;
108
108
  export declare function _creditCard<T extends schemas.$ZodCreditCard>(Class: util.SchemaClass<T>, params?: string | $ZodCreditCardParams | $ZodCheckCreditCardParams): T;
109
+ export type $ZodIBANParams = StringFormatParams<schemas.$ZodIBAN, "pattern" | "when">;
110
+ export type $ZodCheckIBANParams = CheckStringFormatParams<schemas.$ZodIBAN, "pattern" | "when">;
111
+ export declare function _iban<T extends schemas.$ZodIBAN>(Class: util.SchemaClass<T>, params?: string | $ZodIBANParams | $ZodCheckIBANParams): T;
109
112
  export type $ZodJWTParams = StringFormatParams<schemas.$ZodJWT, "pattern" | "when">;
110
113
  export type $ZodCheckJWTParams = CheckStringFormatParams<schemas.$ZodJWT, "pattern" | "when">;
111
114
  export declare function _jwt<T extends schemas.$ZodJWT>(Class: util.SchemaClass<T>, params?: string | $ZodJWTParams | $ZodCheckJWTParams): T;
@@ -211,11 +214,10 @@ export type $ZodCheckEndsWithParams = CheckParams<checks.$ZodCheckEndsWith, "suf
211
214
  export declare function _endsWith(suffix: string, params?: string | $ZodCheckEndsWithParams): checks.$ZodCheckEndsWith;
212
215
  export type $ZodCheckPropertyParams = CheckParams<checks.$ZodCheckProperty, "property" | "schema" | "when">;
213
216
  export declare function _property<K extends string, T extends schemas.$ZodType>(property: K, schema: T, params?: string | $ZodCheckPropertyParams): checks.$ZodCheckProperty<{
214
- [k in K]: core.output<T>;
217
+ [k in K]: util.Widen<core.input<T>>;
215
218
  }>;
216
- export declare function _properties<Shape extends schemas.$ZodShape>(shape: Shape): checks.$ZodCheckProperty<{
217
- -readonly [k in keyof Shape]: core.output<Shape[k]>;
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
221
  export type $ZodCheckMimeTypeParams = CheckParams<checks.$ZodCheckMimeType, "mime" | "when">;
220
222
  export declare function _mime(types: util.MimeTypes[], params?: string | $ZodCheckMimeTypeParams): checks.$ZodCheckMimeType;
221
223
  export declare function _overwrite<T>(tx: (input: T) => T): checks.$ZodCheckOverwrite<T>;
@@ -256,6 +256,16 @@ export function _creditCard(Class, params) {
256
256
  });
257
257
  }
258
258
  // @__NO_SIDE_EFFECTS__
259
+ export function _iban(Class, params) {
260
+ return new Class({
261
+ type: "string",
262
+ format: "iban",
263
+ check: "string_format",
264
+ abort: false,
265
+ ...util.normalizeParams(params),
266
+ });
267
+ }
268
+ // @__NO_SIDE_EFFECTS__
259
269
  export function _jwt(Class, params) {
260
270
  return new Class({
261
271
  type: "string",
@@ -678,8 +688,13 @@ export function _property(property, schema, params) {
678
688
  });
679
689
  }
680
690
  // @__NO_SIDE_EFFECTS__
681
- export function _properties(shape) {
682
- return Object.entries(shape).map(([property, schema]) => new checks.$ZodCheckProperty({ check: "property", property, schema }));
691
+ export function _properties(Class, shape, params) {
692
+ return new Class({
693
+ type: "properties",
694
+ check: "properties",
695
+ shape,
696
+ ...util.normalizeParams(params),
697
+ });
683
698
  }
684
699
  // @__NO_SIDE_EFFECTS__
685
700
  export function _mime(types, params) {
@@ -157,7 +157,7 @@ export interface $ZodCheckLengthEquals<T extends util.HasLength = util.HasLength
157
157
  _zod: $ZodCheckLengthEqualsInternals<T>;
158
158
  }
159
159
  export declare const $ZodCheckLengthEquals: core.$constructor<$ZodCheckLengthEquals>;
160
- export type $ZodStringFormats = "email" | "url" | "emoji" | "uuid" | "guid" | "nanoid" | "cuid" | "cuid2" | "ulid" | "xid" | "ksuid" | "datetime" | "date" | "time" | "duration" | "ipv4" | "ipv6" | "cidrv4" | "cidrv6" | "base64" | "base64url" | "json_string" | "e164" | "credit_card" | "lowercase" | "uppercase" | "regex" | "jwt" | "starts_with" | "ends_with" | "includes";
160
+ export type $ZodStringFormats = "email" | "url" | "emoji" | "uuid" | "guid" | "nanoid" | "cuid" | "cuid2" | "ulid" | "xid" | "ksuid" | "datetime" | "date" | "time" | "duration" | "ipv4" | "ipv6" | "cidrv4" | "cidrv6" | "base64" | "base64url" | "json_string" | "e164" | "credit_card" | "iban" | "lowercase" | "uppercase" | "regex" | "jwt" | "starts_with" | "ends_with" | "includes";
161
161
  export interface $ZodCheckStringFormatDef<Format extends string = string> extends $ZodCheckDef {
162
162
  check: "string_format";
163
163
  format: Format;