@orpc/zod 0.0.0-next.df024bb → 0.0.0-next.df717fa

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