@orpc/zod 0.0.0-next.cac5dd3 → 0.0.0-next.caeb672
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 +8 -10
- package/dist/index.d.mts +16 -7
- package/dist/index.d.ts +16 -7
- package/dist/index.mjs +78 -41
- package/dist/zod4/index.d.mts +30 -18
- package/dist/zod4/index.d.ts +30 -18
- package/dist/zod4/index.mjs +142 -115
- package/package.json +8 -20
package/README.md
CHANGED
@@ -30,7 +30,7 @@
|
|
30
30
|
- **🔗 End-to-End Type Safety**: Ensure type-safe inputs, outputs, and errors from client to server.
|
31
31
|
- **📘 First-Class OpenAPI**: Built-in support that fully adheres to the OpenAPI standard.
|
32
32
|
- **📝 Contract-First Development**: Optionally define your API contract before implementation.
|
33
|
-
- **⚙️ Framework Integrations**: Seamlessly integrate with TanStack Query (React, Vue, Solid, Svelte), Pinia Colada, and more.
|
33
|
+
- **⚙️ Framework Integrations**: Seamlessly integrate with TanStack Query (React, Vue, Solid, Svelte, Angular), Pinia Colada, and more.
|
34
34
|
- **🚀 Server Actions**: Fully compatible with React Server Actions on Next.js, TanStack Start, and other platforms.
|
35
35
|
- **🔠 Standard Schema Support**: Works out of the box with Zod, Valibot, ArkType, and other schema validators.
|
36
36
|
- **🗃️ Native Types**: Supports native types like Date, File, Blob, BigInt, URL, and more.
|
@@ -49,14 +49,12 @@ You can find the full documentation [here](https://orpc.unnoq.com).
|
|
49
49
|
- [@orpc/contract](https://www.npmjs.com/package/@orpc/contract): Build your API contract.
|
50
50
|
- [@orpc/server](https://www.npmjs.com/package/@orpc/server): Build your API or implement API contract.
|
51
51
|
- [@orpc/client](https://www.npmjs.com/package/@orpc/client): Consume your API on the client with type-safety.
|
52
|
-
- [@orpc/
|
52
|
+
- [@orpc/openapi](https://www.npmjs.com/package/@orpc/openapi): Generate OpenAPI specs and handle OpenAPI requests.
|
53
|
+
- [@orpc/nest](https://www.npmjs.com/package/@orpc/nest): Deeply integrate oRPC with [NestJS](https://nestjs.com/).
|
53
54
|
- [@orpc/react](https://www.npmjs.com/package/@orpc/react): Utilities for integrating oRPC with React and React Server Actions.
|
54
|
-
- [@orpc/
|
55
|
-
- [@orpc/vue-query](https://www.npmjs.com/package/@orpc/vue-query): Integration with [Vue Query](https://tanstack.com/query/latest/docs/framework/vue/overview).
|
56
|
-
- [@orpc/solid-query](https://www.npmjs.com/package/@orpc/solid-query): Integration with [Solid Query](https://tanstack.com/query/latest/docs/framework/solid/overview).
|
57
|
-
- [@orpc/svelte-query](https://www.npmjs.com/package/@orpc/svelte-query): Integration with [Svelte Query](https://tanstack.com/query/latest/docs/framework/svelte/overview).
|
55
|
+
- [@orpc/tanstack-query](https://www.npmjs.com/package/@orpc/tanstack-query): [TanStack Query](https://tanstack.com/query/latest) integration.
|
58
56
|
- [@orpc/vue-colada](https://www.npmjs.com/package/@orpc/vue-colada): Integration with [Pinia Colada](https://pinia-colada.esm.dev/).
|
59
|
-
- [@orpc/
|
57
|
+
- [@orpc/hey-api](https://www.npmjs.com/package/@orpc/hey-api): [Hey API](https://heyapi.dev/) integration.
|
60
58
|
- [@orpc/zod](https://www.npmjs.com/package/@orpc/zod): More schemas that [Zod](https://zod.dev/) doesn't support yet.
|
61
59
|
- [@orpc/valibot](https://www.npmjs.com/package/@orpc/valibot): OpenAPI spec generation from [Valibot](https://valibot.dev/).
|
62
60
|
- [@orpc/arktype](https://www.npmjs.com/package/@orpc/arktype): OpenAPI spec generation from [ArkType](https://arktype.io/).
|
@@ -74,7 +72,7 @@ More schemas that [Zod](https://zod.dev/) doesn't support yet, and provides `Zod
|
|
74
72
|
|
75
73
|
```ts
|
76
74
|
import { oz } from '@orpc/zod'
|
77
|
-
import { z } from 'zod'
|
75
|
+
import { z } from 'zod/v3'
|
78
76
|
|
79
77
|
const Example = z.object({
|
80
78
|
url: oz.url(),
|
@@ -88,7 +86,7 @@ const Example = z.object({
|
|
88
86
|
|
89
87
|
```ts
|
90
88
|
import { OpenAPIGenerator } from '@orpc/openapi'
|
91
|
-
import { ZodToJsonSchemaConverter } from '@orpc/zod'
|
89
|
+
import { ZodToJsonSchemaConverter } from '@orpc/zod/zod4'
|
92
90
|
|
93
91
|
const openAPIGenerator = new OpenAPIGenerator({
|
94
92
|
schemaConverters: [new ZodToJsonSchemaConverter()],
|
@@ -113,7 +111,7 @@ const specFromRouter = await openAPIGenerator.generate(router, {
|
|
113
111
|
|
114
112
|
```ts
|
115
113
|
import { oz } from '@orpc/zod'
|
116
|
-
import
|
114
|
+
import * as z from 'zod'
|
117
115
|
|
118
116
|
const InputSchema = oz.openapi(
|
119
117
|
z.object({
|
package/dist/index.d.mts
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
import { JSONSchema, ConditionalSchemaConverter, SchemaConvertOptions } from '@orpc/openapi';
|
2
|
-
import { ZodTypeAny, input, output, ZodTypeDef, CustomErrorParams, ZodType, ZodEffects } from 'zod';
|
2
|
+
import { ZodTypeAny, input, output, ZodTypeDef, CustomErrorParams, ZodType, ZodEffects } from 'zod/v3';
|
3
3
|
import { Context } from '@orpc/server';
|
4
4
|
import { StandardHandlerPlugin, StandardHandlerOptions } from '@orpc/server/standard';
|
5
5
|
import { AnySchema } from '@orpc/contract';
|
@@ -40,34 +40,43 @@ declare class ZodSmartCoercionPlugin<TContext extends Context> implements Standa
|
|
40
40
|
|
41
41
|
interface ZodToJsonSchemaOptions {
|
42
42
|
/**
|
43
|
-
* Max depth of lazy type
|
43
|
+
* Max depth of lazy type
|
44
44
|
*
|
45
|
-
* Used `{}` when
|
45
|
+
* Used `{}` when exceed max depth
|
46
46
|
*
|
47
47
|
* @default 3
|
48
48
|
*/
|
49
49
|
maxLazyDepth?: number;
|
50
50
|
/**
|
51
|
-
*
|
51
|
+
* Max depth of nested types
|
52
52
|
*
|
53
|
-
*
|
53
|
+
* Used anyJsonSchema (`{}`) when exceed max depth
|
54
|
+
*
|
55
|
+
* @default 10
|
54
56
|
*/
|
55
|
-
|
57
|
+
maxStructureDepth?: number;
|
56
58
|
/**
|
57
59
|
* The schema to be used to represent the any | unknown type.
|
58
60
|
*
|
59
61
|
* @default { }
|
60
62
|
*/
|
61
63
|
anyJsonSchema?: Exclude<JSONSchema, boolean>;
|
64
|
+
/**
|
65
|
+
* The schema to be used when the Zod schema is unsupported.
|
66
|
+
*
|
67
|
+
* @default { not: {} }
|
68
|
+
*/
|
69
|
+
unsupportedJsonSchema?: Exclude<JSONSchema, boolean>;
|
62
70
|
}
|
63
71
|
declare class ZodToJsonSchemaConverter implements ConditionalSchemaConverter {
|
64
72
|
#private;
|
65
73
|
private readonly maxLazyDepth;
|
74
|
+
private readonly maxStructureDepth;
|
66
75
|
private readonly unsupportedJsonSchema;
|
67
76
|
private readonly anyJsonSchema;
|
68
77
|
constructor(options?: ZodToJsonSchemaOptions);
|
69
78
|
condition(schema: AnySchema | undefined): boolean;
|
70
|
-
convert(schema: AnySchema | undefined, options: SchemaConvertOptions, lazyDepth?: number, isHandledCustomJSONSchema?: boolean, isHandledZodDescription?: boolean): [required: boolean, jsonSchema: Exclude<JSONSchema, boolean>];
|
79
|
+
convert(schema: AnySchema | undefined, options: SchemaConvertOptions, lazyDepth?: number, isHandledCustomJSONSchema?: boolean, isHandledZodDescription?: boolean, structureDepth?: number): [required: boolean, jsonSchema: Exclude<JSONSchema, boolean>];
|
71
80
|
}
|
72
81
|
|
73
82
|
declare const oz: {
|
package/dist/index.d.ts
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
import { JSONSchema, ConditionalSchemaConverter, SchemaConvertOptions } from '@orpc/openapi';
|
2
|
-
import { ZodTypeAny, input, output, ZodTypeDef, CustomErrorParams, ZodType, ZodEffects } from 'zod';
|
2
|
+
import { ZodTypeAny, input, output, ZodTypeDef, CustomErrorParams, ZodType, ZodEffects } from 'zod/v3';
|
3
3
|
import { Context } from '@orpc/server';
|
4
4
|
import { StandardHandlerPlugin, StandardHandlerOptions } from '@orpc/server/standard';
|
5
5
|
import { AnySchema } from '@orpc/contract';
|
@@ -40,34 +40,43 @@ declare class ZodSmartCoercionPlugin<TContext extends Context> implements Standa
|
|
40
40
|
|
41
41
|
interface ZodToJsonSchemaOptions {
|
42
42
|
/**
|
43
|
-
* Max depth of lazy type
|
43
|
+
* Max depth of lazy type
|
44
44
|
*
|
45
|
-
* Used `{}` when
|
45
|
+
* Used `{}` when exceed max depth
|
46
46
|
*
|
47
47
|
* @default 3
|
48
48
|
*/
|
49
49
|
maxLazyDepth?: number;
|
50
50
|
/**
|
51
|
-
*
|
51
|
+
* Max depth of nested types
|
52
52
|
*
|
53
|
-
*
|
53
|
+
* Used anyJsonSchema (`{}`) when exceed max depth
|
54
|
+
*
|
55
|
+
* @default 10
|
54
56
|
*/
|
55
|
-
|
57
|
+
maxStructureDepth?: number;
|
56
58
|
/**
|
57
59
|
* The schema to be used to represent the any | unknown type.
|
58
60
|
*
|
59
61
|
* @default { }
|
60
62
|
*/
|
61
63
|
anyJsonSchema?: Exclude<JSONSchema, boolean>;
|
64
|
+
/**
|
65
|
+
* The schema to be used when the Zod schema is unsupported.
|
66
|
+
*
|
67
|
+
* @default { not: {} }
|
68
|
+
*/
|
69
|
+
unsupportedJsonSchema?: Exclude<JSONSchema, boolean>;
|
62
70
|
}
|
63
71
|
declare class ZodToJsonSchemaConverter implements ConditionalSchemaConverter {
|
64
72
|
#private;
|
65
73
|
private readonly maxLazyDepth;
|
74
|
+
private readonly maxStructureDepth;
|
66
75
|
private readonly unsupportedJsonSchema;
|
67
76
|
private readonly anyJsonSchema;
|
68
77
|
constructor(options?: ZodToJsonSchemaOptions);
|
69
78
|
condition(schema: AnySchema | undefined): boolean;
|
70
|
-
convert(schema: AnySchema | undefined, options: SchemaConvertOptions, lazyDepth?: number, isHandledCustomJSONSchema?: boolean, isHandledZodDescription?: boolean): [required: boolean, jsonSchema: Exclude<JSONSchema, boolean>];
|
79
|
+
convert(schema: AnySchema | undefined, options: SchemaConvertOptions, lazyDepth?: number, isHandledCustomJSONSchema?: boolean, isHandledZodDescription?: boolean, structureDepth?: number): [required: boolean, jsonSchema: Exclude<JSONSchema, boolean>];
|
71
80
|
}
|
72
81
|
|
73
82
|
declare const oz: {
|
package/dist/index.mjs
CHANGED
@@ -1,6 +1,7 @@
|
|
1
|
-
import { custom, ZodFirstPartyTypeKind } from 'zod';
|
1
|
+
import { custom, ZodFirstPartyTypeKind } from 'zod/v3';
|
2
2
|
import wcmatch from 'wildcard-match';
|
3
|
-
import { isObject, guard } from '@orpc/shared';
|
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
7
|
|
@@ -128,7 +129,7 @@ class ZodSmartCoercionPlugin {
|
|
128
129
|
options.clientInterceptors ??= [];
|
129
130
|
options.clientInterceptors.unshift((options2) => {
|
130
131
|
const inputSchema = options2.procedure["~orpc"].inputSchema;
|
131
|
-
if (!inputSchema || inputSchema["~standard"].vendor !== "zod") {
|
132
|
+
if (!inputSchema || inputSchema["~standard"].vendor !== "zod" || "_zod" in inputSchema) {
|
132
133
|
return options2.next();
|
133
134
|
}
|
134
135
|
const coercedInput = zodCoerceInternal(inputSchema, options2.input);
|
@@ -390,25 +391,39 @@ function safeToDate(value) {
|
|
390
391
|
|
391
392
|
class ZodToJsonSchemaConverter {
|
392
393
|
maxLazyDepth;
|
394
|
+
maxStructureDepth;
|
393
395
|
unsupportedJsonSchema;
|
394
396
|
anyJsonSchema;
|
395
397
|
constructor(options = {}) {
|
396
398
|
this.maxLazyDepth = options.maxLazyDepth ?? 3;
|
399
|
+
this.maxStructureDepth = options.maxStructureDepth ?? 10;
|
397
400
|
this.unsupportedJsonSchema = options.unsupportedJsonSchema ?? { not: {} };
|
398
401
|
this.anyJsonSchema = options.anyJsonSchema ?? {};
|
399
402
|
}
|
400
403
|
condition(schema) {
|
401
|
-
return schema !== void 0 && schema["~standard"].vendor === "zod";
|
404
|
+
return schema !== void 0 && schema["~standard"].vendor === "zod" && !("_zod" in schema);
|
402
405
|
}
|
403
|
-
convert(schema, options, lazyDepth = 0, isHandledCustomJSONSchema = false, isHandledZodDescription = false) {
|
406
|
+
convert(schema, options, lazyDepth = 0, isHandledCustomJSONSchema = false, isHandledZodDescription = false, structureDepth = 0) {
|
404
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
|
+
}
|
405
419
|
if (!isHandledZodDescription && "description" in def && typeof def.description === "string") {
|
406
420
|
const [required, json] = this.convert(
|
407
421
|
schema,
|
408
422
|
options,
|
409
423
|
lazyDepth,
|
410
424
|
isHandledCustomJSONSchema,
|
411
|
-
true
|
425
|
+
true,
|
426
|
+
structureDepth
|
412
427
|
);
|
413
428
|
return [required, { ...json, description: def.description }];
|
414
429
|
}
|
@@ -420,7 +435,8 @@ class ZodToJsonSchemaConverter {
|
|
420
435
|
options,
|
421
436
|
lazyDepth,
|
422
437
|
true,
|
423
|
-
isHandledZodDescription
|
438
|
+
isHandledZodDescription,
|
439
|
+
structureDepth
|
424
440
|
);
|
425
441
|
return [required, { ...json, ...customJSONSchema }];
|
426
442
|
}
|
@@ -548,7 +564,11 @@ class ZodToJsonSchemaConverter {
|
|
548
564
|
return [true, json];
|
549
565
|
}
|
550
566
|
case ZodFirstPartyTypeKind.ZodBigInt: {
|
551
|
-
const json = {
|
567
|
+
const json = {
|
568
|
+
"type": "string",
|
569
|
+
"pattern": "^-?[0-9]+$",
|
570
|
+
"x-native-type": JsonSchemaXNativeType.BigInt
|
571
|
+
};
|
552
572
|
return [true, json];
|
553
573
|
}
|
554
574
|
case ZodFirstPartyTypeKind.ZodNaN: {
|
@@ -558,7 +578,11 @@ class ZodToJsonSchemaConverter {
|
|
558
578
|
return [true, { type: "boolean" }];
|
559
579
|
}
|
560
580
|
case ZodFirstPartyTypeKind.ZodDate: {
|
561
|
-
const schema2 = {
|
581
|
+
const schema2 = {
|
582
|
+
"type": "string",
|
583
|
+
"format": JSONSchemaFormat.DateTime,
|
584
|
+
"x-native-type": JsonSchemaXNativeType.Date
|
585
|
+
};
|
562
586
|
return [true, schema2];
|
563
587
|
}
|
564
588
|
case ZodFirstPartyTypeKind.ZodNull: {
|
@@ -591,7 +615,7 @@ class ZodToJsonSchemaConverter {
|
|
591
615
|
const schema_ = schema;
|
592
616
|
const def2 = schema_._def;
|
593
617
|
const json = { type: "array" };
|
594
|
-
const [itemRequired, itemJson] = this.convert(def2.type, options, lazyDepth, false, false);
|
618
|
+
const [itemRequired, itemJson] = this.convert(def2.type, options, lazyDepth, false, false, structureDepth + 1);
|
595
619
|
json.items = this.#toArrayItemJsonSchema(itemRequired, itemJson, options.strategy);
|
596
620
|
if (def2.exactLength) {
|
597
621
|
json.maxItems = def2.exactLength.value;
|
@@ -610,7 +634,7 @@ class ZodToJsonSchemaConverter {
|
|
610
634
|
const prefixItems = [];
|
611
635
|
const json = { type: "array" };
|
612
636
|
for (const item of schema_._def.items) {
|
613
|
-
const [itemRequired, itemJson] = this.convert(item, options, lazyDepth, false, false);
|
637
|
+
const [itemRequired, itemJson] = this.convert(item, options, lazyDepth, false, false, structureDepth + 1);
|
614
638
|
prefixItems.push(
|
615
639
|
this.#toArrayItemJsonSchema(itemRequired, itemJson, options.strategy)
|
616
640
|
);
|
@@ -619,7 +643,7 @@ class ZodToJsonSchemaConverter {
|
|
619
643
|
json.prefixItems = prefixItems;
|
620
644
|
}
|
621
645
|
if (schema_._def.rest) {
|
622
|
-
const [itemRequired, itemJson] = this.convert(schema_._def.rest, options, lazyDepth, false, false);
|
646
|
+
const [itemRequired, itemJson] = this.convert(schema_._def.rest, options, lazyDepth, false, false, structureDepth + 1);
|
623
647
|
json.items = this.#toArrayItemJsonSchema(itemRequired, itemJson, options.strategy);
|
624
648
|
}
|
625
649
|
return [true, json];
|
@@ -630,7 +654,7 @@ class ZodToJsonSchemaConverter {
|
|
630
654
|
const properties = {};
|
631
655
|
const required = [];
|
632
656
|
for (const [key, value] of Object.entries(schema_.shape)) {
|
633
|
-
const [itemRequired, itemJson] = this.convert(value, options, lazyDepth, false, false);
|
657
|
+
const [itemRequired, itemJson] = this.convert(value, options, lazyDepth, false, false, structureDepth + 1);
|
634
658
|
properties[key] = itemJson;
|
635
659
|
if (itemRequired) {
|
636
660
|
required.push(key);
|
@@ -648,7 +672,7 @@ class ZodToJsonSchemaConverter {
|
|
648
672
|
json.additionalProperties = false;
|
649
673
|
}
|
650
674
|
} else {
|
651
|
-
const [_, addJson] = this.convert(schema_._def.catchall, options, lazyDepth, false, false);
|
675
|
+
const [_, addJson] = this.convert(schema_._def.catchall, options, lazyDepth, false, false, structureDepth + 1);
|
652
676
|
json.additionalProperties = addJson;
|
653
677
|
}
|
654
678
|
return [true, json];
|
@@ -656,28 +680,32 @@ class ZodToJsonSchemaConverter {
|
|
656
680
|
case ZodFirstPartyTypeKind.ZodRecord: {
|
657
681
|
const schema_ = schema;
|
658
682
|
const json = { type: "object" };
|
659
|
-
const [__, keyJson] = this.convert(schema_._def.keyType, options, lazyDepth, false, false);
|
683
|
+
const [__, keyJson] = this.convert(schema_._def.keyType, options, lazyDepth, false, false, structureDepth + 1);
|
660
684
|
if (Object.entries(keyJson).some(([k, v]) => k !== "type" || v !== "string")) {
|
661
685
|
json.propertyNames = keyJson;
|
662
686
|
}
|
663
|
-
const [_, itemJson] = this.convert(schema_._def.valueType, options, lazyDepth, false, false);
|
687
|
+
const [_, itemJson] = this.convert(schema_._def.valueType, options, lazyDepth, false, false, structureDepth + 1);
|
664
688
|
json.additionalProperties = itemJson;
|
665
689
|
return [true, json];
|
666
690
|
}
|
667
691
|
case ZodFirstPartyTypeKind.ZodSet: {
|
668
692
|
const schema_ = schema;
|
669
|
-
const json = {
|
670
|
-
|
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);
|
671
699
|
json.items = this.#toArrayItemJsonSchema(itemRequired, itemJson, options.strategy);
|
672
700
|
return [true, json];
|
673
701
|
}
|
674
702
|
case ZodFirstPartyTypeKind.ZodMap: {
|
675
703
|
const schema_ = schema;
|
676
|
-
const [keyRequired, keyJson] = this.convert(schema_._def.keyType, options, lazyDepth, false, false);
|
677
|
-
const [valueRequired, valueJson] = this.convert(schema_._def.valueType, options, lazyDepth, false, false);
|
678
|
-
|
679
|
-
type: "array",
|
680
|
-
items: {
|
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": {
|
681
709
|
type: "array",
|
682
710
|
prefixItems: [
|
683
711
|
this.#toArrayItemJsonSchema(keyRequired, keyJson, options.strategy),
|
@@ -685,8 +713,10 @@ class ZodToJsonSchemaConverter {
|
|
685
713
|
],
|
686
714
|
maxItems: 2,
|
687
715
|
minItems: 2
|
688
|
-
}
|
689
|
-
|
716
|
+
},
|
717
|
+
"x-native-type": JsonSchemaXNativeType.Map
|
718
|
+
};
|
719
|
+
return [true, json];
|
690
720
|
}
|
691
721
|
case ZodFirstPartyTypeKind.ZodUnion:
|
692
722
|
case ZodFirstPartyTypeKind.ZodDiscriminatedUnion: {
|
@@ -694,7 +724,7 @@ class ZodToJsonSchemaConverter {
|
|
694
724
|
const anyOf = [];
|
695
725
|
let required = true;
|
696
726
|
for (const item of schema_._def.options) {
|
697
|
-
const [itemRequired, itemJson] = this.convert(item, options, lazyDepth, false, false);
|
727
|
+
const [itemRequired, itemJson] = this.convert(item, options, lazyDepth, false, false, structureDepth);
|
698
728
|
if (!itemRequired) {
|
699
729
|
required = false;
|
700
730
|
if (itemJson !== this.unsupportedJsonSchema) {
|
@@ -714,7 +744,7 @@ class ZodToJsonSchemaConverter {
|
|
714
744
|
const allOf = [];
|
715
745
|
let required = false;
|
716
746
|
for (const item of [schema_._def.left, schema_._def.right]) {
|
717
|
-
const [itemRequired, itemJson] = this.convert(item, options, lazyDepth, false, false);
|
747
|
+
const [itemRequired, itemJson] = this.convert(item, options, lazyDepth, false, false, structureDepth);
|
718
748
|
allOf.push(itemJson);
|
719
749
|
if (itemRequired) {
|
720
750
|
required = true;
|
@@ -723,25 +753,26 @@ class ZodToJsonSchemaConverter {
|
|
723
753
|
return [required, { allOf }];
|
724
754
|
}
|
725
755
|
case ZodFirstPartyTypeKind.ZodLazy: {
|
726
|
-
|
756
|
+
const currentLazyDepth = lazyDepth + 1;
|
757
|
+
if (currentLazyDepth > this.maxLazyDepth) {
|
727
758
|
return [false, this.anyJsonSchema];
|
728
759
|
}
|
729
760
|
const schema_ = schema;
|
730
|
-
return this.convert(schema_._def.getter(), options,
|
761
|
+
return this.convert(schema_._def.getter(), options, currentLazyDepth, false, false, structureDepth);
|
731
762
|
}
|
732
763
|
case ZodFirstPartyTypeKind.ZodOptional: {
|
733
764
|
const schema_ = schema;
|
734
|
-
const [_, inner] = this.convert(schema_._def.innerType, options, lazyDepth, false, false);
|
765
|
+
const [_, inner] = this.convert(schema_._def.innerType, options, lazyDepth, false, false, structureDepth);
|
735
766
|
return [false, inner];
|
736
767
|
}
|
737
768
|
case ZodFirstPartyTypeKind.ZodReadonly: {
|
738
769
|
const schema_ = schema;
|
739
|
-
const [required, json] = this.convert(schema_._def.innerType, options, lazyDepth, false, false);
|
770
|
+
const [required, json] = this.convert(schema_._def.innerType, options, lazyDepth, false, false, structureDepth);
|
740
771
|
return [required, { ...json, readOnly: true }];
|
741
772
|
}
|
742
773
|
case ZodFirstPartyTypeKind.ZodDefault: {
|
743
774
|
const schema_ = schema;
|
744
|
-
const [_, json] = this.convert(schema_._def.innerType, options, lazyDepth, false, false);
|
775
|
+
const [_, json] = this.convert(schema_._def.innerType, options, lazyDepth, false, false, structureDepth);
|
745
776
|
return [false, { default: schema_._def.defaultValue(), ...json }];
|
746
777
|
}
|
747
778
|
case ZodFirstPartyTypeKind.ZodEffects: {
|
@@ -749,15 +780,15 @@ class ZodToJsonSchemaConverter {
|
|
749
780
|
if (schema_._def.effect.type === "transform" && options.strategy === "output") {
|
750
781
|
return [false, this.anyJsonSchema];
|
751
782
|
}
|
752
|
-
return this.convert(schema_._def.schema, options, lazyDepth, false, false);
|
783
|
+
return this.convert(schema_._def.schema, options, lazyDepth, false, false, structureDepth);
|
753
784
|
}
|
754
785
|
case ZodFirstPartyTypeKind.ZodCatch: {
|
755
786
|
const schema_ = schema;
|
756
|
-
return this.convert(schema_._def.innerType, options, lazyDepth, false, false);
|
787
|
+
return this.convert(schema_._def.innerType, options, lazyDepth, false, false, structureDepth);
|
757
788
|
}
|
758
789
|
case ZodFirstPartyTypeKind.ZodBranded: {
|
759
790
|
const schema_ = schema;
|
760
|
-
return this.convert(schema_._def.type, options, lazyDepth, false, false);
|
791
|
+
return this.convert(schema_._def.type, options, lazyDepth, false, false, structureDepth);
|
761
792
|
}
|
762
793
|
case ZodFirstPartyTypeKind.ZodPipeline: {
|
763
794
|
const schema_ = schema;
|
@@ -766,13 +797,14 @@ class ZodToJsonSchemaConverter {
|
|
766
797
|
options,
|
767
798
|
lazyDepth,
|
768
799
|
false,
|
769
|
-
false
|
800
|
+
false,
|
801
|
+
structureDepth
|
770
802
|
);
|
771
803
|
}
|
772
804
|
case ZodFirstPartyTypeKind.ZodNullable: {
|
773
805
|
const schema_ = schema;
|
774
|
-
const [required, json] = this.convert(schema_._def.innerType, options, lazyDepth, false, false);
|
775
|
-
return [required, { anyOf: [{ type: "null" }
|
806
|
+
const [required, json] = this.convert(schema_._def.innerType, options, lazyDepth, false, false, structureDepth);
|
807
|
+
return [required, { anyOf: [json, { type: "null" }] }];
|
776
808
|
}
|
777
809
|
}
|
778
810
|
return [true, this.unsupportedJsonSchema];
|
@@ -791,12 +823,17 @@ class ZodToJsonSchemaConverter {
|
|
791
823
|
}
|
792
824
|
case "regexp": {
|
793
825
|
return {
|
794
|
-
type: "string",
|
795
|
-
pattern: "^\\/(.*)\\/([a-z]*)$"
|
826
|
+
"type": "string",
|
827
|
+
"pattern": "^\\/(.*)\\/([a-z]*)$",
|
828
|
+
"x-native-type": JsonSchemaXNativeType.RegExp
|
796
829
|
};
|
797
830
|
}
|
798
831
|
case "url": {
|
799
|
-
return {
|
832
|
+
return {
|
833
|
+
"type": "string",
|
834
|
+
"format": JSONSchemaFormat.URI,
|
835
|
+
"x-native-type": JsonSchemaXNativeType.Url
|
836
|
+
};
|
800
837
|
}
|
801
838
|
}
|
802
839
|
}
|
package/dist/zod4/index.d.mts
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.unnoq.com/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.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.unnoq.com/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);
|
429
450
|
if (!itemRequired) {
|
430
451
|
required = false;
|
431
452
|
}
|
@@ -446,7 +467,7 @@ class experimental_ZodToJsonSchemaConverter {
|
|
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);
|
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,40 @@ 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(options2.strategy === "input" ? pipe._zod.def.in : pipe._zod.def.out, options2, lazyDepth2, structureDepth);
|
570
595
|
}
|
571
596
|
case "readonly": {
|
572
597
|
const readonly_ = schema2;
|
573
|
-
const [required, json] =
|
598
|
+
const [required, json] = this.#convert(readonly_._zod.def.innerType, options2, lazyDepth2, structureDepth);
|
574
599
|
return [required, { ...json, readOnly: true }];
|
575
600
|
}
|
576
601
|
case "template_literal": {
|
@@ -582,15 +607,16 @@ class experimental_ZodToJsonSchemaConverter {
|
|
582
607
|
}
|
583
608
|
case "optional": {
|
584
609
|
const optional = schema2;
|
585
|
-
const [, json] =
|
610
|
+
const [, json] = this.#convert(optional._zod.def.innerType, options2, lazyDepth2, structureDepth);
|
586
611
|
return [false, json];
|
587
612
|
}
|
588
613
|
case "lazy": {
|
589
614
|
const lazy = schema2;
|
590
|
-
|
615
|
+
const currentLazyDepth = lazyDepth2 + 1;
|
616
|
+
if (currentLazyDepth > this.maxLazyDepth) {
|
591
617
|
return [false, this.anyJsonSchema];
|
592
618
|
}
|
593
|
-
return
|
619
|
+
return this.#convert(lazy._zod.def.getter(), options2, currentLazyDepth, structureDepth);
|
594
620
|
}
|
595
621
|
default: {
|
596
622
|
schema2._zod.def.type;
|
@@ -601,25 +627,26 @@ class experimental_ZodToJsonSchemaConverter {
|
|
601
627
|
);
|
602
628
|
}
|
603
629
|
#getCustomJsonSchema(schema, options) {
|
604
|
-
if (options.strategy === "input" &&
|
605
|
-
return
|
630
|
+
if (options.strategy === "input" && JSON_SCHEMA_INPUT_REGISTRY.has(schema)) {
|
631
|
+
return JSON_SCHEMA_INPUT_REGISTRY.get(schema);
|
606
632
|
}
|
607
|
-
if (options.strategy === "output" &&
|
608
|
-
return
|
633
|
+
if (options.strategy === "output" && JSON_SCHEMA_OUTPUT_REGISTRY.has(schema)) {
|
634
|
+
return JSON_SCHEMA_OUTPUT_REGISTRY.get(schema);
|
609
635
|
}
|
610
|
-
if (
|
611
|
-
return
|
636
|
+
if (JSON_SCHEMA_REGISTRY.has(schema)) {
|
637
|
+
return JSON_SCHEMA_REGISTRY.get(schema);
|
612
638
|
}
|
613
639
|
const global = globalRegistry.get(schema);
|
614
640
|
if (global) {
|
615
641
|
return {
|
642
|
+
title: global.title,
|
616
643
|
description: global.description,
|
617
|
-
examples: global.examples
|
644
|
+
examples: Array.isArray(global.examples) ? global.examples : void 0
|
618
645
|
};
|
619
646
|
}
|
620
647
|
}
|
621
648
|
#handleArrayItemJsonSchema([required, schema], options) {
|
622
|
-
if (required || options.strategy === "input") {
|
649
|
+
if (required || options.strategy === "input" || schema.default !== void 0) {
|
623
650
|
return schema;
|
624
651
|
}
|
625
652
|
if (schema === this.undefinedJsonSchema) {
|
@@ -650,4 +677,4 @@ class experimental_ZodToJsonSchemaConverter {
|
|
650
677
|
}
|
651
678
|
}
|
652
679
|
|
653
|
-
export {
|
680
|
+
export { JSON_SCHEMA_INPUT_REGISTRY, JSON_SCHEMA_OUTPUT_REGISTRY, JSON_SCHEMA_REGISTRY, ZodToJsonSchemaConverter, experimental_ZodSmartCoercionPlugin };
|
package/package.json
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
{
|
2
2
|
"name": "@orpc/zod",
|
3
3
|
"type": "module",
|
4
|
-
"version": "0.0.0-next.
|
4
|
+
"version": "0.0.0-next.caeb672",
|
5
5
|
"license": "MIT",
|
6
6
|
"homepage": "https://orpc.unnoq.com",
|
7
7
|
"repository": {
|
@@ -29,31 +29,19 @@
|
|
29
29
|
"dist"
|
30
30
|
],
|
31
31
|
"peerDependencies": {
|
32
|
-
"
|
33
|
-
"
|
34
|
-
"@orpc/server": "0.0.0-next.
|
35
|
-
"@orpc/contract": "0.0.0-next.cac5dd3"
|
36
|
-
},
|
37
|
-
"peerDependenciesMeta": {
|
38
|
-
"@zod/core": {
|
39
|
-
"optional": true
|
40
|
-
},
|
41
|
-
"zod": {
|
42
|
-
"optional": true
|
43
|
-
}
|
32
|
+
"zod": ">=3.25.0",
|
33
|
+
"@orpc/contract": "0.0.0-next.caeb672",
|
34
|
+
"@orpc/server": "0.0.0-next.caeb672"
|
44
35
|
},
|
45
36
|
"dependencies": {
|
46
37
|
"escape-string-regexp": "^5.0.0",
|
47
38
|
"wildcard-match": "^5.1.3",
|
48
|
-
"@orpc/
|
49
|
-
"@orpc/
|
39
|
+
"@orpc/json-schema": "0.0.0-next.caeb672",
|
40
|
+
"@orpc/shared": "0.0.0-next.caeb672",
|
41
|
+
"@orpc/openapi": "0.0.0-next.caeb672"
|
50
42
|
},
|
51
43
|
"devDependencies": {
|
52
|
-
"
|
53
|
-
"@zod/mini": "^4.0.0-beta.20250505T012514",
|
54
|
-
"zod": "^3.24.2",
|
55
|
-
"zod-to-json-schema": "^3.24.5",
|
56
|
-
"zod4": "npm:zod@^4.0.0-beta.20250505T012514"
|
44
|
+
"zod": "^4.0.5"
|
57
45
|
},
|
58
46
|
"scripts": {
|
59
47
|
"build": "unbuild",
|