@orpc/zod 0.0.0-next.ae2f20c → 0.0.0-next.ae4860c
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/README.md +21 -17
- package/dist/index.d.mts +16 -7
- package/dist/index.d.ts +16 -7
- package/dist/index.mjs +78 -44
- package/dist/zod4/index.d.mts +30 -18
- package/dist/zod4/index.d.ts +30 -18
- package/dist/zod4/index.mjs +149 -116
- package/package.json +11 -24
package/dist/zod4/index.d.ts
CHANGED
|
@@ -2,24 +2,35 @@ import { Context } from '@orpc/server';
|
|
|
2
2
|
import { StandardHandlerPlugin, StandardHandlerOptions } from '@orpc/server/standard';
|
|
3
3
|
import { AnySchema } from '@orpc/contract';
|
|
4
4
|
import { JSONSchema, SchemaConvertOptions, ConditionalSchemaConverter } from '@orpc/openapi';
|
|
5
|
-
import { Interceptor
|
|
6
|
-
import * as
|
|
7
|
-
import { $ZodType, $input, $output } from '
|
|
5
|
+
import { Interceptor } from '@orpc/shared';
|
|
6
|
+
import * as zod_v4_core from 'zod/v4/core';
|
|
7
|
+
import { $ZodType, $input, $output } from 'zod/v4/core';
|
|
8
8
|
|
|
9
|
+
/**
|
|
10
|
+
* @deprecated Use [Smart Coercion Plugin](https://orpc.dev/docs/openapi/plugins/smart-coercion) instead.
|
|
11
|
+
*/
|
|
9
12
|
declare class experimental_ZodSmartCoercionPlugin<TContext extends Context> implements StandardHandlerPlugin<TContext> {
|
|
10
13
|
#private;
|
|
11
14
|
init(options: StandardHandlerOptions<TContext>): void;
|
|
12
15
|
}
|
|
13
16
|
|
|
14
|
-
interface
|
|
17
|
+
interface ZodToJsonSchemaConverterOptions {
|
|
15
18
|
/**
|
|
16
|
-
* Max depth of lazy type
|
|
19
|
+
* Max depth of lazy type.
|
|
17
20
|
*
|
|
18
|
-
* Used anyJsonSchema (`{}`) when
|
|
21
|
+
* Used anyJsonSchema (`{}`) when exceed max depth
|
|
19
22
|
*
|
|
20
23
|
* @default 2
|
|
21
24
|
*/
|
|
22
25
|
maxLazyDepth?: number;
|
|
26
|
+
/**
|
|
27
|
+
* Max depth of nested types.
|
|
28
|
+
*
|
|
29
|
+
* Used anyJsonSchema (`{}`) when exceed max depth
|
|
30
|
+
*
|
|
31
|
+
* @default 10
|
|
32
|
+
*/
|
|
33
|
+
maxStructureDepth?: number;
|
|
23
34
|
/**
|
|
24
35
|
* The schema to be used to represent the any | unknown type.
|
|
25
36
|
*
|
|
@@ -46,18 +57,19 @@ interface experimental_ZodToJsonSchemaOptions {
|
|
|
46
57
|
}, [
|
|
47
58
|
required: boolean,
|
|
48
59
|
jsonSchema: Exclude<JSONSchema, boolean>
|
|
49
|
-
]
|
|
60
|
+
]>[];
|
|
50
61
|
}
|
|
51
|
-
declare class
|
|
62
|
+
declare class ZodToJsonSchemaConverter implements ConditionalSchemaConverter {
|
|
52
63
|
#private;
|
|
53
64
|
private readonly maxLazyDepth;
|
|
65
|
+
private readonly maxStructureDepth;
|
|
54
66
|
private readonly anyJsonSchema;
|
|
55
67
|
private readonly unsupportedJsonSchema;
|
|
56
68
|
private readonly undefinedJsonSchema;
|
|
57
69
|
private readonly interceptors;
|
|
58
|
-
constructor(options?:
|
|
70
|
+
constructor(options?: ZodToJsonSchemaConverterOptions);
|
|
59
71
|
condition(schema: AnySchema | undefined): boolean;
|
|
60
|
-
convert(schema: AnySchema | undefined, options: SchemaConvertOptions):
|
|
72
|
+
convert(schema: AnySchema | undefined, options: SchemaConvertOptions): [required: boolean, jsonSchema: Exclude<JSONSchema, boolean>];
|
|
61
73
|
}
|
|
62
74
|
|
|
63
75
|
/**
|
|
@@ -77,7 +89,7 @@ declare class experimental_ZodToJsonSchemaConverter implements ConditionalSchema
|
|
|
77
89
|
* })
|
|
78
90
|
* ```
|
|
79
91
|
*/
|
|
80
|
-
declare const
|
|
92
|
+
declare const JSON_SCHEMA_REGISTRY: zod_v4_core.$ZodRegistry<{
|
|
81
93
|
$anchor?: string;
|
|
82
94
|
$comment?: string;
|
|
83
95
|
$defs?: Record<string, JSONSchema>;
|
|
@@ -138,7 +150,7 @@ declare const experimental_JSON_SCHEMA_REGISTRY: _zod_core.$ZodRegistry<{
|
|
|
138
150
|
unevaluatedProperties?: JSONSchema;
|
|
139
151
|
uniqueItems?: boolean;
|
|
140
152
|
writeOnly?: boolean;
|
|
141
|
-
},
|
|
153
|
+
}, zod_v4_core.$ZodType<unknown, unknown, zod_v4_core.$ZodTypeInternals<unknown, unknown>>>;
|
|
142
154
|
/**
|
|
143
155
|
* Zod registry for customizing generated JSON schema, only useful for .input
|
|
144
156
|
*
|
|
@@ -156,7 +168,7 @@ declare const experimental_JSON_SCHEMA_REGISTRY: _zod_core.$ZodRegistry<{
|
|
|
156
168
|
* })
|
|
157
169
|
* ```
|
|
158
170
|
*/
|
|
159
|
-
declare const
|
|
171
|
+
declare const JSON_SCHEMA_INPUT_REGISTRY: zod_v4_core.$ZodRegistry<{
|
|
160
172
|
$anchor?: string;
|
|
161
173
|
$comment?: string;
|
|
162
174
|
$defs?: Record<string, JSONSchema>;
|
|
@@ -217,7 +229,7 @@ declare const experimental_JSON_SCHEMA_INPUT_REGISTRY: _zod_core.$ZodRegistry<{
|
|
|
217
229
|
unevaluatedProperties?: JSONSchema;
|
|
218
230
|
uniqueItems?: boolean;
|
|
219
231
|
writeOnly?: boolean;
|
|
220
|
-
},
|
|
232
|
+
}, zod_v4_core.$ZodType<unknown, unknown, zod_v4_core.$ZodTypeInternals<unknown, unknown>>>;
|
|
221
233
|
/**
|
|
222
234
|
* Zod registry for customizing generated JSON schema, only useful for .input
|
|
223
235
|
*
|
|
@@ -235,7 +247,7 @@ declare const experimental_JSON_SCHEMA_INPUT_REGISTRY: _zod_core.$ZodRegistry<{
|
|
|
235
247
|
* })
|
|
236
248
|
* ```
|
|
237
249
|
*/
|
|
238
|
-
declare const
|
|
250
|
+
declare const JSON_SCHEMA_OUTPUT_REGISTRY: zod_v4_core.$ZodRegistry<{
|
|
239
251
|
$anchor?: string;
|
|
240
252
|
$comment?: string;
|
|
241
253
|
$defs?: Record<string, JSONSchema>;
|
|
@@ -296,7 +308,7 @@ declare const experimental_JSON_SCHEMA_OUTPUT_REGISTRY: _zod_core.$ZodRegistry<{
|
|
|
296
308
|
unevaluatedProperties?: JSONSchema;
|
|
297
309
|
uniqueItems?: boolean;
|
|
298
310
|
writeOnly?: boolean;
|
|
299
|
-
},
|
|
311
|
+
}, zod_v4_core.$ZodType<unknown, unknown, zod_v4_core.$ZodTypeInternals<unknown, unknown>>>;
|
|
300
312
|
|
|
301
|
-
export {
|
|
302
|
-
export type {
|
|
313
|
+
export { JSON_SCHEMA_INPUT_REGISTRY, JSON_SCHEMA_OUTPUT_REGISTRY, JSON_SCHEMA_REGISTRY, ZodToJsonSchemaConverter, experimental_ZodSmartCoercionPlugin };
|
|
314
|
+
export type { ZodToJsonSchemaConverterOptions };
|
package/dist/zod4/index.mjs
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
import { isObject, guard, intercept } from '@orpc/shared';
|
|
1
|
+
import { isObject, guard, intercept, toArray } from '@orpc/shared';
|
|
2
|
+
import { JsonSchemaXNativeType } from '@orpc/json-schema';
|
|
2
3
|
import { JSONSchemaFormat, JSONSchemaContentEncoding } from '@orpc/openapi';
|
|
3
|
-
import { registry, globalRegistry } from '
|
|
4
|
+
import { registry, globalRegistry } from 'zod/v4/core';
|
|
4
5
|
|
|
5
6
|
class experimental_ZodSmartCoercionPlugin {
|
|
6
7
|
init(options) {
|
|
7
8
|
options.clientInterceptors ??= [];
|
|
8
9
|
options.clientInterceptors.unshift((options2) => {
|
|
9
10
|
const inputSchema = options2.procedure["~orpc"].inputSchema;
|
|
10
|
-
if (!inputSchema || inputSchema["~standard"].vendor !== "zod") {
|
|
11
|
+
if (!inputSchema || inputSchema["~standard"].vendor !== "zod" || !("_zod" in inputSchema)) {
|
|
11
12
|
return options2.next();
|
|
12
13
|
}
|
|
13
14
|
const coercedInput = this.#coerce(inputSchema, options2.input);
|
|
@@ -100,8 +101,7 @@ class experimental_ZodSmartCoercionPlugin {
|
|
|
100
101
|
}
|
|
101
102
|
return value;
|
|
102
103
|
}
|
|
103
|
-
case "object":
|
|
104
|
-
case "interface": {
|
|
104
|
+
case "object": {
|
|
105
105
|
const object = schema;
|
|
106
106
|
if (value === void 0) {
|
|
107
107
|
return {};
|
|
@@ -165,9 +165,21 @@ class experimental_ZodSmartCoercionPlugin {
|
|
|
165
165
|
return this.#coerce(union._zod.def.options[0], value);
|
|
166
166
|
}
|
|
167
167
|
if (isObject(value)) {
|
|
168
|
+
const discriminator = "discriminator" in union._zod.def && typeof union._zod.def.discriminator === "string" ? union._zod.def.discriminator : void 0;
|
|
168
169
|
for (const option of union._zod.def.options) {
|
|
169
|
-
if (option._zod.
|
|
170
|
-
|
|
170
|
+
if (!option._zod.propValues) {
|
|
171
|
+
continue;
|
|
172
|
+
}
|
|
173
|
+
if (discriminator !== void 0) {
|
|
174
|
+
if (option._zod.propValues[discriminator]?.has(value[discriminator])) {
|
|
175
|
+
return this.#coerce(option, value);
|
|
176
|
+
}
|
|
177
|
+
} else {
|
|
178
|
+
for (const key in option._zod.propValues) {
|
|
179
|
+
if (option._zod.propValues[key]?.has(value[key])) {
|
|
180
|
+
return this.#coerce(option, value);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
171
183
|
}
|
|
172
184
|
}
|
|
173
185
|
}
|
|
@@ -207,10 +219,17 @@ class experimental_ZodSmartCoercionPlugin {
|
|
|
207
219
|
return this.#coerce(pipe._zod.def.in, value);
|
|
208
220
|
}
|
|
209
221
|
case "default":
|
|
210
|
-
case "
|
|
222
|
+
case "prefault": {
|
|
211
223
|
const default_ = schema;
|
|
224
|
+
if (value === void 0) {
|
|
225
|
+
return value;
|
|
226
|
+
}
|
|
212
227
|
return this.#coerce(default_._zod.def.innerType, value);
|
|
213
228
|
}
|
|
229
|
+
case "catch": {
|
|
230
|
+
const catch_ = schema;
|
|
231
|
+
return this.#coerce(catch_._zod.def.innerType, value);
|
|
232
|
+
}
|
|
214
233
|
case "lazy": {
|
|
215
234
|
const lazy = schema;
|
|
216
235
|
if (value !== void 0) {
|
|
@@ -248,64 +267,53 @@ class experimental_ZodSmartCoercionPlugin {
|
|
|
248
267
|
}
|
|
249
268
|
return value;
|
|
250
269
|
}
|
|
251
|
-
/**
|
|
252
|
-
* This function is inspired from Zod, because it's not exported
|
|
253
|
-
* https://github.com/colinhacks/zod/blob/v4/packages/core/src/schemas.ts#L1903C1-L1921C2
|
|
254
|
-
*/
|
|
255
|
-
#matchDiscriminators(input, discs) {
|
|
256
|
-
for (const [key, value] of discs) {
|
|
257
|
-
const data = input[key];
|
|
258
|
-
if (value.values.size && !value.values.has(data)) {
|
|
259
|
-
return false;
|
|
260
|
-
}
|
|
261
|
-
if (value.maps.length === 0) {
|
|
262
|
-
continue;
|
|
263
|
-
}
|
|
264
|
-
if (!isObject(data)) {
|
|
265
|
-
return false;
|
|
266
|
-
}
|
|
267
|
-
for (const m of value.maps) {
|
|
268
|
-
if (!this.#matchDiscriminators(data, m)) {
|
|
269
|
-
return false;
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
return true;
|
|
274
|
-
}
|
|
275
270
|
}
|
|
276
271
|
|
|
277
|
-
const
|
|
278
|
-
const
|
|
279
|
-
const
|
|
272
|
+
const JSON_SCHEMA_REGISTRY = registry();
|
|
273
|
+
const JSON_SCHEMA_INPUT_REGISTRY = registry();
|
|
274
|
+
const JSON_SCHEMA_OUTPUT_REGISTRY = registry();
|
|
280
275
|
|
|
281
|
-
class
|
|
276
|
+
class ZodToJsonSchemaConverter {
|
|
282
277
|
maxLazyDepth;
|
|
278
|
+
maxStructureDepth;
|
|
283
279
|
anyJsonSchema;
|
|
284
280
|
unsupportedJsonSchema;
|
|
285
281
|
undefinedJsonSchema;
|
|
286
282
|
interceptors;
|
|
287
283
|
constructor(options = {}) {
|
|
288
284
|
this.maxLazyDepth = options.maxLazyDepth ?? 2;
|
|
285
|
+
this.maxStructureDepth = options.maxStructureDepth ?? 10;
|
|
289
286
|
this.anyJsonSchema = options.anyJsonSchema ?? {};
|
|
290
287
|
this.unsupportedJsonSchema = options.unsupportedJsonSchema ?? { not: {} };
|
|
291
288
|
this.undefinedJsonSchema = options.undefinedJsonSchema ?? { not: {} };
|
|
292
289
|
this.interceptors = options.interceptors ?? [];
|
|
293
290
|
}
|
|
294
291
|
condition(schema) {
|
|
295
|
-
return schema !== void 0 && schema["~standard"].vendor === "zod";
|
|
292
|
+
return schema !== void 0 && schema["~standard"].vendor === "zod" && "_zod" in schema;
|
|
296
293
|
}
|
|
297
294
|
convert(schema, options) {
|
|
298
|
-
return this.#convert(schema, options, 0);
|
|
295
|
+
return this.#convert(schema, options, 0, 0);
|
|
299
296
|
}
|
|
300
|
-
#convert(schema, options, lazyDepth, isHandledCustomJSONSchema = false) {
|
|
297
|
+
#convert(schema, options, lazyDepth, structureDepth, isHandledCustomJSONSchema = false) {
|
|
301
298
|
return intercept(
|
|
302
299
|
this.interceptors,
|
|
303
300
|
{ schema, options, lazyDepth, isHandledCustomJSONSchema },
|
|
304
|
-
|
|
301
|
+
({ schema: schema2, options: options2, lazyDepth: lazyDepth2, isHandledCustomJSONSchema: isHandledCustomJSONSchema2 }) => {
|
|
302
|
+
if (structureDepth > this.maxStructureDepth) {
|
|
303
|
+
return [false, this.anyJsonSchema];
|
|
304
|
+
}
|
|
305
|
+
if (!options2.minStructureDepthForRef || options2.minStructureDepthForRef <= structureDepth) {
|
|
306
|
+
const components = toArray(options2.components);
|
|
307
|
+
for (const component of components) {
|
|
308
|
+
if (component.schema === schema2 && component.allowedStrategies.includes(options2.strategy)) {
|
|
309
|
+
return [component.required, { $ref: component.ref }];
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
305
313
|
if (!isHandledCustomJSONSchema2) {
|
|
306
314
|
const customJSONSchema = this.#getCustomJsonSchema(schema2, options2);
|
|
307
315
|
if (customJSONSchema) {
|
|
308
|
-
const [required, json] =
|
|
316
|
+
const [required, json] = this.#convert(schema2, options2, lazyDepth2, structureDepth, true);
|
|
309
317
|
return [required, { ...json, ...customJSONSchema }];
|
|
310
318
|
}
|
|
311
319
|
}
|
|
@@ -313,21 +321,28 @@ class experimental_ZodToJsonSchemaConverter {
|
|
|
313
321
|
case "string": {
|
|
314
322
|
const string = schema2;
|
|
315
323
|
const json = { type: "string" };
|
|
316
|
-
const { minimum, maximum, format,
|
|
317
|
-
if (minimum
|
|
324
|
+
const { minimum, maximum, format, patterns, contentEncoding } = string._zod.bag;
|
|
325
|
+
if (typeof minimum === "number") {
|
|
318
326
|
json.minLength = minimum;
|
|
319
327
|
}
|
|
320
|
-
if (maximum
|
|
328
|
+
if (typeof maximum === "number") {
|
|
321
329
|
json.maxLength = maximum;
|
|
322
330
|
}
|
|
323
|
-
if (contentEncoding
|
|
331
|
+
if (typeof contentEncoding === "string") {
|
|
324
332
|
json.contentEncoding = this.#handleContentEncoding(contentEncoding);
|
|
325
333
|
}
|
|
326
|
-
if (format
|
|
334
|
+
if (typeof format === "string" && format !== "regex" && json.contentEncoding === void 0) {
|
|
327
335
|
json.format = this.#handleStringFormat(format);
|
|
328
336
|
}
|
|
329
|
-
if (
|
|
330
|
-
|
|
337
|
+
if (patterns instanceof Set && json.contentEncoding === void 0 && json.format === void 0) {
|
|
338
|
+
for (const pattern of patterns) {
|
|
339
|
+
if (json.pattern === void 0) {
|
|
340
|
+
json.pattern = pattern.source;
|
|
341
|
+
} else {
|
|
342
|
+
json.allOf ??= [];
|
|
343
|
+
json.allOf.push({ pattern: pattern.source });
|
|
344
|
+
}
|
|
345
|
+
}
|
|
331
346
|
}
|
|
332
347
|
if (format === "jwt" && json.contentEncoding === void 0 && json.format === void 0 && json.pattern === void 0) {
|
|
333
348
|
json.pattern = /^[\w-]+\.[\w-]+\.[\w-]+$/.source;
|
|
@@ -337,25 +352,23 @@ class experimental_ZodToJsonSchemaConverter {
|
|
|
337
352
|
case "number": {
|
|
338
353
|
const number = schema2;
|
|
339
354
|
const json = { type: "number" };
|
|
340
|
-
const { minimum, maximum, format, multipleOf,
|
|
341
|
-
if (format?.includes("int")) {
|
|
355
|
+
const { minimum, maximum, format, multipleOf, exclusiveMaximum, exclusiveMinimum } = number._zod.bag;
|
|
356
|
+
if (typeof format === "string" && format?.includes("int")) {
|
|
342
357
|
json.type = "integer";
|
|
343
358
|
}
|
|
344
|
-
if (minimum
|
|
345
|
-
|
|
346
|
-
json.minimum = minimum;
|
|
347
|
-
} else {
|
|
348
|
-
json.exclusiveMinimum = minimum;
|
|
349
|
-
}
|
|
359
|
+
if (typeof minimum === "number") {
|
|
360
|
+
json.minimum = minimum;
|
|
350
361
|
}
|
|
351
|
-
if (maximum
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
}
|
|
362
|
+
if (typeof maximum === "number") {
|
|
363
|
+
json.maximum = maximum;
|
|
364
|
+
}
|
|
365
|
+
if (typeof exclusiveMinimum === "number") {
|
|
366
|
+
json.exclusiveMinimum = exclusiveMinimum;
|
|
357
367
|
}
|
|
358
|
-
if (
|
|
368
|
+
if (typeof exclusiveMaximum === "number") {
|
|
369
|
+
json.exclusiveMaximum = exclusiveMaximum;
|
|
370
|
+
}
|
|
371
|
+
if (typeof multipleOf === "number") {
|
|
359
372
|
json.multipleOf = multipleOf;
|
|
360
373
|
}
|
|
361
374
|
return [true, json];
|
|
@@ -364,10 +377,18 @@ class experimental_ZodToJsonSchemaConverter {
|
|
|
364
377
|
return [true, { type: "boolean" }];
|
|
365
378
|
}
|
|
366
379
|
case "bigint": {
|
|
367
|
-
return [true, {
|
|
380
|
+
return [true, {
|
|
381
|
+
"type": "string",
|
|
382
|
+
"pattern": "^-?[0-9]+$",
|
|
383
|
+
"x-native-type": JsonSchemaXNativeType.BigInt
|
|
384
|
+
}];
|
|
368
385
|
}
|
|
369
386
|
case "date": {
|
|
370
|
-
return [true, {
|
|
387
|
+
return [true, {
|
|
388
|
+
"type": "string",
|
|
389
|
+
"format": JSONSchemaFormat.DateTime,
|
|
390
|
+
"x-native-type": JsonSchemaXNativeType.Date
|
|
391
|
+
}];
|
|
371
392
|
}
|
|
372
393
|
case "null": {
|
|
373
394
|
return [true, { type: "null" }];
|
|
@@ -388,21 +409,21 @@ class experimental_ZodToJsonSchemaConverter {
|
|
|
388
409
|
case "array": {
|
|
389
410
|
const array = schema2;
|
|
390
411
|
const json = { type: "array" };
|
|
391
|
-
const { minimum, maximum } = array._zod.
|
|
392
|
-
if (minimum
|
|
412
|
+
const { minimum, maximum } = array._zod.bag;
|
|
413
|
+
if (typeof minimum === "number") {
|
|
393
414
|
json.minItems = minimum;
|
|
394
415
|
}
|
|
395
|
-
if (maximum
|
|
416
|
+
if (typeof maximum === "number") {
|
|
396
417
|
json.maxItems = maximum;
|
|
397
418
|
}
|
|
398
|
-
json.items = this.#handleArrayItemJsonSchema(
|
|
419
|
+
json.items = this.#handleArrayItemJsonSchema(this.#convert(array._zod.def.element, options2, lazyDepth2, structureDepth + 1), options2);
|
|
399
420
|
return [true, json];
|
|
400
421
|
}
|
|
401
422
|
case "object": {
|
|
402
423
|
const object = schema2;
|
|
403
424
|
const json = { type: "object" };
|
|
404
425
|
for (const [key, value] of Object.entries(object._zod.def.shape)) {
|
|
405
|
-
const [itemRequired, itemJson] =
|
|
426
|
+
const [itemRequired, itemJson] = this.#convert(value, options2, lazyDepth2, structureDepth + 1);
|
|
406
427
|
json.properties ??= {};
|
|
407
428
|
json.properties[key] = itemJson;
|
|
408
429
|
if (itemRequired) {
|
|
@@ -414,7 +435,7 @@ class experimental_ZodToJsonSchemaConverter {
|
|
|
414
435
|
if (object._zod.def.catchall._zod.def.type === "never") {
|
|
415
436
|
json.additionalProperties = false;
|
|
416
437
|
} else {
|
|
417
|
-
const [_, addJson] =
|
|
438
|
+
const [_, addJson] = this.#convert(object._zod.def.catchall, options2, lazyDepth2, structureDepth + 1);
|
|
418
439
|
json.additionalProperties = addJson;
|
|
419
440
|
}
|
|
420
441
|
}
|
|
@@ -425,7 +446,7 @@ class experimental_ZodToJsonSchemaConverter {
|
|
|
425
446
|
const anyOf = [];
|
|
426
447
|
let required = true;
|
|
427
448
|
for (const item of union._zod.def.options) {
|
|
428
|
-
const [itemRequired, itemJson] =
|
|
449
|
+
const [itemRequired, itemJson] = this.#convert(item, options2, lazyDepth2, structureDepth + 1);
|
|
429
450
|
if (!itemRequired) {
|
|
430
451
|
required = false;
|
|
431
452
|
}
|
|
@@ -439,14 +460,14 @@ class experimental_ZodToJsonSchemaConverter {
|
|
|
439
460
|
}
|
|
440
461
|
}
|
|
441
462
|
}
|
|
442
|
-
return [required,
|
|
463
|
+
return [required, { anyOf }];
|
|
443
464
|
}
|
|
444
465
|
case "intersection": {
|
|
445
466
|
const intersection = schema2;
|
|
446
467
|
const json = { allOf: [] };
|
|
447
468
|
let required = false;
|
|
448
469
|
for (const item of [intersection._zod.def.left, intersection._zod.def.right]) {
|
|
449
|
-
const [itemRequired, itemJson] =
|
|
470
|
+
const [itemRequired, itemJson] = this.#convert(item, options2, lazyDepth2, structureDepth + 1);
|
|
450
471
|
json.allOf.push(itemJson);
|
|
451
472
|
if (itemRequired) {
|
|
452
473
|
required = true;
|
|
@@ -458,16 +479,16 @@ class experimental_ZodToJsonSchemaConverter {
|
|
|
458
479
|
const tuple = schema2;
|
|
459
480
|
const json = { type: "array", prefixItems: [] };
|
|
460
481
|
for (const item of tuple._zod.def.items) {
|
|
461
|
-
json.prefixItems.push(this.#handleArrayItemJsonSchema(
|
|
482
|
+
json.prefixItems.push(this.#handleArrayItemJsonSchema(this.#convert(item, options2, lazyDepth2, structureDepth + 1), options2));
|
|
462
483
|
}
|
|
463
484
|
if (tuple._zod.def.rest) {
|
|
464
|
-
json.items = this.#handleArrayItemJsonSchema(
|
|
485
|
+
json.items = this.#handleArrayItemJsonSchema(this.#convert(tuple._zod.def.rest, options2, lazyDepth2, structureDepth + 1), options2);
|
|
465
486
|
}
|
|
466
|
-
const { minimum, maximum } = tuple._zod.
|
|
467
|
-
if (minimum
|
|
487
|
+
const { minimum, maximum } = tuple._zod.bag;
|
|
488
|
+
if (typeof minimum === "number") {
|
|
468
489
|
json.minItems = minimum;
|
|
469
490
|
}
|
|
470
|
-
if (maximum
|
|
491
|
+
if (typeof maximum === "number") {
|
|
471
492
|
json.maxItems = maximum;
|
|
472
493
|
}
|
|
473
494
|
return [true, json];
|
|
@@ -475,31 +496,33 @@ class experimental_ZodToJsonSchemaConverter {
|
|
|
475
496
|
case "record": {
|
|
476
497
|
const record = schema2;
|
|
477
498
|
const json = { type: "object" };
|
|
478
|
-
json.propertyNames =
|
|
479
|
-
json.additionalProperties =
|
|
499
|
+
json.propertyNames = this.#convert(record._zod.def.keyType, options2, lazyDepth2, structureDepth + 1)[1];
|
|
500
|
+
json.additionalProperties = this.#convert(record._zod.def.valueType, options2, lazyDepth2, structureDepth + 1)[1];
|
|
480
501
|
return [true, json];
|
|
481
502
|
}
|
|
482
503
|
case "map": {
|
|
483
504
|
const map = schema2;
|
|
484
505
|
return [true, {
|
|
485
|
-
type: "array",
|
|
486
|
-
items: {
|
|
506
|
+
"type": "array",
|
|
507
|
+
"items": {
|
|
487
508
|
type: "array",
|
|
488
509
|
prefixItems: [
|
|
489
|
-
this.#handleArrayItemJsonSchema(
|
|
490
|
-
this.#handleArrayItemJsonSchema(
|
|
510
|
+
this.#handleArrayItemJsonSchema(this.#convert(map._zod.def.keyType, options2, lazyDepth2, structureDepth + 1), options2),
|
|
511
|
+
this.#handleArrayItemJsonSchema(this.#convert(map._zod.def.valueType, options2, lazyDepth2, structureDepth + 1), options2)
|
|
491
512
|
],
|
|
492
513
|
maxItems: 2,
|
|
493
514
|
minItems: 2
|
|
494
|
-
}
|
|
515
|
+
},
|
|
516
|
+
"x-native-type": JsonSchemaXNativeType.Map
|
|
495
517
|
}];
|
|
496
518
|
}
|
|
497
519
|
case "set": {
|
|
498
520
|
const set = schema2;
|
|
499
521
|
return [true, {
|
|
500
|
-
type: "array",
|
|
501
|
-
uniqueItems: true,
|
|
502
|
-
items: this.#handleArrayItemJsonSchema(
|
|
522
|
+
"type": "array",
|
|
523
|
+
"uniqueItems": true,
|
|
524
|
+
"items": this.#handleArrayItemJsonSchema(this.#convert(set._zod.def.valueType, options2, lazyDepth2, structureDepth + 1), options2),
|
|
525
|
+
"x-native-type": JsonSchemaXNativeType.Set
|
|
503
526
|
}];
|
|
504
527
|
}
|
|
505
528
|
case "enum": {
|
|
@@ -523,12 +546,14 @@ class experimental_ZodToJsonSchemaConverter {
|
|
|
523
546
|
case "file": {
|
|
524
547
|
const file = schema2;
|
|
525
548
|
const oneOf = [];
|
|
526
|
-
const { mime } = file._zod.
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
549
|
+
const { mime } = file._zod.bag;
|
|
550
|
+
if (mime === void 0 || Array.isArray(mime) && mime.every((m) => typeof m === "string")) {
|
|
551
|
+
for (const type of mime ?? ["*/*"]) {
|
|
552
|
+
oneOf.push({
|
|
553
|
+
type: "string",
|
|
554
|
+
contentMediaType: type
|
|
555
|
+
});
|
|
556
|
+
}
|
|
532
557
|
}
|
|
533
558
|
return [true, oneOf.length === 1 ? oneOf[0] : { anyOf: oneOf }];
|
|
534
559
|
}
|
|
@@ -537,40 +562,46 @@ class experimental_ZodToJsonSchemaConverter {
|
|
|
537
562
|
}
|
|
538
563
|
case "nullable": {
|
|
539
564
|
const nullable = schema2;
|
|
540
|
-
const [required, json] =
|
|
565
|
+
const [required, json] = this.#convert(nullable._zod.def.innerType, options2, lazyDepth2, structureDepth);
|
|
541
566
|
return [required, { anyOf: [json, { type: "null" }] }];
|
|
542
567
|
}
|
|
543
568
|
case "nonoptional": {
|
|
544
569
|
const nonoptional = schema2;
|
|
545
|
-
const [, json] =
|
|
570
|
+
const [, json] = this.#convert(nonoptional._zod.def.innerType, options2, lazyDepth2, structureDepth);
|
|
546
571
|
return [true, json];
|
|
547
572
|
}
|
|
548
573
|
case "success": {
|
|
549
574
|
return [true, { type: "boolean" }];
|
|
550
575
|
}
|
|
551
|
-
case "default":
|
|
576
|
+
case "default":
|
|
577
|
+
case "prefault": {
|
|
552
578
|
const default_ = schema2;
|
|
553
|
-
const [, json] =
|
|
579
|
+
const [, json] = this.#convert(default_._zod.def.innerType, options2, lazyDepth2, structureDepth);
|
|
554
580
|
return [false, {
|
|
555
581
|
...json,
|
|
556
|
-
default: default_._zod.def.defaultValue
|
|
582
|
+
default: default_._zod.def.defaultValue
|
|
557
583
|
}];
|
|
558
584
|
}
|
|
559
585
|
case "catch": {
|
|
560
586
|
const catch_ = schema2;
|
|
561
|
-
|
|
562
|
-
return [false, json];
|
|
587
|
+
return this.#convert(catch_._zod.def.innerType, options2, lazyDepth2, structureDepth);
|
|
563
588
|
}
|
|
564
589
|
case "nan": {
|
|
565
590
|
return [true, options2.strategy === "input" ? this.unsupportedJsonSchema : { type: "null" }];
|
|
566
591
|
}
|
|
567
592
|
case "pipe": {
|
|
568
593
|
const pipe = schema2;
|
|
569
|
-
return
|
|
594
|
+
return this.#convert(
|
|
595
|
+
// prefer out schema when in schema is preprocess/transform
|
|
596
|
+
options2.strategy === "input" && pipe._zod.def.in._zod.def.type !== "transform" ? pipe._zod.def.in : pipe._zod.def.out,
|
|
597
|
+
options2,
|
|
598
|
+
lazyDepth2,
|
|
599
|
+
structureDepth
|
|
600
|
+
);
|
|
570
601
|
}
|
|
571
602
|
case "readonly": {
|
|
572
603
|
const readonly_ = schema2;
|
|
573
|
-
const [required, json] =
|
|
604
|
+
const [required, json] = this.#convert(readonly_._zod.def.innerType, options2, lazyDepth2, structureDepth);
|
|
574
605
|
return [required, { ...json, readOnly: true }];
|
|
575
606
|
}
|
|
576
607
|
case "template_literal": {
|
|
@@ -582,15 +613,16 @@ class experimental_ZodToJsonSchemaConverter {
|
|
|
582
613
|
}
|
|
583
614
|
case "optional": {
|
|
584
615
|
const optional = schema2;
|
|
585
|
-
const [, json] =
|
|
616
|
+
const [, json] = this.#convert(optional._zod.def.innerType, options2, lazyDepth2, structureDepth);
|
|
586
617
|
return [false, json];
|
|
587
618
|
}
|
|
588
619
|
case "lazy": {
|
|
589
620
|
const lazy = schema2;
|
|
590
|
-
|
|
621
|
+
const currentLazyDepth = lazyDepth2 + 1;
|
|
622
|
+
if (currentLazyDepth > this.maxLazyDepth) {
|
|
591
623
|
return [false, this.anyJsonSchema];
|
|
592
624
|
}
|
|
593
|
-
return
|
|
625
|
+
return this.#convert(lazy._zod.def.getter(), options2, currentLazyDepth, structureDepth);
|
|
594
626
|
}
|
|
595
627
|
default: {
|
|
596
628
|
schema2._zod.def.type;
|
|
@@ -601,25 +633,26 @@ class experimental_ZodToJsonSchemaConverter {
|
|
|
601
633
|
);
|
|
602
634
|
}
|
|
603
635
|
#getCustomJsonSchema(schema, options) {
|
|
604
|
-
if (options.strategy === "input" &&
|
|
605
|
-
return
|
|
636
|
+
if (options.strategy === "input" && JSON_SCHEMA_INPUT_REGISTRY.has(schema)) {
|
|
637
|
+
return JSON_SCHEMA_INPUT_REGISTRY.get(schema);
|
|
606
638
|
}
|
|
607
|
-
if (options.strategy === "output" &&
|
|
608
|
-
return
|
|
639
|
+
if (options.strategy === "output" && JSON_SCHEMA_OUTPUT_REGISTRY.has(schema)) {
|
|
640
|
+
return JSON_SCHEMA_OUTPUT_REGISTRY.get(schema);
|
|
609
641
|
}
|
|
610
|
-
if (
|
|
611
|
-
return
|
|
642
|
+
if (JSON_SCHEMA_REGISTRY.has(schema)) {
|
|
643
|
+
return JSON_SCHEMA_REGISTRY.get(schema);
|
|
612
644
|
}
|
|
613
645
|
const global = globalRegistry.get(schema);
|
|
614
646
|
if (global) {
|
|
615
647
|
return {
|
|
648
|
+
title: global.title,
|
|
616
649
|
description: global.description,
|
|
617
|
-
examples: global.examples
|
|
650
|
+
examples: Array.isArray(global.examples) ? global.examples : void 0
|
|
618
651
|
};
|
|
619
652
|
}
|
|
620
653
|
}
|
|
621
654
|
#handleArrayItemJsonSchema([required, schema], options) {
|
|
622
|
-
if (required || options.strategy === "input") {
|
|
655
|
+
if (required || options.strategy === "input" || schema.default !== void 0) {
|
|
623
656
|
return schema;
|
|
624
657
|
}
|
|
625
658
|
if (schema === this.undefinedJsonSchema) {
|
|
@@ -650,4 +683,4 @@ class experimental_ZodToJsonSchemaConverter {
|
|
|
650
683
|
}
|
|
651
684
|
}
|
|
652
685
|
|
|
653
|
-
export {
|
|
686
|
+
export { JSON_SCHEMA_INPUT_REGISTRY, JSON_SCHEMA_OUTPUT_REGISTRY, JSON_SCHEMA_REGISTRY, ZodToJsonSchemaConverter, experimental_ZodSmartCoercionPlugin };
|