zod 4.2.0-canary.20251213T203150 → 4.2.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 (50) hide show
  1. package/package.json +1 -1
  2. package/src/v4/classic/external.ts +2 -1
  3. package/src/v4/classic/from-json-schema.ts +527 -0
  4. package/src/v4/classic/schemas.ts +43 -0
  5. package/src/v4/classic/tests/from-json-schema.test.ts +537 -0
  6. package/src/v4/classic/tests/record.test.ts +37 -0
  7. package/src/v4/classic/tests/union.test.ts +38 -0
  8. package/src/v4/core/api.ts +15 -0
  9. package/src/v4/core/errors.ts +12 -1
  10. package/src/v4/core/json-schema-processors.ts +5 -5
  11. package/src/v4/core/schemas.ts +99 -10
  12. package/src/v4/core/versions.ts +2 -2
  13. package/src/v4/mini/external.ts +1 -1
  14. package/src/v4/mini/schemas.ts +39 -0
  15. package/v4/classic/external.cjs +5 -2
  16. package/v4/classic/external.d.cts +3 -1
  17. package/v4/classic/external.d.ts +3 -1
  18. package/v4/classic/external.js +3 -1
  19. package/v4/classic/from-json-schema.cjs +503 -0
  20. package/v4/classic/from-json-schema.d.cts +10 -0
  21. package/v4/classic/from-json-schema.d.ts +10 -0
  22. package/v4/classic/from-json-schema.js +477 -0
  23. package/v4/classic/schemas.cjs +30 -2
  24. package/v4/classic/schemas.d.cts +10 -0
  25. package/v4/classic/schemas.d.ts +10 -0
  26. package/v4/classic/schemas.js +26 -0
  27. package/v4/core/api.cjs +9 -0
  28. package/v4/core/api.d.cts +2 -0
  29. package/v4/core/api.d.ts +2 -0
  30. package/v4/core/api.js +8 -0
  31. package/v4/core/errors.d.cts +10 -1
  32. package/v4/core/errors.d.ts +10 -1
  33. package/v4/core/json-schema-processors.cjs +5 -5
  34. package/v4/core/json-schema-processors.js +5 -5
  35. package/v4/core/schemas.cjs +76 -11
  36. package/v4/core/schemas.d.cts +9 -0
  37. package/v4/core/schemas.d.ts +9 -0
  38. package/v4/core/schemas.js +74 -9
  39. package/v4/core/versions.cjs +2 -2
  40. package/v4/core/versions.d.cts +1 -1
  41. package/v4/core/versions.d.ts +1 -1
  42. package/v4/core/versions.js +2 -2
  43. package/v4/mini/external.cjs +3 -2
  44. package/v4/mini/external.d.cts +2 -1
  45. package/v4/mini/external.d.ts +2 -1
  46. package/v4/mini/external.js +2 -1
  47. package/v4/mini/schemas.cjs +28 -2
  48. package/v4/mini/schemas.d.cts +8 -0
  49. package/v4/mini/schemas.d.ts +8 -0
  50. package/v4/mini/schemas.js +24 -0
