@orpc/zod 0.45.1 → 0.47.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.
package/dist/index.mjs CHANGED
@@ -1,336 +1,17 @@
1
- import { guard, isObject } from '@orpc/shared';
2
- import { getCustomZodType as getCustomZodType$1 } from '@orpc/zod';
3
- import { ZodFirstPartyTypeKind, custom } from 'zod';
1
+ import { custom, ZodFirstPartyTypeKind } from 'zod';
2
+ import wcmatch from 'wildcard-match';
3
+ import { isObject, guard } from '@orpc/shared';
4
4
  import { JSONSchemaFormat } from '@orpc/openapi';
5
5
  import escapeStringRegexp from 'escape-string-regexp';
6
- import wcmatch from 'wildcard-match';
7
-
8
- class ZodSmartCoercionPlugin {
9
- init(options) {
10
- options.clientInterceptors ??= [];
11
- options.clientInterceptors.unshift((options2) => {
12
- const inputSchema = options2.procedure["~orpc"].inputSchema;
13
- if (!inputSchema || inputSchema["~standard"].vendor !== "zod") {
14
- return options2.next();
15
- }
16
- const coercedInput = zodCoerceInternal(inputSchema, options2.input, { bracketNotation: true });
17
- return options2.next({ ...options2, input: coercedInput });
18
- });
19
- }
20
- }
21
- function zodCoerceInternal(schema, value, options) {
22
- const isRoot = options?.isRoot ?? true;
23
- const options_ = { ...options, isRoot: false };
24
- if (isRoot && options?.bracketNotation && Array.isArray(value) && value.length === 1) {
25
- const newValue = zodCoerceInternal(schema, value[0], options_);
26
- if (schema.safeParse(newValue).success) {
27
- return newValue;
28
- }
29
- return zodCoerceInternal(schema, value, options_);
30
- }
31
- const customType = getCustomZodType$1(schema._def);
32
- if (customType === "Invalid Date") {
33
- if (typeof value === "string" && value.toLocaleLowerCase() === "invalid date") {
34
- return /* @__PURE__ */ new Date("Invalid Date");
35
- }
36
- } else if (customType === "RegExp") {
37
- if (typeof value === "string" && value.startsWith("/")) {
38
- const match = value.match(/^\/(.*)\/([a-z]*)$/);
39
- if (match) {
40
- const [, pattern, flags] = match;
41
- return new RegExp(pattern, flags);
42
- }
43
- }
44
- } else if (customType === "URL") {
45
- if (typeof value === "string") {
46
- const url = guard(() => new URL(value));
47
- if (url !== void 0) {
48
- return url;
49
- }
50
- }
51
- }
52
- if (schema._def.typeName === void 0) {
53
- return value;
54
- }
55
- const typeName = schema._def.typeName;
56
- if (typeName === ZodFirstPartyTypeKind.ZodNumber) {
57
- if (options_?.bracketNotation && typeof value === "string") {
58
- const num = Number(value);
59
- if (!Number.isNaN(num)) {
60
- return num;
61
- }
62
- }
63
- } else if (typeName === ZodFirstPartyTypeKind.ZodNaN) {
64
- if (typeof value === "string" && value.toLocaleLowerCase() === "nan") {
65
- return Number.NaN;
66
- }
67
- } else if (typeName === ZodFirstPartyTypeKind.ZodBoolean) {
68
- if (options_?.bracketNotation && typeof value === "string") {
69
- const lower = value.toLowerCase();
70
- if (lower === "false" || lower === "off" || lower === "f") {
71
- return false;
72
- }
73
- if (lower === "true" || lower === "on" || lower === "t") {
74
- return true;
75
- }
76
- }
77
- } else if (typeName === ZodFirstPartyTypeKind.ZodNull) {
78
- if (options_?.bracketNotation && typeof value === "string" && value.toLowerCase() === "null") {
79
- return null;
80
- }
81
- } else if (typeName === ZodFirstPartyTypeKind.ZodUndefined || typeName === ZodFirstPartyTypeKind.ZodVoid) {
82
- if (typeof value === "string" && value.toLowerCase() === "undefined") {
83
- return void 0;
84
- }
85
- } else if (typeName === ZodFirstPartyTypeKind.ZodDate) {
86
- if (typeof value === "string" && (value.includes("-") || value.includes(":") || value.toLocaleLowerCase() === "invalid date")) {
87
- return new Date(value);
88
- }
89
- } else if (typeName === ZodFirstPartyTypeKind.ZodBigInt) {
90
- if (typeof value === "string") {
91
- const num = guard(() => BigInt(value));
92
- if (num !== void 0) {
93
- return num;
94
- }
95
- }
96
- } else if (typeName === ZodFirstPartyTypeKind.ZodArray || typeName === ZodFirstPartyTypeKind.ZodTuple) {
97
- const schema_ = schema;
98
- if (Array.isArray(value)) {
99
- return value.map((v) => zodCoerceInternal(schema_._def.type, v, options_));
100
- }
101
- if (options_?.bracketNotation) {
102
- if (value === void 0) {
103
- return [];
104
- }
105
- if (isObject(value) && Object.keys(value).every((k) => /^[1-9]\d*$/.test(k) || k === "0")) {
106
- const indexes = Object.keys(value).map((k) => Number(k)).sort((a, b) => a - b);
107
- const arr = Array.from({ length: (indexes.at(-1) ?? -1) + 1 });
108
- for (const i of indexes) {
109
- arr[i] = zodCoerceInternal(schema_._def.type, value[i], options_);
110
- }
111
- return arr;
112
- }
113
- }
114
- } else if (typeName === ZodFirstPartyTypeKind.ZodObject) {
115
- const schema_ = schema;
116
- if (isObject(value)) {
117
- const newObj = {};
118
- const keys = /* @__PURE__ */ new Set([
119
- ...Object.keys(value),
120
- ...Object.keys(schema_.shape)
121
- ]);
122
- for (const k of keys) {
123
- if (!(k in value))
124
- continue;
125
- const v = value[k];
126
- newObj[k] = zodCoerceInternal(
127
- schema_.shape[k] ?? schema_._def.catchall,
128
- v,
129
- options_
130
- );
131
- }
132
- return newObj;
133
- }
134
- if (options_?.bracketNotation) {
135
- if (value === void 0) {
136
- return {};
137
- }
138
- if (Array.isArray(value) && value.length === 1) {
139
- const emptySchema = schema_.shape[""] ?? schema_._def.catchall;
140
- return { "": zodCoerceInternal(emptySchema, value[0], options_) };
141
- }
142
- }
143
- } else if (typeName === ZodFirstPartyTypeKind.ZodSet) {
144
- const schema_ = schema;
145
- if (Array.isArray(value)) {
146
- return new Set(
147
- value.map((v) => zodCoerceInternal(schema_._def.valueType, v, options_))
148
- );
149
- }
150
- if (options_?.bracketNotation) {
151
- if (value === void 0) {
152
- return /* @__PURE__ */ new Set();
153
- }
154
- if (isObject(value) && Object.keys(value).every((k) => /^[1-9]\d*$/.test(k) || k === "0")) {
155
- const indexes = Object.keys(value).map((k) => Number(k)).sort((a, b) => a - b);
156
- const arr = Array.from({ length: (indexes.at(-1) ?? -1) + 1 });
157
- for (const i of indexes) {
158
- arr[i] = zodCoerceInternal(schema_._def.valueType, value[i], options_);
159
- }
160
- return new Set(arr);
161
- }
162
- }
163
- } else if (typeName === ZodFirstPartyTypeKind.ZodMap) {
164
- const schema_ = schema;
165
- if (Array.isArray(value) && value.every((i) => Array.isArray(i) && i.length === 2)) {
166
- return new Map(
167
- value.map(([k, v]) => [
168
- zodCoerceInternal(schema_._def.keyType, k, options_),
169
- zodCoerceInternal(schema_._def.valueType, v, options_)
170
- ])
171
- );
172
- }
173
- if (options_?.bracketNotation) {
174
- if (value === void 0) {
175
- return /* @__PURE__ */ new Map();
176
- }
177
- if (isObject(value)) {
178
- const arr = Array.from({ length: Object.keys(value).length }).fill(void 0).map(
179
- (_, i) => isObject(value[i]) && Object.keys(value[i]).length === 2 && "0" in value[i] && "1" in value[i] ? [value[i]["0"], value[i]["1"]] : void 0
180
- );
181
- if (arr.every((v) => !!v)) {
182
- return new Map(
183
- arr.map(([k, v]) => [
184
- zodCoerceInternal(schema_._def.keyType, k, options_),
185
- zodCoerceInternal(schema_._def.valueType, v, options_)
186
- ])
187
- );
188
- }
189
- }
190
- }
191
- } else if (typeName === ZodFirstPartyTypeKind.ZodRecord) {
192
- const schema_ = schema;
193
- if (isObject(value)) {
194
- const newObj = {};
195
- for (const [k, v] of Object.entries(value)) {
196
- const key = zodCoerceInternal(schema_._def.keyType, k, options_);
197
- const val = zodCoerceInternal(schema_._def.valueType, v, options_);
198
- newObj[key] = val;
199
- }
200
- return newObj;
201
- }
202
- } else if (typeName === ZodFirstPartyTypeKind.ZodUnion || typeName === ZodFirstPartyTypeKind.ZodDiscriminatedUnion) {
203
- const schema_ = schema;
204
- if (schema_.safeParse(value).success) {
205
- return value;
206
- }
207
- const results = [];
208
- for (const s of schema_._def.options) {
209
- const newValue = zodCoerceInternal(s, value, { ...options_, isRoot });
210
- if (newValue === value)
211
- continue;
212
- const result = schema_.safeParse(newValue);
213
- if (result.success) {
214
- return newValue;
215
- }
216
- results.push([newValue, result.error.issues.length]);
217
- }
218
- if (results.length === 0) {
219
- return value;
220
- }
221
- return results.sort((a, b) => a[1] - b[1])[0]?.[0];
222
- } else if (typeName === ZodFirstPartyTypeKind.ZodIntersection) {
223
- const schema_ = schema;
224
- return zodCoerceInternal(
225
- schema_._def.right,
226
- zodCoerceInternal(schema_._def.left, value, { ...options_, isRoot }),
227
- { ...options_, isRoot }
228
- );
229
- } else if (typeName === ZodFirstPartyTypeKind.ZodReadonly) {
230
- const schema_ = schema;
231
- return zodCoerceInternal(schema_._def.innerType, value, { ...options_, isRoot });
232
- } else if (typeName === ZodFirstPartyTypeKind.ZodPipeline) {
233
- const schema_ = schema;
234
- return zodCoerceInternal(schema_._def.in, value, { ...options_, isRoot });
235
- } else if (typeName === ZodFirstPartyTypeKind.ZodLazy) {
236
- const schema_ = schema;
237
- return zodCoerceInternal(schema_._def.getter(), value, { ...options_, isRoot });
238
- } else if (typeName === ZodFirstPartyTypeKind.ZodEffects) {
239
- const schema_ = schema;
240
- return zodCoerceInternal(schema_._def.schema, value, { ...options_, isRoot });
241
- } else if (typeName === ZodFirstPartyTypeKind.ZodBranded) {
242
- const schema_ = schema;
243
- return zodCoerceInternal(schema_._def.type, value, { ...options_, isRoot });
244
- } else if (typeName === ZodFirstPartyTypeKind.ZodCatch) {
245
- const schema_ = schema;
246
- return zodCoerceInternal(schema_._def.innerType, value, { ...options_, isRoot });
247
- } else if (typeName === ZodFirstPartyTypeKind.ZodDefault) {
248
- const schema_ = schema;
249
- return zodCoerceInternal(schema_._def.innerType, value, { ...options_, isRoot });
250
- } else if (typeName === ZodFirstPartyTypeKind.ZodNullable) {
251
- const schema_ = schema;
252
- if (value === null) {
253
- return null;
254
- }
255
- if (typeof value === "string" && value.toLowerCase() === "null") {
256
- return schema_.safeParse(value).success ? value : null;
257
- }
258
- return zodCoerceInternal(schema_._def.innerType, value, { ...options_, isRoot });
259
- } else if (typeName === ZodFirstPartyTypeKind.ZodOptional) {
260
- const schema_ = schema;
261
- if (value === void 0) {
262
- return void 0;
263
- }
264
- if (typeof value === "string" && value.toLowerCase() === "undefined") {
265
- return schema_.safeParse(value).success ? value : void 0;
266
- }
267
- return zodCoerceInternal(schema_._def.innerType, value, { ...options_, isRoot });
268
- } else if (typeName === ZodFirstPartyTypeKind.ZodNativeEnum) {
269
- const schema_ = schema;
270
- if (Object.values(schema_._def.values).includes(value)) {
271
- return value;
272
- }
273
- if (options?.bracketNotation && typeof value === "string") {
274
- for (const expectedValue of Object.values(schema_._def.values)) {
275
- if (expectedValue.toString() === value) {
276
- return expectedValue;
277
- }
278
- }
279
- }
280
- } else if (typeName === ZodFirstPartyTypeKind.ZodLiteral) {
281
- const schema_ = schema;
282
- const expectedValue = schema_._def.value;
283
- if (typeof value === "string" && typeof expectedValue !== "string") {
284
- if (typeof expectedValue === "bigint") {
285
- const num = guard(() => BigInt(value));
286
- if (num !== void 0) {
287
- return num;
288
- }
289
- } else if (expectedValue === void 0) {
290
- if (value.toLocaleLowerCase() === "undefined") {
291
- return void 0;
292
- }
293
- } else if (options?.bracketNotation) {
294
- if (typeof expectedValue === "number") {
295
- const num = Number(value);
296
- if (!Number.isNaN(num)) {
297
- return num;
298
- }
299
- } else if (typeof expectedValue === "boolean") {
300
- const lower = value.toLowerCase();
301
- if (lower === "false" || lower === "off" || lower === "f") {
302
- return false;
303
- }
304
- if (lower === "true" || lower === "on" || lower === "t") {
305
- return true;
306
- }
307
- } else if (expectedValue === null) {
308
- if (value.toLocaleLowerCase() === "null") {
309
- return null;
310
- }
311
- }
312
- }
313
- }
314
- } else ;
315
- return value;
316
- }
317
6
 