@@ -0,0 +1,477 @@
1
+ import * as z from "../index.js";
2
+ function detectVersion(schema, defaultTarget) {
3
+ const $schema = schema.$schema;
4
+ if ($schema === "https://json-schema.org/draft/2020-12/schema") {
5
+ return "draft-2020-12";
6
+ }
7
+ if ($schema === "http://json-schema.org/draft-07/schema#") {
8
+ return "draft-7";
9
+ }
10
+ if ($schema === "http://json-schema.org/draft-04/schema#") {
11
+ return "draft-4";
12
+ }
13
+ // Use defaultTarget if provided, otherwise default to draft-2020-12
14
+ return defaultTarget ?? "draft-2020-12";
15
+ }
16
+ function resolveRef(ref, ctx) {
17
+ if (!ref.startsWith("#")) {
18
+ throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
19
+ }
20
+ const path = ref.slice(1).split("/").filter(Boolean);
21
+ // Handle root reference "#"
22
+ if (path.length === 0) {
23
+ return ctx.rootSchema;
24
+ }
25
+ const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
26
+ if (path[0] === defsKey) {
27
+ const key = path[1];
28
+ if (!key || !ctx.defs[key]) {
29
+ throw new Error(`Reference not found: ${ref}`);
30
+ }
31
+ return ctx.defs[key];
32
+ }
33
+ throw new Error(`Reference not found: ${ref}`);
34
+ }
35
+ function convertBaseSchema(schema, ctx) {
36
+ // Handle unsupported features
37
+ if (schema.not !== undefined) {
38
+ // Special case: { not: {} } represents never
39
+ if (typeof schema.not === "object" && Object.keys(schema.not).length === 0) {
40
+ return z.never();
41
+ }
42
+ throw new Error("not is not supported in Zod (except { not: {} } for never)");
43
+ }
44
+ if (schema.unevaluatedItems !== undefined) {
45
+ throw new Error("unevaluatedItems is not supported");
46
+ }
47
+ if (schema.unevaluatedProperties !== undefined) {
48
+ throw new Error("unevaluatedProperties is not supported");
49
+ }
50
+ if (schema.if !== undefined || schema.then !== undefined || schema.else !== undefined) {
51
+ throw new Error("Conditional schemas (if/then/else) are not supported");
52
+ }
53
+ if (schema.dependentSchemas !== undefined || schema.dependentRequired !== undefined) {
54
+ throw new Error("dependentSchemas and dependentRequired are not supported");
55
+ }
56
+ // Handle $ref
57
+ if (schema.$ref) {
58
+ const refPath = schema.$ref;
59
+ if (ctx.refs.has(refPath)) {
60
+ return ctx.refs.get(refPath);
61
+ }
62
+ if (ctx.processing.has(refPath)) {
63
+ // Circular reference - use lazy
64
+ return z.lazy(() => {
65
+ if (!ctx.refs.has(refPath)) {
66
+ throw new Error(`Circular reference not resolved: ${refPath}`);
67
+ }
68
+ return ctx.refs.get(refPath);
69
+ });
70
+ }
71
+ ctx.processing.add(refPath);
72
+ const resolved = resolveRef(refPath, ctx);
73
+ const zodSchema = convertSchema(resolved, ctx);
74
+ ctx.refs.set(refPath, zodSchema);
75
+ ctx.processing.delete(refPath);
76
+ return zodSchema;
77
+ }
78
+ // Handle enum
79
+ if (schema.enum !== undefined) {
80
+ const enumValues = schema.enum;
81
+ // Special case: OpenAPI 3.0 null representation { type: "string", nullable: true, enum: [null] }
82
+ if (ctx.version === "openapi-3.0" &&
83
+ schema.nullable === true &&
84
+ enumValues.length === 1 &&
85
+ enumValues[0] === null) {
86
+ return z.null();
87
+ }
88
+ if (enumValues.length === 0) {
89
+ return z.never();
90
+ }
91
+ if (enumValues.length === 1) {
92
+ return z.literal(enumValues[0]);
93
+ }
94
+ // Check if all values are strings
95
+ if (enumValues.every((v) => typeof v === "string")) {
96
+ return z.enum(enumValues);
97
+ }
98
+ // Mixed types - use union of literals
99
+ const literalSchemas = enumValues.map((v) => z.literal(v));
100
+ if (literalSchemas.length < 2) {
101
+ return literalSchemas[0];
102
+ }
103
+ return z.union([literalSchemas[0], literalSchemas[1], ...literalSchemas.slice(2)]);
104
+ }
105
+ // Handle const
106
+ if (schema.const !== undefined) {
107
+ return z.literal(schema.const);
108
+ }
109
+ // Handle type
110
+ const type = schema.type;
111
+ if (Array.isArray(type)) {
112
+ // Expand type array into anyOf union
113
+ const typeSchemas = type.map((t) => {
114
+ const typeSchema = { ...schema, type: t };
115
+ return convertBaseSchema(typeSchema, ctx);
116
+ });
117
+ if (typeSchemas.length === 0) {
118
+ return z.never();
119
+ }
120
+ if (typeSchemas.length === 1) {
121
+ return typeSchemas[0];
122
+ }
123
+ return z.union(typeSchemas);
124
+ }
125
+ if (!type) {
126
+ // No type specified - empty schema (any)
127
+ return z.any();
128
+ }
129
+ let zodSchema;
130
+ switch (type) {
131
+ case "string": {
132
+ let stringSchema = z.string();
133
+ // Apply format using .check() with Zod format functions
134
+ if (schema.format) {
135
+ const format = schema.format;
136
+ // Map common formats to Zod check functions
137
+ if (format === "email") {
138
+ stringSchema = stringSchema.check(z.email());
139
+ }
140
+ else if (format === "uri" || format === "uri-reference") {
141
+ stringSchema = stringSchema.check(z.url());
142
+ }
143
+ else if (format === "uuid" || format === "guid") {
144
+ stringSchema = stringSchema.check(z.uuid());
145
+ }
146
+ else if (format === "date-time") {
147
+ stringSchema = stringSchema.check(z.iso.datetime());
148
+ }
149
+ else if (format === "date") {
150
+ stringSchema = stringSchema.check(z.iso.date());
151
+ }
152
+ else if (format === "time") {
153
+ stringSchema = stringSchema.check(z.iso.time());
154
+ }
155
+ else if (format === "duration") {
156
+ stringSchema = stringSchema.check(z.iso.duration());
157
+ }
158
+ else if (format === "ipv4") {
159
+ stringSchema = stringSchema.check(z.ipv4());
160
+ }
161
+ else if (format === "ipv6") {
162
+ stringSchema = stringSchema.check(z.ipv6());
163
+ }
164
+ else if (format === "mac") {
165
+ stringSchema = stringSchema.check(z.mac());
166
+ }
167
+ else if (format === "cidr") {
168
+ stringSchema = stringSchema.check(z.cidrv4());
169
+ }
170
+ else if (format === "cidr-v6") {
171
+ stringSchema = stringSchema.check(z.cidrv6());
172
+ }
173
+ else if (format === "base64") {
174
+ stringSchema = stringSchema.check(z.base64());
175
+ }
176
+ else if (format === "base64url") {
177
+ stringSchema = stringSchema.check(z.base64url());
178
+ }
179
+ else if (format === "e164") {
180
+ stringSchema = stringSchema.check(z.e164());
181
+ }
182
+ else if (format === "jwt") {
183
+ stringSchema = stringSchema.check(z.jwt());
184
+ }
185
+ else if (format === "emoji") {
186
+ stringSchema = stringSchema.check(z.emoji());
187
+ }
188
+ else if (format === "nanoid") {
189
+ stringSchema = stringSchema.check(z.nanoid());
190
+ }
191
+ else if (format === "cuid") {
192
+ stringSchema = stringSchema.check(z.cuid());
193
+ }
194
+ else if (format === "cuid2") {
195
+ stringSchema = stringSchema.check(z.cuid2());
196
+ }
197
+ else if (format === "ulid") {
198
+ stringSchema = stringSchema.check(z.ulid());
199
+ }
200
+ else if (format === "xid") {
201
+ stringSchema = stringSchema.check(z.xid());
202
+ }
203
+ else if (format === "ksuid") {
204
+ stringSchema = stringSchema.check(z.ksuid());
205
+ }
206
+ // Note: json-string format is not currently supported by Zod
207
+ // Custom formats are ignored - keep as plain string
208
+ }
209
+ // Apply constraints
210
+ if (typeof schema.minLength === "number") {
211
+ stringSchema = stringSchema.min(schema.minLength);
212
+ }
213
+ if (typeof schema.maxLength === "number") {
214
+ stringSchema = stringSchema.max(schema.maxLength);
215
+ }
216
+ if (schema.pattern) {
217
+ // JSON Schema patterns are not implicitly anchored (match anywhere in string)
218
+ stringSchema = stringSchema.regex(new RegExp(schema.pattern));
219
+ }
220
+ zodSchema = stringSchema;
221
+ break;
222
+ }
223
+ case "number":
224
+ case "integer": {
225
+ let numberSchema = type === "integer" ? z.number().int() : z.number();
226
+ // Apply constraints
227
+ if (typeof schema.minimum === "number") {
228
+ numberSchema = numberSchema.min(schema.minimum);
229
+ }
230
+ if (typeof schema.maximum === "number") {
231
+ numberSchema = numberSchema.max(schema.maximum);
232
+ }
233
+ if (typeof schema.exclusiveMinimum === "number") {
234
+ numberSchema = numberSchema.gt(schema.exclusiveMinimum);
235
+ }
236
+ else if (schema.exclusiveMinimum === true && typeof schema.minimum === "number") {
237
+ numberSchema = numberSchema.gt(schema.minimum);
238
+ }
239
+ if (typeof schema.exclusiveMaximum === "number") {
240
+ numberSchema = numberSchema.lt(schema.exclusiveMaximum);
241
+ }
242
+ else if (schema.exclusiveMaximum === true && typeof schema.maximum === "number") {
243
+ numberSchema = numberSchema.lt(schema.maximum);
244
+ }
245
+ if (typeof schema.multipleOf === "number") {
246
+ numberSchema = numberSchema.multipleOf(schema.multipleOf);
247
+ }
248
+ zodSchema = numberSchema;
249
+ break;
250
+ }
251
+ case "boolean": {
252
+ zodSchema = z.boolean();
253
+ break;
254
+ }
255
+ case "null": {
256
+ zodSchema = z.null();
257
+ break;
258
+ }
259
+ case "object": {
260
+ const shape = {};
261
+ const properties = schema.properties || {};
262
+ const requiredSet = new Set(schema.required || []);
263
+ // Convert properties - mark optional ones
264
+ for (const [key, propSchema] of Object.entries(properties)) {
265
+ const propZodSchema = convertSchema(propSchema, ctx);
266
+ // If not in required array, make it optional
267
+ shape[key] = requiredSet.has(key) ? propZodSchema : propZodSchema.optional();
268
+ }
269
+ // Handle propertyNames
270
+ if (schema.propertyNames) {
271
+ const keySchema = convertSchema(schema.propertyNames, ctx);
272
+ const valueSchema = schema.additionalProperties && typeof schema.additionalProperties === "object"
273
+ ? convertSchema(schema.additionalProperties, ctx)
274
+ : z.any();
275
+ // Case A: No properties (pure record)
276
+ if (Object.keys(shape).length === 0) {
277
+ zodSchema = z.record(keySchema, valueSchema);
278
+ break;
279
+ }
280
+ // Case B: With properties (intersection of object and looseRecord)
281
+ const objectSchema = z.object(shape).passthrough();
282
+ const recordSchema = z.looseRecord(keySchema, valueSchema);
283
+ zodSchema = z.intersection(objectSchema, recordSchema);
284
+ break;
285
+ }
286
+ // Handle patternProperties
287
+ if (schema.patternProperties) {
288
+ // patternProperties: keys matching pattern must satisfy corresponding schema
289
+ // Use loose records so non-matching keys pass through
290
+ const patternProps = schema.patternProperties;
291
+ const patternKeys = Object.keys(patternProps);
292
+ const looseRecords = [];
293
+ for (const pattern of patternKeys) {
294
+ const patternValue = convertSchema(patternProps[pattern], ctx);
295
+ const keySchema = z.string().regex(new RegExp(pattern));
296
+ looseRecords.push(z.looseRecord(keySchema, patternValue));
297
+ }
298
+ // Build intersection: object schema + all pattern property records
299
+ const schemasToIntersect = [];
300
+ if (Object.keys(shape).length > 0) {
301
+ // Use passthrough so patternProperties can validate additional keys
302
+ schemasToIntersect.push(z.object(shape).passthrough());
303
+ }
304
+ schemasToIntersect.push(...looseRecords);
305
+ if (schemasToIntersect.length === 0) {
306
+ zodSchema = z.object({}).passthrough();
307
+ }
308
+ else if (schemasToIntersect.length === 1) {
309
+ zodSchema = schemasToIntersect[0];
310
+ }
311
+ else {
312
+ // Chain intersections: (A & B) & C & D ...
313
+ let result = z.intersection(schemasToIntersect[0], schemasToIntersect[1]);
314
+ for (let i = 2; i < schemasToIntersect.length; i++) {
315
+ result = z.intersection(result, schemasToIntersect[i]);
316
+ }
317
+ zodSchema = result;
318
+ }
319
+ break;
320
+ }
321
+ // Handle additionalProperties
322
+ // In JSON Schema, additionalProperties defaults to true (allow any extra properties)
323
+ // In Zod, objects strip unknown keys by default, so we need to handle this explicitly
324
+ const objectSchema = z.object(shape);
325
+ if (schema.additionalProperties === false) {
326
+ // Strict mode - no extra properties allowed
327
+ zodSchema = objectSchema.strict();
328
+ }
329
+ else if (typeof schema.additionalProperties === "object") {
330
+ // Extra properties must match the specified schema
331
+ zodSchema = objectSchema.catchall(convertSchema(schema.additionalProperties, ctx));
332
+ }
333
+ else {
334
+ // additionalProperties is true or undefined - allow any extra properties (passthrough)
335
+ zodSchema = objectSchema.passthrough();
336
+ }
337
+ break;
338
+ }
339
+ case "array": {
340
+ // TODO: uniqueItems is not supported
341
+ // TODO: contains/minContains/maxContains are not supported
342
+ // Check if this is a tuple (prefixItems or items as array)
343
+ const prefixItems = schema.prefixItems;
344
+ const items = schema.items;
345
+ if (prefixItems && Array.isArray(prefixItems)) {
346
+ // Tuple with prefixItems (draft-2020-12)
347
+ const tupleItems = prefixItems.map((item) => convertSchema(item, ctx));
348
+ const rest = items && typeof items === "object" && !Array.isArray(items)
349
+ ? convertSchema(items, ctx)
350
+ : undefined;
351
+ if (rest) {
352
+ zodSchema = z.tuple(tupleItems).rest(rest);
353
+ }
354
+ else {
355
+ zodSchema = z.tuple(tupleItems);
356
+ }
357
+ // Apply minItems/maxItems constraints to tuples
358
+ if (typeof schema.minItems === "number") {
359
+ zodSchema = zodSchema.check(z.minLength(schema.minItems));
360
+ }
361
+ if (typeof schema.maxItems === "number") {
362
+ zodSchema = zodSchema.check(z.maxLength(schema.maxItems));
363
+ }
364
+ }
365
+ else if (Array.isArray(items)) {
366
+ // Tuple with items array (draft-7)
367
+ const tupleItems = items.map((item) => convertSchema(item, ctx));
368
+ const rest = schema.additionalItems && typeof schema.additionalItems === "object"
369
+ ? convertSchema(schema.additionalItems, ctx)
370
+ : undefined; // additionalItems: false means no rest, handled by default tuple behavior
371
+ if (rest) {
372
+ zodSchema = z.tuple(tupleItems).rest(rest);
373
+ }
374
+ else {
375
+ zodSchema = z.tuple(tupleItems);
376
+ }
377
+ // Apply minItems/maxItems constraints to tuples
378
+ if (typeof schema.minItems === "number") {
379
+ zodSchema = zodSchema.check(z.minLength(schema.minItems));
380
+ }
381
+ if (typeof schema.maxItems === "number") {
382
+ zodSchema = zodSchema.check(z.maxLength(schema.maxItems));
383
+ }
384
+ }
385
+ else if (items !== undefined) {
386
+ // Regular array
387
+ const element = convertSchema(items, ctx);
388
+ let arraySchema = z.array(element);
389
+ // Apply constraints
390
+ if (typeof schema.minItems === "number") {
391
+ arraySchema = arraySchema.min(schema.minItems);
392
+ }
393
+ if (typeof schema.maxItems === "number") {
394
+ arraySchema = arraySchema.max(schema.maxItems);
395
+ }
396
+ zodSchema = arraySchema;
397
+ }
398
+ else {
399
+ // No items specified - array of any
400
+ zodSchema = z.array(z.any());
401
+ }
402
+ break;
403
+ }
404
+ default:
405
+ throw new Error(`Unsupported type: ${type}`);
406
+ }
407
+ // Apply metadata
408
+ if (schema.description) {
409
+ zodSchema = zodSchema.describe(schema.description);
410
+ }
411
+ if (schema.default !== undefined) {
412
+ zodSchema = zodSchema.default(schema.default);
413
+ }
414
+ return zodSchema;
415
+ }
416
+ function convertSchema(schema, ctx) {
417
+ if (typeof schema === "boolean") {
418
+ return schema ? z.any() : z.never();
419
+ }
420
+ // Convert base schema first (ignoring composition keywords)
421
+ let baseSchema = convertBaseSchema(schema, ctx);
422
+ const hasExplicitType = schema.type || schema.enum !== undefined || schema.const !== undefined;
423
+ // Process composition keywords LAST (they can appear together)
424
+ // Handle anyOf - wrap base schema with union
425
+ if (schema.anyOf && Array.isArray(schema.anyOf)) {
426
+ const options = schema.anyOf.map((s) => convertSchema(s, ctx));
427
+ const anyOfUnion = z.union(options);
428
+ baseSchema = hasExplicitType ? z.intersection(baseSchema, anyOfUnion) : anyOfUnion;
429
+ }
430
+ // Handle oneOf - exclusive union (exactly one must match)
431
+ if (schema.oneOf && Array.isArray(schema.oneOf)) {
432
+ const options = schema.oneOf.map((s) => convertSchema(s, ctx));
433
+ const oneOfUnion = z.xor(options);
434
+ baseSchema = hasExplicitType ? z.intersection(baseSchema, oneOfUnion) : oneOfUnion;
435
+ }
436
+ // Handle allOf - wrap base schema with intersection
437
+ if (schema.allOf && Array.isArray(schema.allOf)) {
438
+ if (schema.allOf.length === 0) {
439
+ baseSchema = hasExplicitType ? baseSchema : z.any();
440
+ }
441
+ else {
442
+ let result = hasExplicitType ? baseSchema : convertSchema(schema.allOf[0], ctx);
443
+ const startIdx = hasExplicitType ? 0 : 1;
444
+ for (let i = startIdx; i < schema.allOf.length; i++) {
445
+ result = z.intersection(result, convertSchema(schema.allOf[i], ctx));
446
+ }
447
+ baseSchema = result;
448
+ }
449
+ }
450
+ // Handle nullable (OpenAPI 3.0)
451
+ if (schema.nullable === true && ctx.version === "openapi-3.0") {
452
+ baseSchema = z.nullable(baseSchema);
453
+ }
454
+ // Handle readOnly
455
+ if (schema.readOnly === true) {
456
+ baseSchema = z.readonly(baseSchema);
457
+ }
458
+ return baseSchema;
459
+ }
460
+ /**
461
+ * Converts a JSON Schema to a Zod schema. This function should be considered semi-experimental. It's behavior is liable to change. */
462
+ export function fromJSONSchema(schema, params) {
463
+ // Handle boolean schemas
464
+ if (typeof schema === "boolean") {
465
+ return schema ? z.any() : z.never();
466
+ }
467
+ const version = detectVersion(schema, params?.defaultTarget);
468
+ const defs = (schema.$defs || schema.definitions || {});
469
+ const ctx = {
470
+ version,
471
+ defs,
472
+ refs: new Map(),
473
+ processing: new Set(),
474
+ rootSchema: schema,
475
+ };
476
+ return convertSchema(schema, ctx);
477
+ }
@@ -23,8 +23,8 @@ var __importStar = (this && this.__importStar) || function (mod) {
23
23
  return result;
24
24
  };
25
25
  Object.defineProperty(exports, "__esModule", { value: true });
26
- exports.ZodFile = exports.ZodLiteral = exports.ZodEnum = exports.ZodSet = exports.ZodMap = exports.ZodRecord = exports.ZodTuple = exports.ZodIntersection = exports.ZodDiscriminatedUnion = exports.ZodUnion = 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.ZodE164 = exports.ZodBase64URL = exports.ZodBase64 = exports.ZodCIDRv6 = exports.ZodCIDRv4 = exports.ZodIPv6 = exports.ZodMAC = exports.ZodIPv4 = exports.ZodKSUID = exports.ZodXID = exports.ZodULID = exports.ZodCUID2 = exports.ZodCUID = exports.ZodNanoID = exports.ZodEmoji = exports.ZodURL = exports.ZodUUID = exports.ZodGUID = exports.ZodEmail = exports.ZodStringFormat = exports.ZodString = exports._ZodString = exports.ZodType = void 0;
27
- exports.stringbool = exports.meta = exports.describe = exports.ZodCustom = exports.ZodFunction = exports.ZodPromise = exports.ZodLazy = exports.ZodTemplateLiteral = exports.ZodReadonly = exports.ZodCodec = exports.ZodPipe = exports.ZodNaN = exports.ZodCatch = exports.ZodSuccess = exports.ZodNonOptional = exports.ZodPrefault = exports.ZodDefault = exports.ZodNullable = exports.ZodOptional = exports.ZodTransform = void 0;
26
+ exports.ZodLiteral = exports.ZodEnum = exports.ZodSet = exports.ZodMap = exports.ZodRecord = exports.ZodTuple = exports.ZodIntersection = exports.ZodDiscriminatedUnion = exports.ZodXor = exports.ZodUnion = 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.ZodE164 = exports.ZodBase64URL = exports.ZodBase64 = exports.ZodCIDRv6 = exports.ZodCIDRv4 = exports.ZodIPv6 = exports.ZodMAC = exports.ZodIPv4 = exports.ZodKSUID = exports.ZodXID = exports.ZodULID = exports.ZodCUID2 = exports.ZodCUID = exports.ZodNanoID = exports.ZodEmoji = exports.ZodURL = exports.ZodUUID = exports.ZodGUID = exports.ZodEmail = exports.ZodStringFormat = exports.ZodString = exports._ZodString = exports.ZodType = void 0;
27
+ exports.stringbool = exports.meta = exports.describe = exports.ZodCustom = exports.ZodFunction = exports.ZodPromise = exports.ZodLazy = exports.ZodTemplateLiteral = exports.ZodReadonly = exports.ZodCodec = exports.ZodPipe = exports.ZodNaN = exports.ZodCatch = exports.ZodSuccess = exports.ZodNonOptional = exports.ZodPrefault = exports.ZodDefault = exports.ZodNullable = exports.ZodOptional = exports.ZodTransform = exports.ZodFile = void 0;
28
28
  exports.string = string;