318
- const customZodTypeSymbol = Symbol("customZodTypeSymbol");
319
- const customZodFileMimeTypeSymbol = Symbol("customZodFileMimeTypeSymbol");
320
- const CUSTOM_JSON_SCHEMA_SYMBOL = Symbol("CUSTOM_JSON_SCHEMA");
321
- const CUSTOM_JSON_SCHEMA_INPUT_SYMBOL = Symbol("CUSTOM_JSON_SCHEMA_INPUT");
322
- const CUSTOM_JSON_SCHEMA_OUTPUT_SYMBOL = Symbol("CUSTOM_JSON_SCHEMA_OUTPUT");
323
- function getCustomZodType(def) {
324
- return customZodTypeSymbol in def ? def[customZodTypeSymbol] : void 0;
325
- }
326
- function getCustomZodFileMimeType(def) {
327
- return customZodFileMimeTypeSymbol in def ? def[customZodFileMimeTypeSymbol] : void 0;
328
- }
329
- function getCustomJSONSchema(def, options) {
330
- if (options?.mode === "input" && CUSTOM_JSON_SCHEMA_INPUT_SYMBOL in def) {
7
+ const CUSTOM_JSON_SCHEMA_SYMBOL = Symbol("ORPC_CUSTOM_JSON_SCHEMA");
8
+ const CUSTOM_JSON_SCHEMA_INPUT_SYMBOL = Symbol("ORPC_CUSTOM_JSON_SCHEMA_INPUT");
9
+ const CUSTOM_JSON_SCHEMA_OUTPUT_SYMBOL = Symbol("ORPC_CUSTOM_JSON_SCHEMA_OUTPUT");
10
+ function getCustomJsonSchema(def, options) {
11
+ if (options.strategy === "input" && CUSTOM_JSON_SCHEMA_INPUT_SYMBOL in def) {
331
12
  return def[CUSTOM_JSON_SCHEMA_INPUT_SYMBOL];
332
13
  }
333
- if (options?.mode === "output" && CUSTOM_JSON_SCHEMA_OUTPUT_SYMBOL in def) {
14
+ if (options.strategy === "output" && CUSTOM_JSON_SCHEMA_OUTPUT_SYMBOL in def) {
334
15
  return def[CUSTOM_JSON_SCHEMA_OUTPUT_SYMBOL];
335
16
  }
336
17
  if (CUSTOM_JSON_SCHEMA_SYMBOL in def) {
@@ -338,571 +19,799 @@ function getCustomJSONSchema(def, options) {
338
19
  }
339
20
  return void 0;
340
21
  }
341
- function composeParams(options) {
22
+ function customJsonSchema(schema, custom, options = {}) {
23
+ const SYMBOL = options.strategy === "input" ? CUSTOM_JSON_SCHEMA_INPUT_SYMBOL : options.strategy === "output" ? CUSTOM_JSON_SCHEMA_OUTPUT_SYMBOL : CUSTOM_JSON_SCHEMA_SYMBOL;
24
+ const This = schema.constructor;
25
+ const newSchema = new This({
26
+ ...schema._def,
27
+ [SYMBOL]: custom
28
+ });
29
+ return newSchema;
30
+ }
31
+
32
+ const CUSTOM_ZOD_DEF_SYMBOL = Symbol("ORPC_CUSTOM_ZOD_DEF");
33
+ function setCustomZodDef(def, custom) {
34
+ Object.assign(def, { [CUSTOM_ZOD_DEF_SYMBOL]: custom });
35
+ }
36
+ function getCustomZodDef(def) {
37
+ return def[CUSTOM_ZOD_DEF_SYMBOL];
38
+ }
39
+ function composeParams(defaultMessage, params) {
342
40
  return (val) => {
343
- const defaultMessage = typeof options.defaultMessage === "function" ? options.defaultMessage(val) : options.defaultMessage;
344
- if (!options.params) {
41
+ const message = defaultMessage(val);
42
+ if (!params) {
345
43
  return {
346
- message: defaultMessage
44
+ message
347
45
  };
348
46
  }
349
- if (typeof options.params === "function") {
47
+ if (typeof params === "function") {
350
48
  return {
351
- message: defaultMessage,
352
- ...options.params(val)
49
+ message,
50
+ ...params(val)
353
51
  };
354
52
  }
355
- if (typeof options.params === "object") {
53
+ if (typeof params === "object") {
356
54
  return {
357
- message: defaultMessage,
358
- ...options.params
55
+ message,
56
+ ...params
359
57
  };
360
58
  }
361
59
  return {
362
- message: options.params
60
+ message: params
363
61
  };
364
62
  };
365
63
  }
64
+
65
+ function blob(params) {
66
+ const schema = custom(
67
+ (val) => val instanceof Blob,
68
+ composeParams(
69
+ () => "Input is not a blob",
70
+ params
71
+ )
72
+ );
73
+ setCustomZodDef(schema._def, { type: "blob" });
74
+ return schema;
75
+ }
76
+
366
77
  function file(params) {
367
78
  const schema = custom(
368
79
  (val) => val instanceof File,
369
- composeParams({ params, defaultMessage: "Input is not a file" })
80
+ composeParams(
81
+ () => "Input is not a file",
82
+ params
83
+ )
370
84
  );
371
- Object.assign(schema._def, {
372
- [customZodTypeSymbol]: "File"
373
- });
85
+ setCustomZodDef(schema._def, { type: "file" });
374
86
  return Object.assign(schema, {
375
87
  type: (mimeType, params2) => {
376
88
  const isMatch = wcmatch(mimeType);
377
89
  const refinedSchema = schema.refine(
378
90
  (val) => isMatch(val.type.split(";")[0]),
379
- composeParams({
380
- params: params2,
381
- defaultMessage: (val) => `Expected a file of type ${mimeType} but got a file of type ${val.type || "unknown"}`
382
- })
91
+ composeParams(
92
+ (val) => `Expected a file of type ${mimeType} but got a file of type ${val.type || "unknown"}`,
93
+ params2
94
+ )
383
95
  );
384
- Object.assign(refinedSchema._def, {
385
- [customZodTypeSymbol]: "File",
386
- [customZodFileMimeTypeSymbol]: mimeType
387
- });
96
+ setCustomZodDef(refinedSchema._def, { type: "file", mimeType });
388
97
  return refinedSchema;
389
98
  }
390
99
  });
391
100
  }
392
- function blob(params) {
393
- const schema = custom(
394
- (val) => val instanceof Blob,
395
- composeParams({ params, defaultMessage: "Input is not a blob" })
396
- );
397
- Object.assign(schema._def, {
398
- [customZodTypeSymbol]: "Blob"
399
- });
400
- return schema;
401
- }
402
- function invalidDate(params) {
403
- const schema = custom(
404
- (val) => val instanceof Date && Number.isNaN(val.getTime()),
405
- composeParams({ params, defaultMessage: "Input is not an invalid date" })
406
- );
407
- Object.assign(schema._def, {
408
- [customZodTypeSymbol]: "Invalid Date"
409
- });
410
- return schema;
411
- }
412
- function regexp(options) {
101
+
102
+ function regexp(params) {
413
103
  const schema = custom(
414
104
  (val) => val instanceof RegExp,
415
- composeParams({ params: options, defaultMessage: "Input is not a regexp" })
105
+ composeParams(
106
+ () => "Input is not a regexp",
107
+ params
108
+ )
416
109
  );
417
- Object.assign(schema._def, {
418
- [customZodTypeSymbol]: "RegExp"
419
- });
110
+ setCustomZodDef(schema._def, { type: "regexp" });
420
111
  return schema;
421
112
  }
422
- function url(options) {
113
+
114
+ function url(params) {
423
115
  const schema = custom(
424
116
  (val) => val instanceof URL,
425
- composeParams({ params: options, defaultMessage: "Input is not a URL" })
117
+ composeParams(
118
+ () => "Input is not a URL",
119
+ params
120
+ )
426
121
  );
427
- Object.assign(schema._def, {
428
- [customZodTypeSymbol]: "URL"
429
- });
122
+ setCustomZodDef(schema._def, { type: "url" });
430
123
  return schema;
431
124
  }
432
- function openapi(schema, custom2, options) {
433
- const newSchema = schema.refine(() => true);
434
- const SYMBOL = options?.mode === "input" ? CUSTOM_JSON_SCHEMA_INPUT_SYMBOL : options?.mode === "output" ? CUSTOM_JSON_SCHEMA_OUTPUT_SYMBOL : CUSTOM_JSON_SCHEMA_SYMBOL;
435
- Object.assign(newSchema._def, {
436
- [SYMBOL]: custom2
437
- });
438
- return newSchema;
439
- }
440
- const oz = {
441
- openapi,
442
- file,
443
- blob,
444
- invalidDate,
445
- regexp,
446
- url
447
- };
448
125
 
449
- const NON_LOGIC_KEYWORDS = [
450
- // Core Documentation Keywords
451
- "$anchor",
452
- "$comment",
453
- "$defs",
454
- "$id",
455
- "title",
456
- "description",
457
- // Value Keywords
458
- "default",
459
- "deprecated",
460
- "examples",
461
- // Metadata Keywords
462
- "$schema",
463
- "definitions",
464
- // Legacy, but still used
465
- "readOnly",
466
- "writeOnly",
467
- // Display and UI Hints
468
- "contentMediaType",
469
- "contentEncoding",
470
- "format",
471
- // Custom Extensions
472
- "$vocabulary",
473
- "$dynamicAnchor",
474
- "$dynamicRef"
475
- ];
476
- const UNSUPPORTED_JSON_SCHEMA = { not: {} };
477
- const UNDEFINED_JSON_SCHEMA = { const: "undefined" };
478
- function zodToJsonSchema(schema, options) {
479
- if (schema["~standard"].vendor !== "zod") {
480
- console.warn(`Generate JSON schema not support ${schema["~standard"].vendor} yet`);
481
- return {};
482
- }
483
- const schema__ = schema;
484
- if (!options?.isHandledZodDescription && "description" in schema__._def) {
485
- const json = zodToJsonSchema(schema__, {
486
- ...options,
487
- isHandledZodDescription: true
126
+ class ZodSmartCoercionPlugin {
127
+ init(options) {
128
+ options.clientInterceptors ??= [];
129
+ options.clientInterceptors.unshift((options2) => {
130
+ const inputSchema = options2.procedure["~orpc"].inputSchema;
131
+ if (!inputSchema || inputSchema["~standard"].vendor !== "zod") {
132
+ return options2.next();
133
+ }
134
+ const coercedInput = zodCoerceInternal(inputSchema, options2.input);
135
+ return options2.next({ ...options2, input: coercedInput });
488
136
  });
489
- return {
490
- description: schema__._def.description,
491
- ...json
492
- };
493
137
  }
494
- if (!options?.isHandledCustomJSONSchema) {
495
- const customJSONSchema = getCustomJSONSchema(schema__._def, options);
496
- if (customJSONSchema) {
497
- const json = zodToJsonSchema(schema__, {
498
- ...options,
499
- isHandledCustomJSONSchema: true
500
- });
501
- return {
502
- ...json,
503
- ...customJSONSchema
504
- };
505
- }
506
- }
507
- const childOptions = { ...options, isHandledCustomJSONSchema: false, isHandledZodDescription: false };
508
- const customType = getCustomZodType(schema__._def);
509
- switch (customType) {
510
- case "Blob": {
511
- return { type: "string", contentMediaType: "*/*" };
512
- }
513
- case "File": {
514
- const mimeType = getCustomZodFileMimeType(schema__._def) ?? "*/*";
515
- return { type: "string", contentMediaType: mimeType };
516
- }
517
- case "Invalid Date": {
518
- return { const: "Invalid Date" };
519
- }
520
- case "RegExp": {
521
- return {
522
- type: "string",
523
- pattern: "^\\/(.*)\\/([a-z]*)$"
524
- };
138
+ }
139
+ function zodCoerceInternal(schema, value) {
140
+ const customZodDef = getCustomZodDef(schema._def);
141
+ switch (customZodDef?.type) {
142
+ case "regexp": {
143
+ if (typeof value === "string") {
144
+ return safeToRegExp(value);
145
+ }
146
+ return value;
525
147
  }
526
- case "URL": {
527
- return { type: "string", format: JSONSchemaFormat.URI };
148
+ case "url": {
149
+ if (typeof value === "string") {
150
+ return safeToURL(value);
151
+ }
152
+ return value;
528
153
  }
529
154
  }
530
- const typeName = schema__._def.typeName;
155
+ const typeName = schema._def.typeName;
531
156
  switch (typeName) {
532
- case ZodFirstPartyTypeKind.ZodString: {
533
- const schema_ = schema__;
534
- const json = { type: "string" };
535
- for (const check of schema_._def.checks) {
536
- switch (check.kind) {
537
- case "base64":
538
- json.contentEncoding = "base64";
539
- break;
540
- case "cuid":
541
- json.pattern = "^[0-9A-HJKMNP-TV-Z]{26}$";
542
- break;
543
- case "email":
544
- json.format = JSONSchemaFormat.Email;
545
- break;
546
- case "url":
547
- json.format = JSONSchemaFormat.URI;
548
- break;
549
- case "uuid":
550
- json.format = JSONSchemaFormat.UUID;
551
- break;
552
- case "regex":
553
- json.pattern = check.regex.source;
554
- break;
555
- case "min":
556
- json.minLength = check.value;
557
- break;
558
- case "max":
559
- json.maxLength = check.value;
560
- break;
561
- case "length":
562
- json.minLength = check.value;
563
- json.maxLength = check.value;
564
- break;
565
- case "includes":
566
- json.pattern = escapeStringRegexp(check.value);
567
- break;
568
- case "startsWith":
569
- json.pattern = `^${escapeStringRegexp(check.value)}`;
570
- break;
571
- case "endsWith":
572
- json.pattern = `${escapeStringRegexp(check.value)}$`;
573
- break;
574
- case "emoji":
575
- json.pattern = "^(\\p{Extended_Pictographic}|\\p{Emoji_Component})+$";
576
- break;
577
- case "nanoid":
578
- json.pattern = "^[a-zA-Z0-9_-]{21}$";
579
- break;
580
- case "cuid2":
581
- json.pattern = "^[0-9a-z]+$";
582
- break;
583
- case "ulid":
584
- json.pattern = "^[0-9A-HJKMNP-TV-Z]{26}$";
585
- break;
586
- case "datetime":
587
- json.format = JSONSchemaFormat.DateTime;
588
- break;
589
- case "date":
590
- json.format = JSONSchemaFormat.Date;
591
- break;
592
- case "time":
593
- json.format = JSONSchemaFormat.Time;
594
- break;
595
- case "duration":
596
- json.format = JSONSchemaFormat.Duration;
597
- break;
598
- case "ip":
599
- json.format = JSONSchemaFormat.IPv4;
600
- break;
601
- case "jwt":
602
- json.pattern = "^[A-Za-z0-9-_]+\\.[A-Za-z0-9-_]+\\.[A-Za-z0-9-_]*$";
603
- break;
604
- case "base64url":
605
- json.pattern = "^([0-9a-zA-Z-_]{4})*(([0-9a-zA-Z-_]{2}(==)?)|([0-9a-zA-Z-_]{3}(=)?))?$";
606
- break;
607
- default: {
608
- check.kind;
609
- }
610
- }
611
- }
612
- return json;
613
- }
614
157
  case ZodFirstPartyTypeKind.ZodNumber: {
615
- const schema_ = schema__;
616
- const json = { type: "number" };
617
- for (const check of schema_._def.checks) {
618
- switch (check.kind) {
619
- case "int":
620
- json.type = "integer";
621
- break;
622
- case "min":
623
- json.minimum = check.value;
624
- break;
625
- case "max":
626
- json.maximum = check.value;
627
- break;
628
- case "multipleOf":
629
- json.multipleOf = check.value;
630
- break;
631
- default: {
632
- check.kind;
633
- }
634
- }
158
+ if (typeof value === "string") {
159
+ return safeToNumber(value);
635
160
  }
636
- return json;
637
- }
638
- case ZodFirstPartyTypeKind.ZodNaN: {
639
- return { const: "NaN" };
161
+ return value;
640
162
  }
641
163
  case ZodFirstPartyTypeKind.ZodBigInt: {
642
- const json = { type: "string", pattern: "^-?[0-9]+$" };
643
- return json;
164
+ if (typeof value === "string") {
165
+ return safeToBigInt(value);
166
+ }
167
+ return value;
644
168
  }
645
169
  case ZodFirstPartyTypeKind.ZodBoolean: {
646
- return { type: "boolean" };
170
+ if (typeof value === "string") {
171
+ return safeToBoolean(value);
172
+ }
173
+ return value;
647
174
  }
648
175
  case ZodFirstPartyTypeKind.ZodDate: {
649
- const schema2 = { type: "string", format: JSONSchemaFormat.Date };
650
- return schema2;
651
- }
652
- case ZodFirstPartyTypeKind.ZodNull: {
653
- return { type: "null" };
654
- }
655
- case ZodFirstPartyTypeKind.ZodVoid:
656
- case ZodFirstPartyTypeKind.ZodUndefined: {
657
- return UNDEFINED_JSON_SCHEMA;
176
+ if (typeof value === "string") {
177
+ return safeToDate(value);
178
+ }
179
+ return value;
658
180
  }
659
181
  case ZodFirstPartyTypeKind.ZodLiteral: {
660
- const schema_ = schema__;
661
- return { const: schema_._def.value };
662
- }
663
- case ZodFirstPartyTypeKind.ZodEnum: {
664
- const schema_ = schema__;
665
- return {
666
- enum: schema_._def.values
667
- };
668
- }
669
- case ZodFirstPartyTypeKind.ZodNativeEnum: {
670
- const schema_ = schema__;
671
- return {
672
- enum: Object.values(schema_._def.values)
673
- };
674
- }
675
- case ZodFirstPartyTypeKind.ZodArray: {
676
- const schema_ = schema__;
677
- const def = schema_._def;
678
- const json = { type: "array" };
679
- json.items = zodToJsonSchema(def.type, childOptions);
680
- if (def.exactLength) {
681
- json.maxItems = def.exactLength.value;
682
- json.minItems = def.exactLength.value;
683
- }
684
- if (def.minLength) {
685
- json.minItems = def.minLength.value;
686
- }
687
- if (def.maxLength) {
688
- json.maxItems = def.maxLength.value;
182
+ const schema_ = schema;
183
+ const expectedValue = schema_._def.value;
184
+ if (typeof value === "string" && typeof expectedValue !== "string") {
185
+ if (typeof expectedValue === "bigint") {
186
+ return safeToBigInt(value);
187
+ } else if (typeof expectedValue === "number") {
188
+ return safeToNumber(value);
189
+ } else if (typeof expectedValue === "boolean") {
190
+ return safeToBoolean(value);
191
+ }
689
192
  }
690
- return json;
193
+ return value;
691
194
  }
692
- case ZodFirstPartyTypeKind.ZodTuple: {
693
- const schema_ = schema__;
694
- const prefixItems = [];
695
- const json = { type: "array" };
696
- for (const item of schema_._def.items) {
697
- prefixItems.push(zodToJsonSchema(item, childOptions));
698
- }
699
- if (prefixItems?.length) {
700
- json.prefixItems = prefixItems;
701
- }
702
- if (schema_._def.rest) {
703
- const items = zodToJsonSchema(schema_._def.rest, childOptions);
704
- if (items) {
705
- json.items = items;
195
+ case ZodFirstPartyTypeKind.ZodNativeEnum: {
196
+ const schema_ = schema;
197
+ if (Object.values(schema_._def.values).includes(value)) {
198
+ return value;
199
+ }
200
+ if (typeof value === "string") {
201
+ for (const expectedValue of Object.values(schema_._def.values)) {
202
+ if (expectedValue.toString() === value) {
203
+ return expectedValue;
204
+ }
706
205
  }
707
206
  }
708
- return json;
207
+ return value;
709
208
  }
710
209
  case ZodFirstPartyTypeKind.ZodObject: {
711
- const schema_ = schema__;
712
- const json = { type: "object" };
713
- const properties = {};
714
- const required = [];
715
- for (const [key, value] of Object.entries(schema_.shape)) {
716
- const { schema: schema2, matches } = extractJSONSchema(
717
- zodToJsonSchema(value, childOptions),
718
- (schema3) => schema3 === UNDEFINED_JSON_SCHEMA
719
- );
720
- if (schema2) {
721
- properties[key] = schema2;
722
- }
723
- if (matches.length === 0) {
724
- required.push(key);
210
+ const schema_ = schema;
211
+ if (isObject(value)) {
212
+ const newObj = {};
213
+ const keys = /* @__PURE__ */ new Set([
214
+ ...Object.keys(value),
215
+ ...Object.keys(schema_.shape)
216
+ ]);
217
+ for (const k of keys) {
218
+ newObj[k] = zodCoerceInternal(
219
+ schema_.shape[k] ?? schema_._def.catchall,
220
+ value[k]
221
+ );
725
222
  }
223
+ return newObj;
726
224
  }
727
- if (Object.keys(properties).length) {
728
- json.properties = properties;
729
- }
730
- if (required.length) {
731
- json.required = required;
732
- }
733
- const additionalProperties = zodToJsonSchema(
734
- schema_._def.catchall,
735
- childOptions
736
- );
737
- if (schema_._def.unknownKeys === "strict") {
738
- json.additionalProperties = additionalProperties === UNSUPPORTED_JSON_SCHEMA ? false : additionalProperties;
739
- } else {
740
- if (additionalProperties && additionalProperties !== UNSUPPORTED_JSON_SCHEMA) {
741
- json.additionalProperties = additionalProperties;
225
+ return value;
226
+ }
227
+ case ZodFirstPartyTypeKind.ZodRecord: {
228
+ const schema_ = schema;
229
+ if (isObject(value)) {
230
+ const newObj = {};
231
+ for (const [k, v] of Object.entries(value)) {
232
+ const key = zodCoerceInternal(schema_._def.keyType, k);
233
+ const val = zodCoerceInternal(schema_._def.valueType, v);
234
+ newObj[key] = val;
742
235
  }
236
+ return newObj;
743
237
  }
744
- return json;
238
+ return value;
745
239
  }
746
- case ZodFirstPartyTypeKind.ZodRecord: {
747
- const schema_ = schema__;
748
- const json = { type: "object" };
749
- json.additionalProperties = zodToJsonSchema(
750
- schema_._def.valueType,
751
- childOptions
752
- );
753
- return json;
240
+ case ZodFirstPartyTypeKind.ZodArray: {
241
+ const schema_ = schema;
242
+ if (Array.isArray(value)) {
243
+ return value.map((v) => zodCoerceInternal(schema_._def.type, v));
244
+ }
245
+ return value;
246
+ }
247
+ case ZodFirstPartyTypeKind.ZodTuple: {
248
+ const schema_ = schema;
249
+ if (Array.isArray(value)) {
250
+ return value.map((v, i) => {
251
+ const s = schema_._def.items[i] ?? schema_._def.rest;
252
+ return s ? zodCoerceInternal(s, v) : v;
253
+ });
254
+ }
255
+ return value;
754
256
  }
755
257
  case ZodFirstPartyTypeKind.ZodSet: {
756
- const schema_ = schema__;
757
- return {
758
- type: "array",
759
- items: zodToJsonSchema(schema_._def.valueType, childOptions)
760
- };
258
+ const schema_ = schema;
259
+ if (Array.isArray(value)) {
260
+ return new Set(
261
+ value.map((v) => zodCoerceInternal(schema_._def.valueType, v))
262
+ );
263
+ }
264
+ return value;
761
265
  }
762
266
  case ZodFirstPartyTypeKind.ZodMap: {
763
- const schema_ = schema__;
764
- return {
765
- type: "array",
766
- items: {
767
- type: "array",
768
- prefixItems: [
769
- zodToJsonSchema(schema_._def.keyType, childOptions),
770
- zodToJsonSchema(schema_._def.valueType, childOptions)
771
- ],
772
- maxItems: 2,
773
- minItems: 2
774
- }
775
- };
267
+ const schema_ = schema;
268
+ if (Array.isArray(value) && value.every((i) => Array.isArray(i) && i.length === 2)) {
269
+ return new Map(
270
+ value.map(([k, v]) => [
271
+ zodCoerceInternal(schema_._def.keyType, k),
272
+ zodCoerceInternal(schema_._def.valueType, v)
273
+ ])
274
+ );
275
+ }
276
+ return value;
776
277
  }
777
278
  case ZodFirstPartyTypeKind.ZodUnion:
778
279
  case ZodFirstPartyTypeKind.ZodDiscriminatedUnion: {
779
- const schema_ = schema__;
780
- const anyOf = [];
280
+ const schema_ = schema;
281
+ if (schema_.safeParse(value).success) {
282
+ return value;
283
+ }
284
+ const results = [];
781
285
  for (const s of schema_._def.options) {
782
- anyOf.push(zodToJsonSchema(s, childOptions));
286
+ const newValue = zodCoerceInternal(s, value);
287
+ const result = schema_.safeParse(newValue);
288
+ if (result.success) {
289
+ return newValue;
290
+ }
291
+ results.push([newValue, result.error.issues.length]);
783
292
  }
784
- return { anyOf };
785
- }
786
- case ZodFirstPartyTypeKind.ZodIntersection: {
787
- const schema_ = schema__;
788
- const allOf = [];
789
- for (const s of [schema_._def.left, schema_._def.right]) {
790
- allOf.push(zodToJsonSchema(s, childOptions));
293
+ if (results.length === 0) {
294
+ return value;
791
295
  }
792
- return { allOf };
296
+ return results.sort((a, b) => a[1] - b[1])[0][0];
793
297
  }
794
- case ZodFirstPartyTypeKind.ZodLazy: {
795
- const schema_ = schema__;
796
- const maxLazyDepth = childOptions?.maxLazyDepth ?? 5;
797
- const lazyDepth = childOptions?.lazyDepth ?? 0;
798
- if (lazyDepth > maxLazyDepth) {
799
- return {};
800
- }
801
- return zodToJsonSchema(schema_._def.getter(), {
802
- ...childOptions,
803
- lazyDepth: lazyDepth + 1
804
- });
805
- }
806
- case ZodFirstPartyTypeKind.ZodUnknown:
807
- case ZodFirstPartyTypeKind.ZodAny:
808
- case void 0: {
809
- return {};
810
- }
811
- case ZodFirstPartyTypeKind.ZodOptional: {
812
- const schema_ = schema__;
813
- const inner = zodToJsonSchema(schema_._def.innerType, childOptions);
814
- return {
815
- anyOf: [UNDEFINED_JSON_SCHEMA, inner]
816
- };
298
+ case ZodFirstPartyTypeKind.ZodIntersection: {
299
+ const schema_ = schema;
300
+ return zodCoerceInternal(
301
+ schema_._def.right,
302
+ zodCoerceInternal(schema_._def.left, value)
303
+ );
817
304
  }
818
305
  case ZodFirstPartyTypeKind.ZodReadonly: {
819
- const schema_ = schema__;
820
- return zodToJsonSchema(schema_._def.innerType, childOptions);
306
+ const schema_ = schema;
307
+ return zodCoerceInternal(schema_._def.innerType, value);
821
308
  }
822
- case ZodFirstPartyTypeKind.ZodDefault: {
823
- const schema_ = schema__;
824
- return zodToJsonSchema(schema_._def.innerType, childOptions);
309
+ case ZodFirstPartyTypeKind.ZodPipeline: {
310
+ const schema_ = schema;
311
+ return zodCoerceInternal(schema_._def.in, value);
825
312
  }
826
313
  case ZodFirstPartyTypeKind.ZodEffects: {
827
- const schema_ = schema__;
828
- if (schema_._def.effect.type === "transform" && childOptions?.mode === "output") {
829
- return {};
830
- }
831
- return zodToJsonSchema(schema_._def.schema, childOptions);
832
- }
833
- case ZodFirstPartyTypeKind.ZodCatch: {
834
- const schema_ = schema__;
835
- return zodToJsonSchema(schema_._def.innerType, childOptions);
314
+ const schema_ = schema;
315
+ return zodCoerceInternal(schema_._def.schema, value);
836
316
  }
837
317
  case ZodFirstPartyTypeKind.ZodBranded: {
838
- const schema_ = schema__;
839
- return zodToJsonSchema(schema_._def.type, childOptions);
318
+ const schema_ = schema;
319
+ return zodCoerceInternal(schema_._def.type, value);
840
320
  }
841
- case ZodFirstPartyTypeKind.ZodPipeline: {
842
- const schema_ = schema__;
843
- return zodToJsonSchema(
844
- childOptions?.mode === "output" ? schema_._def.out : schema_._def.in,
845
- childOptions
846
- );
321
+ case ZodFirstPartyTypeKind.ZodCatch: {
322
+ const schema_ = schema;
323
+ return zodCoerceInternal(schema_._def.innerType, value);
324
+ }
325
+ case ZodFirstPartyTypeKind.ZodDefault: {
326
+ const schema_ = schema;
327
+ return zodCoerceInternal(schema_._def.innerType, value);
847
328
  }
848
329
  case ZodFirstPartyTypeKind.ZodNullable: {
849
- const schema_ = schema__;
850
- const inner = zodToJsonSchema(schema_._def.innerType, childOptions);
851
- return {
852
- anyOf: [{ type: "null" }, inner]
853
- };
330
+ if (value === null) {
331
+ return null;
332
+ }
333
+ const schema_ = schema;
334
+ return zodCoerceInternal(schema_._def.innerType, value);
335
+ }
336
+ case ZodFirstPartyTypeKind.ZodOptional: {
337
+ if (value === void 0) {
338
+ return void 0;
339
+ }
340
+ const schema_ = schema;
341
+ return zodCoerceInternal(schema_._def.innerType, value);
342
+ }
343
+ case ZodFirstPartyTypeKind.ZodLazy: {
344
+ const schema_ = schema;
345
+ if (value !== void 0) {
346
+ return zodCoerceInternal(schema_._def.getter(), value);
347
+ }
348
+ return value;
854
349
  }
855
350
  }
856
- return UNSUPPORTED_JSON_SCHEMA;
351
+ return value;
857
352
  }
858
- function extractJSONSchema(schema, check, matches = []) {
859
- if (check(schema)) {
860
- matches.push(schema);
861
- return { schema: void 0, matches };
353
+ function safeToBigInt(value) {
354
+ return guard(() => BigInt(value)) ?? value;
355
+ }
356
+ function safeToNumber(value) {
357
+ const num = Number(value);
358
+ return Number.isNaN(num) || num.toString() !== value ? value : num;
359
+ }
360
+ function safeToBoolean(value) {
361
+ const lower = value.toLowerCase();
362
+ if (lower === "false" || lower === "off" || lower === "f") {
363
+ return false;
862
364
  }
863
- if (typeof schema === "boolean") {
864
- return { schema, matches };
365
+ if (lower === "true" || lower === "on" || lower === "t") {
366
+ return true;
865
367
  }
866
- if (schema.anyOf && Object.keys(schema).every(
867
- (k) => k === "anyOf" || NON_LOGIC_KEYWORDS.includes(k)
868
- )) {
869
- const anyOf = schema.anyOf.map((s) => extractJSONSchema(s, check, matches).schema).filter((v) => !!v);
870
- if (anyOf.length === 1 && typeof anyOf[0] === "object") {
871
- return { schema: { ...schema, anyOf: void 0, ...anyOf[0] }, matches };
368
+ return value;
369
+ }
370
+ function safeToRegExp(value) {
371
+ if (value.startsWith("/")) {
372
+ const match = value.match(/^\/(.*)\/([a-z]*)$/);
373
+ if (match) {
374
+ const [, pattern, flags] = match;
375
+ return new RegExp(pattern, flags);
872
376
  }
873
- return {
874
- schema: {
875
- ...schema,
876
- anyOf
877
- },
878
- matches
879
- };
880
377
  }
881
- if (schema.oneOf && Object.keys(schema).every(
882
- (k) => k === "oneOf" || NON_LOGIC_KEYWORDS.includes(k)
883
- )) {
884
- const oneOf = schema.oneOf.map((s) => extractJSONSchema(s, check, matches).schema).filter((v) => !!v);
885
- if (oneOf.length === 1 && typeof oneOf[0] === "object") {
886
- return { schema: { ...schema, oneOf: void 0, ...oneOf[0] }, matches };
887
- }
888
- return {
889
- schema: {
890
- ...schema,
891
- oneOf
892
- },
893
- matches
894
- };
378
+ return value;
379
+ }
380
+ function safeToURL(value) {
381
+ return guard(() => new URL(value)) ?? value;
382
+ }
383
+ function safeToDate(value) {
384
+ const date = new Date(value);
385
+ if (!Number.isNaN(date.getTime()) && date.toISOString().startsWith(value)) {
386
+ return date;
895
387
  }
896
- return { schema, matches };
388
+ return value;
897
389
  }
390
+
898
391
  class ZodToJsonSchemaConverter {
392
+ maxLazyDepth;
393
+ unsupportedJsonSchema;
394
+ anyJsonSchema;
395
+ constructor(options = {}) {
396
+ this.maxLazyDepth = options.maxLazyDepth ?? 3;
397
+ this.unsupportedJsonSchema = options.unsupportedJsonSchema ?? { not: {} };
398
+ this.anyJsonSchema = options.anyJsonSchema ?? {};
399
+ }
899
400
  condition(schema) {
900
401
  return Boolean(schema && schema["~standard"].vendor === "zod");
901
402
  }
902
- convert(schema, options) {
903
- const jsonSchema = schema;
904
- return zodToJsonSchema(jsonSchema, { mode: options.strategy });
403
+ convert(schema, options, lazyDepth = 0, isHandledCustomJSONSchema = false, isHandledZodDescription = false) {
404
+ const def = schema._def;
405
+ if (!isHandledZodDescription && "description" in def && typeof def.description === "string") {
406
+ const [required, json] = this.convert(
407
+ schema,
408
+ options,
409
+ lazyDepth,
410
+ isHandledCustomJSONSchema,
411
+ true
412
+ );
413
+ return [required, { ...json, description: def.description }];
414
+ }
415
+ if (!isHandledCustomJSONSchema) {
416
+ const customJSONSchema = getCustomJsonSchema(def, options);
417
+ if (customJSONSchema) {
418
+ const [required, json] = this.convert(
419
+ schema,
420
+ options,
421
+ lazyDepth,
422
+ true,
423
+ isHandledZodDescription
424
+ );
425
+ return [required, { ...json, ...customJSONSchema }];
426
+ }
427
+ }
428
+ const customSchema = this.#handleCustomZodDef(def);
429
+ if (customSchema) {
430
+ return [true, customSchema];
431
+ }
432
+ const typeName = this.#getZodTypeName(def);
433
+ switch (typeName) {
434
+ case ZodFirstPartyTypeKind.ZodString: {
435
+ const schema_ = schema;
436
+ const json = { type: "string" };
437
+ for (const check of schema_._def.checks) {
438
+ switch (check.kind) {
439
+ case "base64":
440
+ json.contentEncoding = "base64";
441
+ break;
442
+ case "cuid":
443
+ json.pattern = "^[0-9A-HJKMNP-TV-Z]{26}$";
444
+ break;
445
+ case "email":
446
+ json.format = JSONSchemaFormat.Email;
447
+ break;
448
+ case "url":
449
+ json.format = JSONSchemaFormat.URI;
450
+ break;
451
+ case "uuid":
452
+ json.format = JSONSchemaFormat.UUID;
453
+ break;
454
+ case "regex":
455
+ json.pattern = check.regex.source;
456
+ break;
457
+ case "min":
458
+ json.minLength = check.value;
459
+ break;
460
+ case "max":
461
+ json.maxLength = check.value;
462
+ break;
463
+ case "length":
464
+ json.minLength = check.value;
465
+ json.maxLength = check.value;
466
+ break;
467
+ case "includes":
468
+ json.pattern = escapeStringRegexp(check.value);
469
+ break;
470
+ case "startsWith":
471
+ json.pattern = `^${escapeStringRegexp(check.value)}`;
472
+ break;
473
+ case "endsWith":
474
+ json.pattern = `${escapeStringRegexp(check.value)}$`;
475
+ break;
476
+ case "emoji":
477
+ json.pattern = "^(\\p{Extended_Pictographic}|\\p{Emoji_Component})+$";
478
+ break;
479
+ case "nanoid":
480
+ json.pattern = "^[a-zA-Z0-9_-]{21}$";
481
+ break;
482
+ case "cuid2":
483
+ json.pattern = "^[0-9a-z]+$";
484
+ break;
485
+ case "ulid":
486
+ json.pattern = "^[0-9A-HJKMNP-TV-Z]{26}$";
487
+ break;
488
+ case "datetime":
489
+ json.format = JSONSchemaFormat.DateTime;
490
+ break;
491
+ case "date":
492
+ json.format = JSONSchemaFormat.Date;
493
+ break;
494
+ case "time":
495
+ json.format = JSONSchemaFormat.Time;
496
+ break;
497
+ case "duration":
498
+ json.format = JSONSchemaFormat.Duration;
499
+ break;
500
+ case "ip": {
501
+ if (check.version === "v4") {
502
+ json.format = JSONSchemaFormat.IPv4;
503
+ } else if (check.version === "v6") {
504
+ json.format = JSONSchemaFormat.IPv6;
505
+ } else {
506
+ json.anyOf = [
507
+ { format: JSONSchemaFormat.IPv4 },
508
+ { format: JSONSchemaFormat.IPv6 }
509
+ ];
510
+ }
511
+ break;
512
+ }
513
+ case "jwt":
514
+ json.pattern = "^[A-Za-z0-9-_]+\\.[A-Za-z0-9-_]+\\.[A-Za-z0-9-_]*$";
515
+ break;
516
+ case "base64url":
517
+ json.pattern = "^([0-9a-zA-Z-_]{4})*(([0-9a-zA-Z-_]{2}(==)?)|([0-9a-zA-Z-_]{3}(=)?))?$";
518
+ break;
519
+ default: {
520
+ check.kind;
521
+ }
522
+ }
523
+ }
524
+ return [true, json];
525
+ }
526
+ case ZodFirstPartyTypeKind.ZodNumber: {
527
+ const schema_ = schema;
528
+ const json = { type: "number" };
529
+ for (const check of schema_._def.checks) {
530
+ switch (check.kind) {
531
+ case "int":
532
+ json.type = "integer";
533
+ break;
534
+ case "min":
535
+ json.minimum = check.value;
536
+ break;
537
+ case "max":
538
+ json.maximum = check.value;
539
+ break;
540
+ case "multipleOf":
541
+ json.multipleOf = check.value;
542
+ break;
543
+ default: {
544
+ check.kind;
545
+ }
546
+ }
547
+ }
548
+ return [true, json];
549
+ }
550
+ case ZodFirstPartyTypeKind.ZodBigInt: {
551
+ const json = { type: "string", pattern: "^-?[0-9]+$" };
552
+ return [true, json];
553
+ }
554
+ case ZodFirstPartyTypeKind.ZodNaN: {
555
+ return options.strategy === "input" ? [true, this.unsupportedJsonSchema] : [true, { type: "null" }];
556
+ }
557
+ case ZodFirstPartyTypeKind.ZodBoolean: {
558
+ return [true, { type: "boolean" }];
559
+ }
560
+ case ZodFirstPartyTypeKind.ZodDate: {
561
+ const schema2 = { type: "string", format: JSONSchemaFormat.DateTime };
562
+ return [true, schema2];
563
+ }
564
+ case ZodFirstPartyTypeKind.ZodNull: {
565
+ return [true, { type: "null" }];
566
+ }
567
+ case ZodFirstPartyTypeKind.ZodLiteral: {
568
+ const schema_ = schema;
569
+ if (schema_._def.value === void 0) {
570
+ return [false, this.unsupportedJsonSchema];
571
+ }
572
+ return [true, { const: schema_._def.value }];
573
+ }
574
+ case ZodFirstPartyTypeKind.ZodVoid:
575
+ case ZodFirstPartyTypeKind.ZodUndefined: {
576
+ return [false, this.unsupportedJsonSchema];
577
+ }
578
+ case ZodFirstPartyTypeKind.ZodUnknown:
579
+ case ZodFirstPartyTypeKind.ZodAny: {
580
+ return [false, this.anyJsonSchema];
581
+ }
582
+ case ZodFirstPartyTypeKind.ZodEnum: {
583
+ const schema_ = schema;
584
+ return [true, { enum: schema_._def.values }];
585
+ }
586
+ case ZodFirstPartyTypeKind.ZodNativeEnum: {
587
+ const schema_ = schema;
588
+ return [true, { enum: Object.values(schema_._def.values) }];
589
+ }
590
+ case ZodFirstPartyTypeKind.ZodArray: {
591
+ const schema_ = schema;
592
+ const def2 = schema_._def;
593
+ const json = { type: "array" };
594
+ const [itemRequired, itemJson] = this.convert(def2.type, options, lazyDepth, false, false);
595
+ json.items = this.#toArrayItemJsonSchema(itemRequired, itemJson, options.strategy);
596
+ if (def2.exactLength) {
597
+ json.maxItems = def2.exactLength.value;
598
+ json.minItems = def2.exactLength.value;
599
+ }
600
+ if (def2.minLength) {
601
+ json.minItems = def2.minLength.value;
602
+ }
603
+ if (def2.maxLength) {
604
+ json.maxItems = def2.maxLength.value;
605
+ }
606
+ return [true, json];
607
+ }
608
+ case ZodFirstPartyTypeKind.ZodTuple: {
609
+ const schema_ = schema;
610
+ const prefixItems = [];
611
+ const json = { type: "array" };
612
+ for (const item of schema_._def.items) {
613
+ const [itemRequired, itemJson] = this.convert(item, options, lazyDepth, false, false);
614
+ prefixItems.push(
615
+ this.#toArrayItemJsonSchema(itemRequired, itemJson, options.strategy)
616
+ );
617
+ }
618
+ if (prefixItems?.length) {
619
+ json.prefixItems = prefixItems;
620
+ }
621
+ if (schema_._def.rest) {
622
+ const [itemRequired, itemJson] = this.convert(schema_._def.rest, options, lazyDepth, false, false);
623
+ json.items = this.#toArrayItemJsonSchema(itemRequired, itemJson, options.strategy);
624
+ }
625
+ return [true, json];
626
+ }
627
+ case ZodFirstPartyTypeKind.ZodObject: {
628
+ const schema_ = schema;
629
+ const json = { type: "object" };
630
+ const properties = {};
631
+ const required = [];
632
+ for (const [key, value] of Object.entries(schema_.shape)) {
633
+ const [itemRequired, itemJson] = this.convert(value, options, lazyDepth, false, false);
634
+ properties[key] = itemJson;
635
+ if (itemRequired) {
636
+ required.push(key);
637
+ }
638
+ }
639
+ if (Object.keys(properties).length) {
640
+ json.properties = properties;
641
+ }
642
+ if (required.length) {
643
+ json.required = required;
644
+ }
645
+ const catchAllTypeName = this.#getZodTypeName(schema_._def.catchall._def);
646
+ if (catchAllTypeName === ZodFirstPartyTypeKind.ZodNever) {
647
+ if (schema_._def.unknownKeys === "strict") {
648
+ json.additionalProperties = false;
649
+ }
650
+ } else {
651
+ const [_, addJson] = this.convert(schema_._def.catchall, options, lazyDepth, false, false);
652
+ json.additionalProperties = addJson;
653
+ }
654
+ return [true, json];
655
+ }
656
+ case ZodFirstPartyTypeKind.ZodRecord: {
657
+ const schema_ = schema;
658
+ const json = { type: "object" };
659
+ const [_, itemJson] = this.convert(schema_._def.valueType, options, lazyDepth, false, false);
660
+ json.additionalProperties = itemJson;
661
+ return [true, json];
662
+ }
663
+ case ZodFirstPartyTypeKind.ZodSet: {
664
+ const schema_ = schema;
665
+ const json = { type: "array", uniqueItems: true };
666
+ const [itemRequired, itemJson] = this.convert(schema_._def.valueType, options, lazyDepth, false, false);
667
+ json.items = this.#toArrayItemJsonSchema(itemRequired, itemJson, options.strategy);
668
+ return [true, json];
669
+ }
670
+ case ZodFirstPartyTypeKind.ZodMap: {
671
+ const schema_ = schema;
672
+ const [keyRequired, keyJson] = this.convert(schema_._def.keyType, options, lazyDepth, false, false);
673
+ const [valueRequired, valueJson] = this.convert(schema_._def.valueType, options, lazyDepth, false, false);
674
+ return [true, {
675
+ type: "array",
676
+ items: {
677
+ type: "array",
678
+ prefixItems: [
679
+ this.#toArrayItemJsonSchema(keyRequired, keyJson, options.strategy),
680
+ this.#toArrayItemJsonSchema(valueRequired, valueJson, options.strategy)
681
+ ],
682
+ maxItems: 2,
683
+ minItems: 2
684
+ }
685
+ }];
686
+ }
687
+ case ZodFirstPartyTypeKind.ZodUnion:
688
+ case ZodFirstPartyTypeKind.ZodDiscriminatedUnion: {
689
+ const schema_ = schema;
690
+ const anyOf = [];
691
+ let required = true;
692
+ for (const item of schema_._def.options) {
693
+ const [itemRequired, itemJson] = this.convert(item, options, lazyDepth, false, false);
694
+ if (!itemRequired) {
695
+ required = false;
696
+ if (itemJson !== this.unsupportedJsonSchema) {
697
+ anyOf.push(itemJson);
698
+ }
699
+ } else {
700
+ anyOf.push(itemJson);
701
+ }
702
+ }
703
+ if (anyOf.length === 1) {
704
+ return [required, anyOf[0]];
705
+ }
706
+ return [required, { anyOf }];
707
+ }
708
+ case ZodFirstPartyTypeKind.ZodIntersection: {
709
+ const schema_ = schema;
710
+ const allOf = [];
711
+ let required = false;
712
+ for (const item of [schema_._def.left, schema_._def.right]) {
713
+ const [itemRequired, itemJson] = this.convert(item, options, lazyDepth, false, false);
714
+ allOf.push(itemJson);
715
+ if (itemRequired) {
716
+ required = true;
717
+ }
718
+ }
719
+ return [required, { allOf }];
720
+ }
721
+ case ZodFirstPartyTypeKind.ZodLazy: {
722
+ if (lazyDepth >= this.maxLazyDepth) {
723
+ return [false, this.anyJsonSchema];
724
+ }
725
+ const schema_ = schema;
726
+ return this.convert(schema_._def.getter(), options, lazyDepth + 1, false, false);
727
+ }
728
+ case ZodFirstPartyTypeKind.ZodOptional: {
729
+ const schema_ = schema;
730
+ const [_, inner] = this.convert(schema_._def.innerType, options, lazyDepth, false, false);
731
+ return [false, inner];
732
+ }
733
+ case ZodFirstPartyTypeKind.ZodReadonly: {
734
+ const schema_ = schema;
735
+ return this.convert(schema_._def.innerType, options, lazyDepth, false, false);
736
+ }
737
+ case ZodFirstPartyTypeKind.ZodDefault: {
738
+ const schema_ = schema;
739
+ const [_, json] = this.convert(schema_._def.innerType, options, lazyDepth, false, false);
740
+ return [false, { default: schema_._def.defaultValue(), ...json }];
741
+ }
742
+ case ZodFirstPartyTypeKind.ZodEffects: {
743
+ const schema_ = schema;
744
+ if (schema_._def.effect.type === "transform" && options.strategy === "output") {
745
+ return [false, this.anyJsonSchema];
746
+ }
747
+ return this.convert(schema_._def.schema, options, lazyDepth, false, false);
748
+ }
749
+ case ZodFirstPartyTypeKind.ZodCatch: {
750
+ const schema_ = schema;
751
+ return this.convert(schema_._def.innerType, options, lazyDepth, false, false);
752
+ }
753
+ case ZodFirstPartyTypeKind.ZodBranded: {
754
+ const schema_ = schema;
755
+ return this.convert(schema_._def.type, options, lazyDepth, false, false);
756
+ }
757
+ case ZodFirstPartyTypeKind.ZodPipeline: {
758
+ const schema_ = schema;
759
+ return this.convert(
760
+ options.strategy === "input" ? schema_._def.in : schema_._def.out,
761
+ options,
762
+ lazyDepth,
763
+ false,
764
+ false
765
+ );
766
+ }
767
+ case ZodFirstPartyTypeKind.ZodNullable: {
768
+ const schema_ = schema;
769
+ const [required, json] = this.convert(schema_._def.innerType, options, lazyDepth, false, false);
770
+ return [required, { anyOf: [{ type: "null" }, json] }];
771
+ }
772
+ }
773
+ return [true, this.unsupportedJsonSchema];
774
+ }
775
+ #handleCustomZodDef(def) {
776
+ const customZodDef = getCustomZodDef(def);
777
+ if (!customZodDef) {
778
+ return void 0;
779
+ }
780
+ switch (customZodDef.type) {
781
+ case "blob": {
782
+ return { type: "string", contentMediaType: "*/*" };
783
+ }
784
+ case "file": {
785
+ return { type: "string", contentMediaType: customZodDef.mimeType ?? "*/*" };
786
+ }
787
+ case "regexp": {
788
+ return {
789
+ type: "string",
790
+ pattern: "^\\/(.*)\\/([a-z]*)$"
791
+ };
792
+ }
793
+ case "url": {
794
+ return { type: "string", format: JSONSchemaFormat.URI };
795
+ }
796
+ }
797
+ }
798
+ #getZodTypeName(def) {
799
+ return def.typeName;
800
+ }
801
+ #toArrayItemJsonSchema(required, schema, strategy) {
802
+ if (required) {
803
+ return schema;
804
+ }
805
+ return strategy === "input" ? { anyOf: [schema, this.unsupportedJsonSchema] } : { anyOf: [schema, { type: "null" }] };
905
806
  }
906
807
  }
907
808
 
908
- export { NON_LOGIC_KEYWORDS, UNDEFINED_JSON_SCHEMA, UNSUPPORTED_JSON_SCHEMA, ZodSmartCoercionPlugin as ZodAutoCoercePlugin, ZodSmartCoercionPlugin, ZodToJsonSchemaConverter, blob, file, getCustomJSONSchema, getCustomZodFileMimeType, getCustomZodType, invalidDate, openapi, oz, regexp, url, zodToJsonSchema };
809
+ const oz = {
810
+ file,
811
+ blob,
812
+ url,
813
+ regexp,
814
+ openapi: customJsonSchema
815
+ };
816
+
817
+ export { ZodSmartCoercionPlugin, ZodToJsonSchemaConverter, blob, composeParams, customJsonSchema, file, getCustomJsonSchema, getCustomZodDef, oz, regexp, setCustomZodDef, url };