29
29
  exports.email = email;
30
30
  exports.guid = guid;
@@ -78,11 +78,13 @@ exports.object = object;
78
78
  exports.strictObject = strictObject;
79
79
  exports.looseObject = looseObject;
80
80
  exports.union = union;
81
+ exports.xor = xor;
81
82
  exports.discriminatedUnion = discriminatedUnion;
82
83
  exports.intersection = intersection;
83
84
  exports.tuple = tuple;
84
85
  exports.record = record;
85
86
  exports.partialRecord = partialRecord;
87
+ exports.looseRecord = looseRecord;
86
88
  exports.map = map;
87
89
  exports.set = set;
88
90
  exports.enum = _enum;
@@ -721,6 +723,23 @@ function union(options, params) {
721
723
  ...index_js_1.util.normalizeParams(params),
722
724
  });
723
725
  }
726
+ exports.ZodXor = core.$constructor("ZodXor", (inst, def) => {
727
+ exports.ZodUnion.init(inst, def);
728
+ core.$ZodXor.init(inst, def);
729
+ inst._zod.processJSONSchema = (ctx, json, params) => processors.unionProcessor(inst, ctx, json, params);
730
+ inst.options = def.options;
731
+ });
732
+ /** Creates an exclusive union (XOR) where exactly one option must match.
733
+ * Unlike regular unions that succeed when any option matches, xor fails if
734
+ * zero or more than one option matches the input. */
735
+ function xor(options, params) {
736
+ return new exports.ZodXor({
737
+ type: "union",
738
+ options: options,
739
+ inclusive: false,
740
+ ...index_js_1.util.normalizeParams(params),
741
+ });
742
+ }
724
743
  exports.ZodDiscriminatedUnion = core.$constructor("ZodDiscriminatedUnion", (inst, def) => {
725
744
  exports.ZodUnion.init(inst, def);
726
745
  core.$ZodDiscriminatedUnion.init(inst, def);
@@ -792,6 +811,15 @@ function partialRecord(keyType, valueType, params) {
792
811
  ...index_js_1.util.normalizeParams(params),
793
812
  });
794
813
  }
814
+ function looseRecord(keyType, valueType, params) {
815
+ return new exports.ZodRecord({
816
+ type: "record",
817
+ keyType,
818
+ valueType: valueType,
819
+ mode: "loose",
820
+ ...index_js_1.util.normalizeParams(params),
821
+ });
822
+ }
795
823
  exports.ZodMap = core.$constructor("ZodMap", (inst, def) => {
796
824
  core.$ZodMap.init(inst, def);
797
825
  exports.ZodType.init(inst, def);
@@ -472,6 +472,15 @@ export interface ZodUnion<T extends readonly core.SomeType[] = readonly core.$Zo
472
472
  }
473
473
  export declare const ZodUnion: core.$constructor<ZodUnion>;
474
474
  export declare function union<const T extends readonly core.SomeType[]>(options: T, params?: string | core.$ZodUnionParams): ZodUnion<T>;
475
+ export interface ZodXor<T extends readonly core.SomeType[] = readonly core.$ZodType[]> extends _ZodType<core.$ZodXorInternals<T>>, core.$ZodXor<T> {
476
+ "~standard": ZodStandardSchemaWithJSON<this>;
477
+ options: T;
478
+ }
479
+ export declare const ZodXor: core.$constructor<ZodXor>;
480
+ /** Creates an exclusive union (XOR) where exactly one option must match.
481
+ * Unlike regular unions that succeed when any option matches, xor fails if
482
+ * zero or more than one option matches the input. */
483
+ export declare function xor<const T extends readonly core.SomeType[]>(options: T, params?: string | core.$ZodXorParams): ZodXor<T>;
475
484
  export interface ZodDiscriminatedUnion<Options extends readonly core.SomeType[] = readonly core.$ZodType[], Disc extends string = string> extends ZodUnion<Options>, core.$ZodDiscriminatedUnion<Options, Disc> {
476
485
  "~standard": ZodStandardSchemaWithJSON<this>;
477
486
  _zod: core.$ZodDiscriminatedUnionInternals<Options, Disc>;
@@ -500,6 +509,7 @@ export interface ZodRecord<Key extends core.$ZodRecordKey = core.$ZodRecordKey,
500
509
  export declare const ZodRecord: core.$constructor<ZodRecord>;
501
510
  export declare function record<Key extends core.$ZodRecordKey, Value extends core.SomeType>(keyType: Key, valueType: Value, params?: string | core.$ZodRecordParams): ZodRecord<Key, Value>;
502
511
  export declare function partialRecord<Key extends core.$ZodRecordKey, Value extends core.SomeType>(keyType: Key, valueType: Value, params?: string | core.$ZodRecordParams): ZodRecord<Key & core.$partial, Value>;
512
+ export declare function looseRecord<Key extends core.$ZodRecordKey, Value extends core.SomeType>(keyType: Key, valueType: Value, params?: string | core.$ZodRecordParams): ZodRecord<Key, Value>;
503
513
  export interface ZodMap<Key extends core.SomeType = core.$ZodType, Value extends core.SomeType = core.$ZodType> extends _ZodType<core.$ZodMapInternals<Key, Value>>, core.$ZodMap<Key, Value> {
504
514
  "~standard": ZodStandardSchemaWithJSON<this>;
505
515
  keyType: Key;
@@ -472,6 +472,15 @@ export interface ZodUnion<T extends readonly core.SomeType[] = readonly core.$Zo
472
472
  }
473
473
  export declare const ZodUnion: core.$constructor<ZodUnion>;
474
474
  export declare function union<const T extends readonly core.SomeType[]>(options: T, params?: string | core.$ZodUnionParams): ZodUnion<T>;
475
+ export interface ZodXor<T extends readonly core.SomeType[] = readonly core.$ZodType[]> extends _ZodType<core.$ZodXorInternals<T>>, core.$ZodXor<T> {
476
+ "~standard": ZodStandardSchemaWithJSON<this>;
477
+ options: T;
478
+ }
479
+ export declare const ZodXor: core.$constructor<ZodXor>;
480
+ /** Creates an exclusive union (XOR) where exactly one option must match.
481
+ * Unlike regular unions that succeed when any option matches, xor fails if
482
+ * zero or more than one option matches the input. */
483
+ export declare function xor<const T extends readonly core.SomeType[]>(options: T, params?: string | core.$ZodXorParams): ZodXor<T>;
475
484
  export interface ZodDiscriminatedUnion<Options extends readonly core.SomeType[] = readonly core.$ZodType[], Disc extends string = string> extends ZodUnion<Options>, core.$ZodDiscriminatedUnion<Options, Disc> {
476
485
  "~standard": ZodStandardSchemaWithJSON<this>;
477
486
  _zod: core.$ZodDiscriminatedUnionInternals<Options, Disc>;
@@ -500,6 +509,7 @@ export interface ZodRecord<Key extends core.$ZodRecordKey = core.$ZodRecordKey,
500
509
  export declare const ZodRecord: core.$constructor<ZodRecord>;
501
510
  export declare function record<Key extends core.$ZodRecordKey, Value extends core.SomeType>(keyType: Key, valueType: Value, params?: string | core.$ZodRecordParams): ZodRecord<Key, Value>;
502
511
  export declare function partialRecord<Key extends core.$ZodRecordKey, Value extends core.SomeType>(keyType: Key, valueType: Value, params?: string | core.$ZodRecordParams): ZodRecord<Key & core.$partial, Value>;
512
+ export declare function looseRecord<Key extends core.$ZodRecordKey, Value extends core.SomeType>(keyType: Key, valueType: Value, params?: string | core.$ZodRecordParams): ZodRecord<Key, Value>;
503
513
  export interface ZodMap<Key extends core.SomeType = core.$ZodType, Value extends core.SomeType = core.$ZodType> extends _ZodType<core.$ZodMapInternals<Key, Value>>, core.$ZodMap<Key, Value> {
504
514
  "~standard": ZodStandardSchemaWithJSON<this>;
505
515
  keyType: Key;
@@ -606,6 +606,23 @@ export function union(options, params) {
606
606
  ...util.normalizeParams(params),
607
607
  });
608
608
  }
609
+ export const ZodXor = /*@__PURE__*/ core.$constructor("ZodXor", (inst, def) => {
610
+ ZodUnion.init(inst, def);
611
+ core.$ZodXor.init(inst, def);
612
+ inst._zod.processJSONSchema = (ctx, json, params) => processors.unionProcessor(inst, ctx, json, params);
613
+ inst.options = def.options;
614
+ });
615
+ /** Creates an exclusive union (XOR) where exactly one option must match.
616
+ * Unlike regular unions that succeed when any option matches, xor fails if
617
+ * zero or more than one option matches the input. */
618
+ export function xor(options, params) {
619
+ return new ZodXor({
620
+ type: "union",
621
+ options: options,
622
+ inclusive: false,
623
+ ...util.normalizeParams(params),
624
+ });
625
+ }
609
626
  export const ZodDiscriminatedUnion = /*@__PURE__*/ core.$constructor("ZodDiscriminatedUnion", (inst, def) => {
610
627
  ZodUnion.init(inst, def);
611
628
  core.$ZodDiscriminatedUnion.init(inst, def);
@@ -677,6 +694,15 @@ export function partialRecord(keyType, valueType, params) {
677
694
  ...util.normalizeParams(params),
678
695
  });
679
696
  }
697
+ export function looseRecord(keyType, valueType, params) {
698
+ return new ZodRecord({
699
+ type: "record",
700
+ keyType,
701
+ valueType: valueType,
702
+ mode: "loose",
703
+ ...util.normalizeParams(params),
704
+ });
705
+ }
680
706
  export const ZodMap = /*@__PURE__*/ core.$constructor("ZodMap", (inst, def) => {
681
707
  core.$ZodMap.init(inst, def);
682
708
  ZodType.init(inst, def);
package/v4/core/api.cjs CHANGED
@@ -113,6 +113,7 @@ exports._toUpperCase = _toUpperCase;
113
113
  exports._slugify = _slugify;
114
114
  exports._array = _array;
115
115
  exports._union = _union;
116
+ exports._xor = _xor;
116
117
  exports._discriminatedUnion = _discriminatedUnion;
117
118
  exports._intersection = _intersection;
118
119
  exports._tuple = _tuple;
@@ -777,6 +778,14 @@ function _union(Class, options, params) {
777
778
  ...util.normalizeParams(params),
778
779
  });
779
780
  }
781
+ function _xor(Class, options, params) {
782
+ return new Class({
783
+ type: "union",
784
+ options,
785
+ inclusive: false,
786
+ ...util.normalizeParams(params),
787
+ });
788
+ }
780
789
  function _discriminatedUnion(Class, discriminator, options, params) {
781
790
  return new Class({
782
791
  type: "union",
package/v4/core/api.d.cts CHANGED
@@ -208,6 +208,8 @@ export declare function _array<T extends schemas.$ZodType>(Class: util.SchemaCla
208
208
  export type $ZodObjectParams = TypeParams<schemas.$ZodObject, "shape" | "catchall">;
209
209
  export type $ZodUnionParams = TypeParams<schemas.$ZodUnion, "options">;
210
210
  export declare function _union<const T extends readonly schemas.$ZodObject[]>(Class: util.SchemaClass<schemas.$ZodUnion>, options: T, params?: string | $ZodUnionParams): schemas.$ZodUnion<T>;
211
+ export type $ZodXorParams = TypeParams<schemas.$ZodXor, "options">;
212
+ export declare function _xor<const T extends readonly schemas.$ZodObject[]>(Class: util.SchemaClass<schemas.$ZodXor>, options: T, params?: string | $ZodXorParams): schemas.$ZodXor<T>;
211
213
  export interface $ZodTypeDiscriminableInternals extends schemas.$ZodTypeInternals {
212
214
  propValues: util.PropValues;
213
215
  }