@orpc/zod 0.0.0-next.d5f6b77 → 0.0.0-next.d636350
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 +5 -6
- package/dist/index.d.mts +15 -6
- package/dist/index.d.ts +15 -6
- package/dist/index.mjs +44 -27
- package/dist/zod4/index.d.mts +22 -13
- package/dist/zod4/index.d.ts +22 -13
- package/dist/zod4/index.mjs +110 -95
- package/package.json +7 -19
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,13 +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/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/).
|
52
54
|
- [@orpc/react](https://www.npmjs.com/package/@orpc/react): Utilities for integrating oRPC with React and React Server Actions.
|
53
|
-
- [@orpc/
|
54
|
-
- [@orpc/vue-query](https://www.npmjs.com/package/@orpc/vue-query): Integration with [Vue Query](https://tanstack.com/query/latest/docs/framework/vue/overview).
|
55
|
-
- [@orpc/solid-query](https://www.npmjs.com/package/@orpc/solid-query): Integration with [Solid Query](https://tanstack.com/query/latest/docs/framework/solid/overview).
|
56
|
-
- [@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.
|
57
56
|
- [@orpc/vue-colada](https://www.npmjs.com/package/@orpc/vue-colada): Integration with [Pinia Colada](https://pinia-colada.esm.dev/).
|
58
|
-
- [@orpc/
|
57
|
+
- [@orpc/hey-api](https://www.npmjs.com/package/@orpc/hey-api): [Hey API](https://heyapi.dev/) integration.
|
59
58
|
- [@orpc/zod](https://www.npmjs.com/package/@orpc/zod): More schemas that [Zod](https://zod.dev/) doesn't support yet.
|
60
59
|
- [@orpc/valibot](https://www.npmjs.com/package/@orpc/valibot): OpenAPI spec generation from [Valibot](https://valibot.dev/).
|
61
60
|
- [@orpc/arktype](https://www.npmjs.com/package/@orpc/arktype): OpenAPI spec generation from [ArkType](https://arktype.io/).
|
package/dist/index.d.mts
CHANGED
@@ -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
@@ -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,6 @@
|
|
1
1
|
import { custom, ZodFirstPartyTypeKind } from 'zod';
|
2
2
|
import wcmatch from 'wildcard-match';
|
3
|
-
import { isObject, guard } from '@orpc/shared';
|
3
|
+
import { isObject, guard, toArray } from '@orpc/shared';
|
4
4
|
import { JSONSchemaFormat } from '@orpc/openapi';
|
5
5
|
import escapeStringRegexp from 'escape-string-regexp';
|
6
6
|
|
@@ -390,25 +390,39 @@ function safeToDate(value) {
|
|
390
390
|
|
391
391
|
class ZodToJsonSchemaConverter {
|
392
392
|
maxLazyDepth;
|
393
|
+
maxStructureDepth;
|
393
394
|
unsupportedJsonSchema;
|
394
395
|
anyJsonSchema;
|
395
396
|
constructor(options = {}) {
|
396
397
|
this.maxLazyDepth = options.maxLazyDepth ?? 3;
|
398
|
+
this.maxStructureDepth = options.maxStructureDepth ?? 10;
|
397
399
|
this.unsupportedJsonSchema = options.unsupportedJsonSchema ?? { not: {} };
|
398
400
|
this.anyJsonSchema = options.anyJsonSchema ?? {};
|
399
401
|
}
|
400
402
|
condition(schema) {
|
401
403
|
return schema !== void 0 && schema["~standard"].vendor === "zod";
|
402
404
|
}
|
403
|
-
convert(schema, options, lazyDepth = 0, isHandledCustomJSONSchema = false, isHandledZodDescription = false) {
|
405
|
+
convert(schema, options, lazyDepth = 0, isHandledCustomJSONSchema = false, isHandledZodDescription = false, structureDepth = 0) {
|
404
406
|
const def = schema._def;
|
407
|
+
if (structureDepth > this.maxStructureDepth) {
|
408
|
+
return [false, this.anyJsonSchema];
|
409
|
+
}
|
410
|
+
if (!options.minStructureDepthForRef || options.minStructureDepthForRef <= structureDepth) {
|
411
|
+
const components = toArray(options.components);
|
412
|
+
for (const component of components) {
|
413
|
+
if (component.schema === schema && component.allowedStrategies.includes(options.strategy)) {
|
414
|
+
return [component.required, { $ref: component.ref }];
|
415
|
+
}
|
416
|
+
}
|
417
|
+
}
|
405
418
|
if (!isHandledZodDescription && "description" in def && typeof def.description === "string") {
|
406
419
|
const [required, json] = this.convert(
|
407
420
|
schema,
|
408
421
|
options,
|
409
422
|
lazyDepth,
|
410
423
|
isHandledCustomJSONSchema,
|
411
|
-
true
|
424
|
+
true,
|
425
|
+
structureDepth
|
412
426
|
);
|
413
427
|
return [required, { ...json, description: def.description }];
|
414
428
|
}
|
@@ -420,7 +434,8 @@ class ZodToJsonSchemaConverter {
|
|
420
434
|
options,
|
421
435
|
lazyDepth,
|
422
436
|
true,
|
423
|
-
isHandledZodDescription
|
437
|
+
isHandledZodDescription,
|
438
|
+
structureDepth
|
424
439
|
);
|
425
440
|
return [required, { ...json, ...customJSONSchema }];
|
426
441
|
}
|
@@ -591,7 +606,7 @@ class ZodToJsonSchemaConverter {
|
|
591
606
|
const schema_ = schema;
|
592
607
|
const def2 = schema_._def;
|
593
608
|
const json = { type: "array" };
|
594
|
-
const [itemRequired, itemJson] = this.convert(def2.type, options, lazyDepth, false, false);
|
609
|
+
const [itemRequired, itemJson] = this.convert(def2.type, options, lazyDepth, false, false, structureDepth + 1);
|
595
610
|
json.items = this.#toArrayItemJsonSchema(itemRequired, itemJson, options.strategy);
|
596
611
|
if (def2.exactLength) {
|
597
612
|
json.maxItems = def2.exactLength.value;
|
@@ -610,7 +625,7 @@ class ZodToJsonSchemaConverter {
|
|
610
625
|
const prefixItems = [];
|
611
626
|
const json = { type: "array" };
|
612
627
|
for (const item of schema_._def.items) {
|
613
|
-
const [itemRequired, itemJson] = this.convert(item, options, lazyDepth, false, false);
|
628
|
+
const [itemRequired, itemJson] = this.convert(item, options, lazyDepth, false, false, structureDepth + 1);
|
614
629
|
prefixItems.push(
|
615
630
|
this.#toArrayItemJsonSchema(itemRequired, itemJson, options.strategy)
|
616
631
|
);
|
@@ -619,7 +634,7 @@ class ZodToJsonSchemaConverter {
|
|
619
634
|
json.prefixItems = prefixItems;
|
620
635
|
}
|
621
636
|
if (schema_._def.rest) {
|
622
|
-
const [itemRequired, itemJson] = this.convert(schema_._def.rest, options, lazyDepth, false, false);
|
637
|
+
const [itemRequired, itemJson] = this.convert(schema_._def.rest, options, lazyDepth, false, false, structureDepth + 1);
|
623
638
|
json.items = this.#toArrayItemJsonSchema(itemRequired, itemJson, options.strategy);
|
624
639
|
}
|
625
640
|
return [true, json];
|
@@ -630,7 +645,7 @@ class ZodToJsonSchemaConverter {
|
|
630
645
|
const properties = {};
|
631
646
|
const required = [];
|
632
647
|
for (const [key, value] of Object.entries(schema_.shape)) {
|
633
|
-
const [itemRequired, itemJson] = this.convert(value, options, lazyDepth, false, false);
|
648
|
+
const [itemRequired, itemJson] = this.convert(value, options, lazyDepth, false, false, structureDepth + 1);
|
634
649
|
properties[key] = itemJson;
|
635
650
|
if (itemRequired) {
|
636
651
|
required.push(key);
|
@@ -648,7 +663,7 @@ class ZodToJsonSchemaConverter {
|
|
648
663
|
json.additionalProperties = false;
|
649
664
|
}
|
650
665
|
} else {
|
651
|
-
const [_, addJson] = this.convert(schema_._def.catchall, options, lazyDepth, false, false);
|
666
|
+
const [_, addJson] = this.convert(schema_._def.catchall, options, lazyDepth, false, false, structureDepth + 1);
|
652
667
|
json.additionalProperties = addJson;
|
653
668
|
}
|
654
669
|
return [true, json];
|
@@ -656,25 +671,25 @@ class ZodToJsonSchemaConverter {
|
|
656
671
|
case ZodFirstPartyTypeKind.ZodRecord: {
|
657
672
|
const schema_ = schema;
|
658
673
|
const json = { type: "object" };
|
659
|
-
const [__, keyJson] = this.convert(schema_._def.keyType, options, lazyDepth, false, false);
|
674
|
+
const [__, keyJson] = this.convert(schema_._def.keyType, options, lazyDepth, false, false, structureDepth + 1);
|
660
675
|
if (Object.entries(keyJson).some(([k, v]) => k !== "type" || v !== "string")) {
|
661
676
|
json.propertyNames = keyJson;
|
662
677
|
}
|
663
|
-
const [_, itemJson] = this.convert(schema_._def.valueType, options, lazyDepth, false, false);
|
678
|
+
const [_, itemJson] = this.convert(schema_._def.valueType, options, lazyDepth, false, false, structureDepth + 1);
|
664
679
|
json.additionalProperties = itemJson;
|
665
680
|
return [true, json];
|
666
681
|
}
|
667
682
|
case ZodFirstPartyTypeKind.ZodSet: {
|
668
683
|
const schema_ = schema;
|
669
684
|
const json = { type: "array", uniqueItems: true };
|
670
|
-
const [itemRequired, itemJson] = this.convert(schema_._def.valueType, options, lazyDepth, false, false);
|
685
|
+
const [itemRequired, itemJson] = this.convert(schema_._def.valueType, options, lazyDepth, false, false, structureDepth + 1);
|
671
686
|
json.items = this.#toArrayItemJsonSchema(itemRequired, itemJson, options.strategy);
|
672
687
|
return [true, json];
|
673
688
|
}
|
674
689
|
case ZodFirstPartyTypeKind.ZodMap: {
|
675
690
|
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);
|
691
|
+
const [keyRequired, keyJson] = this.convert(schema_._def.keyType, options, lazyDepth, false, false, structureDepth + 1);
|
692
|
+
const [valueRequired, valueJson] = this.convert(schema_._def.valueType, options, lazyDepth, false, false, structureDepth + 1);
|
678
693
|
return [true, {
|
679
694
|
type: "array",
|
680
695
|
items: {
|
@@ -694,7 +709,7 @@ class ZodToJsonSchemaConverter {
|
|
694
709
|
const anyOf = [];
|
695
710
|
let required = true;
|
696
711
|
for (const item of schema_._def.options) {
|
697
|
-
const [itemRequired, itemJson] = this.convert(item, options, lazyDepth, false, false);
|
712
|
+
const [itemRequired, itemJson] = this.convert(item, options, lazyDepth, false, false, structureDepth);
|
698
713
|
if (!itemRequired) {
|
699
714
|
required = false;
|
700
715
|
if (itemJson !== this.unsupportedJsonSchema) {
|
@@ -714,7 +729,7 @@ class ZodToJsonSchemaConverter {
|
|
714
729
|
const allOf = [];
|
715
730
|
let required = false;
|
716
731
|
for (const item of [schema_._def.left, schema_._def.right]) {
|
717
|
-
const [itemRequired, itemJson] = this.convert(item, options, lazyDepth, false, false);
|
732
|
+
const [itemRequired, itemJson] = this.convert(item, options, lazyDepth, false, false, structureDepth);
|
718
733
|
allOf.push(itemJson);
|
719
734
|
if (itemRequired) {
|
720
735
|
required = true;
|
@@ -723,25 +738,26 @@ class ZodToJsonSchemaConverter {
|
|
723
738
|
return [required, { allOf }];
|
724
739
|
}
|
725
740
|
case ZodFirstPartyTypeKind.ZodLazy: {
|
726
|
-
|
741
|
+
const currentLazyDepth = lazyDepth + 1;
|
742
|
+
if (currentLazyDepth > this.maxLazyDepth) {
|
727
743
|
return [false, this.anyJsonSchema];
|
728
744
|
}
|
729
745
|
const schema_ = schema;
|
730
|
-
return this.convert(schema_._def.getter(), options,
|
746
|
+
return this.convert(schema_._def.getter(), options, currentLazyDepth, false, false, structureDepth);
|
731
747
|
}
|
732
748
|
case ZodFirstPartyTypeKind.ZodOptional: {
|
733
749
|
const schema_ = schema;
|
734
|
-
const [_, inner] = this.convert(schema_._def.innerType, options, lazyDepth, false, false);
|
750
|
+
const [_, inner] = this.convert(schema_._def.innerType, options, lazyDepth, false, false, structureDepth);
|
735
751
|
return [false, inner];
|
736
752
|
}
|
737
753
|
case ZodFirstPartyTypeKind.ZodReadonly: {
|
738
754
|
const schema_ = schema;
|
739
|
-
const [required, json] = this.convert(schema_._def.innerType, options, lazyDepth, false, false);
|
755
|
+
const [required, json] = this.convert(schema_._def.innerType, options, lazyDepth, false, false, structureDepth);
|
740
756
|
return [required, { ...json, readOnly: true }];
|
741
757
|
}
|
742
758
|
case ZodFirstPartyTypeKind.ZodDefault: {
|
743
759
|
const schema_ = schema;
|
744
|
-
const [_, json] = this.convert(schema_._def.innerType, options, lazyDepth, false, false);
|
760
|
+
const [_, json] = this.convert(schema_._def.innerType, options, lazyDepth, false, false, structureDepth);
|
745
761
|
return [false, { default: schema_._def.defaultValue(), ...json }];
|
746
762
|
}
|
747
763
|
case ZodFirstPartyTypeKind.ZodEffects: {
|
@@ -749,15 +765,15 @@ class ZodToJsonSchemaConverter {
|
|
749
765
|
if (schema_._def.effect.type === "transform" && options.strategy === "output") {
|
750
766
|
return [false, this.anyJsonSchema];
|
751
767
|
}
|
752
|
-
return this.convert(schema_._def.schema, options, lazyDepth, false, false);
|
768
|
+
return this.convert(schema_._def.schema, options, lazyDepth, false, false, structureDepth);
|
753
769
|
}
|
754
770
|
case ZodFirstPartyTypeKind.ZodCatch: {
|
755
771
|
const schema_ = schema;
|
756
|
-
return this.convert(schema_._def.innerType, options, lazyDepth, false, false);
|
772
|
+
return this.convert(schema_._def.innerType, options, lazyDepth, false, false, structureDepth);
|
757
773
|
}
|
758
774
|
case ZodFirstPartyTypeKind.ZodBranded: {
|
759
775
|
const schema_ = schema;
|
760
|
-
return this.convert(schema_._def.type, options, lazyDepth, false, false);
|
776
|
+
return this.convert(schema_._def.type, options, lazyDepth, false, false, structureDepth);
|
761
777
|
}
|
762
778
|
case ZodFirstPartyTypeKind.ZodPipeline: {
|
763
779
|
const schema_ = schema;
|
@@ -766,13 +782,14 @@ class ZodToJsonSchemaConverter {
|
|
766
782
|
options,
|
767
783
|
lazyDepth,
|
768
784
|
false,
|
769
|
-
false
|
785
|
+
false,
|
786
|
+
structureDepth
|
770
787
|
);
|
771
788
|
}
|
772
789
|
case ZodFirstPartyTypeKind.ZodNullable: {
|
773
790
|
const schema_ = schema;
|
774
|
-
const [required, json] = this.convert(schema_._def.innerType, options, lazyDepth, false, false);
|
775
|
-
return [required, { anyOf: [{ type: "null" }
|
791
|
+
const [required, json] = this.convert(schema_._def.innerType, options, lazyDepth, false, false, structureDepth);
|
792
|
+
return [required, { anyOf: [json, { type: "null" }] }];
|
776
793
|
}
|
777
794
|
}
|
778
795
|
return [true, this.unsupportedJsonSchema];
|
package/dist/zod4/index.d.mts
CHANGED
@@ -2,9 +2,9 @@ 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
9
|
declare class experimental_ZodSmartCoercionPlugin<TContext extends Context> implements StandardHandlerPlugin<TContext> {
|
10
10
|
#private;
|
@@ -13,13 +13,21 @@ declare class experimental_ZodSmartCoercionPlugin<TContext extends Context> impl
|
|
13
13
|
|
14
14
|
interface experimental_ZodToJsonSchemaOptions {
|
15
15
|
/**
|
16
|
-
* Max depth of lazy type
|
16
|
+
* Max depth of lazy type.
|
17
17
|
*
|
18
|
-
* Used anyJsonSchema (`{}`) when
|
18
|
+
* Used anyJsonSchema (`{}`) when exceed max depth
|
19
19
|
*
|
20
20
|
* @default 2
|
21
21
|
*/
|
22
22
|
maxLazyDepth?: number;
|
23
|
+
/**
|
24
|
+
* Max depth of nested types.
|
25
|
+
*
|
26
|
+
* Used anyJsonSchema (`{}`) when exceed max depth
|
27
|
+
*
|
28
|
+
* @default 10
|
29
|
+
*/
|
30
|
+
maxStructureDepth?: number;
|
23
31
|
/**
|
24
32
|
* The schema to be used to represent the any | unknown type.
|
25
33
|
*
|
@@ -46,18 +54,19 @@ interface experimental_ZodToJsonSchemaOptions {
|
|
46
54
|
}, [
|
47
55
|
required: boolean,
|
48
56
|
jsonSchema: Exclude<JSONSchema, boolean>
|
49
|
-
]
|
57
|
+
]>[];
|
50
58
|
}
|
51
59
|
declare class experimental_ZodToJsonSchemaConverter implements ConditionalSchemaConverter {
|
52
60
|
#private;
|
53
61
|
private readonly maxLazyDepth;
|
62
|
+
private readonly maxStructureDepth;
|
54
63
|
private readonly anyJsonSchema;
|
55
64
|
private readonly unsupportedJsonSchema;
|
56
65
|
private readonly undefinedJsonSchema;
|
57
66
|
private readonly interceptors;
|
58
67
|
constructor(options?: experimental_ZodToJsonSchemaOptions);
|
59
68
|
condition(schema: AnySchema | undefined): boolean;
|
60
|
-
convert(schema: AnySchema | undefined, options: SchemaConvertOptions):
|
69
|
+
convert(schema: AnySchema | undefined, options: SchemaConvertOptions): [required: boolean, jsonSchema: Exclude<JSONSchema, boolean>];
|
61
70
|
}
|
62
71
|
|
63
72
|
/**
|
@@ -77,7 +86,7 @@ declare class experimental_ZodToJsonSchemaConverter implements ConditionalSchema
|
|
77
86
|
* })
|
78
87
|
* ```
|
79
88
|
*/
|
80
|
-
declare const experimental_JSON_SCHEMA_REGISTRY:
|
89
|
+
declare const experimental_JSON_SCHEMA_REGISTRY: zod_v4_core.$ZodRegistry<{
|
81
90
|
$anchor?: string;
|
82
91
|
$comment?: string;
|
83
92
|
$defs?: Record<string, JSONSchema>;
|
@@ -138,7 +147,7 @@ declare const experimental_JSON_SCHEMA_REGISTRY: _zod_core.$ZodRegistry<{
|
|
138
147
|
unevaluatedProperties?: JSONSchema;
|
139
148
|
uniqueItems?: boolean;
|
140
149
|
writeOnly?: boolean;
|
141
|
-
},
|
150
|
+
}, zod_v4_core.$ZodType<unknown, unknown, zod_v4_core.$ZodTypeInternals<unknown, unknown>>>;
|
142
151
|
/**
|
143
152
|
* Zod registry for customizing generated JSON schema, only useful for .input
|
144
153
|
*
|
@@ -156,7 +165,7 @@ declare const experimental_JSON_SCHEMA_REGISTRY: _zod_core.$ZodRegistry<{
|
|
156
165
|
* })
|
157
166
|
* ```
|
158
167
|
*/
|
159
|
-
declare const experimental_JSON_SCHEMA_INPUT_REGISTRY:
|
168
|
+
declare const experimental_JSON_SCHEMA_INPUT_REGISTRY: zod_v4_core.$ZodRegistry<{
|
160
169
|
$anchor?: string;
|
161
170
|
$comment?: string;
|
162
171
|
$defs?: Record<string, JSONSchema>;
|
@@ -217,7 +226,7 @@ declare const experimental_JSON_SCHEMA_INPUT_REGISTRY: _zod_core.$ZodRegistry<{
|
|
217
226
|
unevaluatedProperties?: JSONSchema;
|
218
227
|
uniqueItems?: boolean;
|
219
228
|
writeOnly?: boolean;
|
220
|
-
},
|
229
|
+
}, zod_v4_core.$ZodType<unknown, unknown, zod_v4_core.$ZodTypeInternals<unknown, unknown>>>;
|
221
230
|
/**
|
222
231
|
* Zod registry for customizing generated JSON schema, only useful for .input
|
223
232
|
*
|
@@ -235,7 +244,7 @@ declare const experimental_JSON_SCHEMA_INPUT_REGISTRY: _zod_core.$ZodRegistry<{
|
|
235
244
|
* })
|
236
245
|
* ```
|
237
246
|
*/
|
238
|
-
declare const experimental_JSON_SCHEMA_OUTPUT_REGISTRY:
|
247
|
+
declare const experimental_JSON_SCHEMA_OUTPUT_REGISTRY: zod_v4_core.$ZodRegistry<{
|
239
248
|
$anchor?: string;
|
240
249
|
$comment?: string;
|
241
250
|
$defs?: Record<string, JSONSchema>;
|
@@ -296,7 +305,7 @@ declare const experimental_JSON_SCHEMA_OUTPUT_REGISTRY: _zod_core.$ZodRegistry<{
|
|
296
305
|
unevaluatedProperties?: JSONSchema;
|
297
306
|
uniqueItems?: boolean;
|
298
307
|
writeOnly?: boolean;
|
299
|
-
},
|
308
|
+
}, zod_v4_core.$ZodType<unknown, unknown, zod_v4_core.$ZodTypeInternals<unknown, unknown>>>;
|
300
309
|
|
301
310
|
export { experimental_JSON_SCHEMA_INPUT_REGISTRY, experimental_JSON_SCHEMA_OUTPUT_REGISTRY, experimental_JSON_SCHEMA_REGISTRY, experimental_ZodSmartCoercionPlugin, experimental_ZodToJsonSchemaConverter };
|
302
311
|
export type { experimental_ZodToJsonSchemaOptions };
|
package/dist/zod4/index.d.ts
CHANGED
@@ -2,9 +2,9 @@ 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
9
|
declare class experimental_ZodSmartCoercionPlugin<TContext extends Context> implements StandardHandlerPlugin<TContext> {
|
10
10
|
#private;
|
@@ -13,13 +13,21 @@ declare class experimental_ZodSmartCoercionPlugin<TContext extends Context> impl
|
|
13
13
|
|
14
14
|
interface experimental_ZodToJsonSchemaOptions {
|
15
15
|
/**
|
16
|
-
* Max depth of lazy type
|
16
|
+
* Max depth of lazy type.
|
17
17
|
*
|
18
|
-
* Used anyJsonSchema (`{}`) when
|
18
|
+
* Used anyJsonSchema (`{}`) when exceed max depth
|
19
19
|
*
|
20
20
|
* @default 2
|
21
21
|
*/
|
22
22
|
maxLazyDepth?: number;
|
23
|
+
/**
|
24
|
+
* Max depth of nested types.
|
25
|
+
*
|
26
|
+
* Used anyJsonSchema (`{}`) when exceed max depth
|
27
|
+
*
|
28
|
+
* @default 10
|
29
|
+
*/
|
30
|
+
maxStructureDepth?: number;
|
23
31
|
/**
|
24
32
|
* The schema to be used to represent the any | unknown type.
|
25
33
|
*
|
@@ -46,18 +54,19 @@ interface experimental_ZodToJsonSchemaOptions {
|
|
46
54
|
}, [
|
47
55
|
required: boolean,
|
48
56
|
jsonSchema: Exclude<JSONSchema, boolean>
|
49
|
-
]
|
57
|
+
]>[];
|
50
58
|
}
|
51
59
|
declare class experimental_ZodToJsonSchemaConverter implements ConditionalSchemaConverter {
|
52
60
|
#private;
|
53
61
|
private readonly maxLazyDepth;
|
62
|
+
private readonly maxStructureDepth;
|
54
63
|
private readonly anyJsonSchema;
|
55
64
|
private readonly unsupportedJsonSchema;
|
56
65
|
private readonly undefinedJsonSchema;
|
57
66
|
private readonly interceptors;
|
58
67
|
constructor(options?: experimental_ZodToJsonSchemaOptions);
|
59
68
|
condition(schema: AnySchema | undefined): boolean;
|
60
|
-
convert(schema: AnySchema | undefined, options: SchemaConvertOptions):
|
69
|
+
convert(schema: AnySchema | undefined, options: SchemaConvertOptions): [required: boolean, jsonSchema: Exclude<JSONSchema, boolean>];
|
61
70
|
}
|
62
71
|
|
63
72
|
/**
|
@@ -77,7 +86,7 @@ declare class experimental_ZodToJsonSchemaConverter implements ConditionalSchema
|
|
77
86
|
* })
|
78
87
|
* ```
|
79
88
|
*/
|
80
|
-
declare const experimental_JSON_SCHEMA_REGISTRY:
|
89
|
+
declare const experimental_JSON_SCHEMA_REGISTRY: zod_v4_core.$ZodRegistry<{
|
81
90
|
$anchor?: string;
|
82
91
|
$comment?: string;
|
83
92
|
$defs?: Record<string, JSONSchema>;
|
@@ -138,7 +147,7 @@ declare const experimental_JSON_SCHEMA_REGISTRY: _zod_core.$ZodRegistry<{
|
|
138
147
|
unevaluatedProperties?: JSONSchema;
|
139
148
|
uniqueItems?: boolean;
|
140
149
|
writeOnly?: boolean;
|
141
|
-
},
|
150
|
+
}, zod_v4_core.$ZodType<unknown, unknown, zod_v4_core.$ZodTypeInternals<unknown, unknown>>>;
|
142
151
|
/**
|
143
152
|
* Zod registry for customizing generated JSON schema, only useful for .input
|
144
153
|
*
|
@@ -156,7 +165,7 @@ declare const experimental_JSON_SCHEMA_REGISTRY: _zod_core.$ZodRegistry<{
|
|
156
165
|
* })
|
157
166
|
* ```
|
158
167
|
*/
|
159
|
-
declare const experimental_JSON_SCHEMA_INPUT_REGISTRY:
|
168
|
+
declare const experimental_JSON_SCHEMA_INPUT_REGISTRY: zod_v4_core.$ZodRegistry<{
|
160
169
|
$anchor?: string;
|
161
170
|
$comment?: string;
|
162
171
|
$defs?: Record<string, JSONSchema>;
|
@@ -217,7 +226,7 @@ declare const experimental_JSON_SCHEMA_INPUT_REGISTRY: _zod_core.$ZodRegistry<{
|
|
217
226
|
unevaluatedProperties?: JSONSchema;
|
218
227
|
uniqueItems?: boolean;
|
219
228
|
writeOnly?: boolean;
|
220
|
-
},
|
229
|
+
}, zod_v4_core.$ZodType<unknown, unknown, zod_v4_core.$ZodTypeInternals<unknown, unknown>>>;
|
221
230
|
/**
|
222
231
|
* Zod registry for customizing generated JSON schema, only useful for .input
|
223
232
|
*
|
@@ -235,7 +244,7 @@ declare const experimental_JSON_SCHEMA_INPUT_REGISTRY: _zod_core.$ZodRegistry<{
|
|
235
244
|
* })
|
236
245
|
* ```
|
237
246
|
*/
|
238
|
-
declare const experimental_JSON_SCHEMA_OUTPUT_REGISTRY:
|
247
|
+
declare const experimental_JSON_SCHEMA_OUTPUT_REGISTRY: zod_v4_core.$ZodRegistry<{
|
239
248
|
$anchor?: string;
|
240
249
|
$comment?: string;
|
241
250
|
$defs?: Record<string, JSONSchema>;
|
@@ -296,7 +305,7 @@ declare const experimental_JSON_SCHEMA_OUTPUT_REGISTRY: _zod_core.$ZodRegistry<{
|
|
296
305
|
unevaluatedProperties?: JSONSchema;
|
297
306
|
uniqueItems?: boolean;
|
298
307
|
writeOnly?: boolean;
|
299
|
-
},
|
308
|
+
}, zod_v4_core.$ZodType<unknown, unknown, zod_v4_core.$ZodTypeInternals<unknown, unknown>>>;
|
300
309
|
|
301
310
|
export { experimental_JSON_SCHEMA_INPUT_REGISTRY, experimental_JSON_SCHEMA_OUTPUT_REGISTRY, experimental_JSON_SCHEMA_REGISTRY, experimental_ZodSmartCoercionPlugin, experimental_ZodToJsonSchemaConverter };
|
302
311
|
export type { experimental_ZodToJsonSchemaOptions };
|
package/dist/zod4/index.mjs
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
import { isObject, guard, intercept } from '@orpc/shared';
|
1
|
+
import { isObject, guard, intercept, toArray } from '@orpc/shared';
|
2
2
|
import { JSONSchemaFormat, JSONSchemaContentEncoding } from '@orpc/openapi';
|
3
|
-
import { registry, globalRegistry } from '
|
3
|
+
import { registry, globalRegistry } from 'zod/v4/core';
|
4
4
|
|
5
5
|
class experimental_ZodSmartCoercionPlugin {
|
6
6
|
init(options) {
|
@@ -100,8 +100,7 @@ class experimental_ZodSmartCoercionPlugin {
|
|
100
100
|
}
|
101
101
|
return value;
|
102
102
|
}
|
103
|
-
case "object":
|
104
|
-
case "interface": {
|
103
|
+
case "object": {
|
105
104
|
const object = schema;
|
106
105
|
if (value === void 0) {
|
107
106
|
return {};
|
@@ -165,9 +164,21 @@ class experimental_ZodSmartCoercionPlugin {
|
|
165
164
|
return this.#coerce(union._zod.def.options[0], value);
|
166
165
|
}
|
167
166
|
if (isObject(value)) {
|
167
|
+
const discriminator = "discriminator" in union._zod.def && typeof union._zod.def.discriminator === "string" ? union._zod.def.discriminator : void 0;
|
168
168
|
for (const option of union._zod.def.options) {
|
169
|
-
if (option._zod.
|
170
|
-
|
169
|
+
if (!option._zod.propValues) {
|
170
|
+
continue;
|
171
|
+
}
|
172
|
+
if (discriminator !== void 0) {
|
173
|
+
if (option._zod.propValues[discriminator]?.has(value[discriminator])) {
|
174
|
+
return this.#coerce(option, value);
|
175
|
+
}
|
176
|
+
} else {
|
177
|
+
for (const key in option._zod.propValues) {
|
178
|
+
if (option._zod.propValues[key]?.has(value[key])) {
|
179
|
+
return this.#coerce(option, value);
|
180
|
+
}
|
181
|
+
}
|
171
182
|
}
|
172
183
|
}
|
173
184
|
}
|
@@ -207,10 +218,17 @@ class experimental_ZodSmartCoercionPlugin {
|
|
207
218
|
return this.#coerce(pipe._zod.def.in, value);
|
208
219
|
}
|
209
220
|
case "default":
|
210
|
-
case "
|
221
|
+
case "prefault": {
|
211
222
|
const default_ = schema;
|
223
|
+
if (value === void 0) {
|
224
|
+
return value;
|
225
|
+
}
|
212
226
|
return this.#coerce(default_._zod.def.innerType, value);
|
213
227
|
}
|
228
|
+
case "catch": {
|
229
|
+
const catch_ = schema;
|
230
|
+
return this.#coerce(catch_._zod.def.innerType, value);
|
231
|
+
}
|
214
232
|
case "lazy": {
|
215
233
|
const lazy = schema;
|
216
234
|
if (value !== void 0) {
|
@@ -248,30 +266,6 @@ class experimental_ZodSmartCoercionPlugin {
|
|
248
266
|
}
|
249
267
|
return value;
|
250
268
|
}
|
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
269
|
}
|
276
270
|
|
277
271
|
const experimental_JSON_SCHEMA_REGISTRY = registry();
|
@@ -280,12 +274,14 @@ const experimental_JSON_SCHEMA_OUTPUT_REGISTRY = registry();
|
|
280
274
|
|
281
275
|
class experimental_ZodToJsonSchemaConverter {
|
282
276
|
maxLazyDepth;
|
277
|
+
maxStructureDepth;
|
283
278
|
anyJsonSchema;
|
284
279
|
unsupportedJsonSchema;
|
285
280
|
undefinedJsonSchema;
|
286
281
|
interceptors;
|
287
282
|
constructor(options = {}) {
|
288
283
|
this.maxLazyDepth = options.maxLazyDepth ?? 2;
|
284
|
+
this.maxStructureDepth = options.maxStructureDepth ?? 10;
|
289
285
|
this.anyJsonSchema = options.anyJsonSchema ?? {};
|
290
286
|
this.unsupportedJsonSchema = options.unsupportedJsonSchema ?? { not: {} };
|
291
287
|
this.undefinedJsonSchema = options.undefinedJsonSchema ?? { not: {} };
|
@@ -295,17 +291,28 @@ class experimental_ZodToJsonSchemaConverter {
|
|
295
291
|
return schema !== void 0 && schema["~standard"].vendor === "zod";
|
296
292
|
}
|
297
293
|
convert(schema, options) {
|
298
|
-
return this.#convert(schema, options, 0);
|
294
|
+
return this.#convert(schema, options, 0, 0);
|
299
295
|
}
|
300
|
-
#convert(schema, options, lazyDepth, isHandledCustomJSONSchema = false) {
|
296
|
+
#convert(schema, options, lazyDepth, structureDepth, isHandledCustomJSONSchema = false) {
|
301
297
|
return intercept(
|
302
298
|
this.interceptors,
|
303
299
|
{ schema, options, lazyDepth, isHandledCustomJSONSchema },
|
304
|
-
|
300
|
+
({ schema: schema2, options: options2, lazyDepth: lazyDepth2, isHandledCustomJSONSchema: isHandledCustomJSONSchema2 }) => {
|
301
|
+
if (structureDepth > this.maxStructureDepth) {
|
302
|
+
return [false, this.anyJsonSchema];
|
303
|
+
}
|
304
|
+
if (!options2.minStructureDepthForRef || options2.minStructureDepthForRef <= structureDepth) {
|
305
|
+
const components = toArray(options2.components);
|
306
|
+
for (const component of components) {
|
307
|
+
if (component.schema === schema2 && component.allowedStrategies.includes(options2.strategy)) {
|
308
|
+
return [component.required, { $ref: component.ref }];
|
309
|
+
}
|
310
|
+
}
|
311
|
+
}
|
305
312
|
if (!isHandledCustomJSONSchema2) {
|
306
313
|
const customJSONSchema = this.#getCustomJsonSchema(schema2, options2);
|
307
314
|
if (customJSONSchema) {
|
308
|
-
const [required, json] =
|
315
|
+
const [required, json] = this.#convert(schema2, options2, lazyDepth2, structureDepth, true);
|
309
316
|
return [required, { ...json, ...customJSONSchema }];
|
310
317
|
}
|
311
318
|
}
|
@@ -313,21 +320,28 @@ class experimental_ZodToJsonSchemaConverter {
|
|
313
320
|
case "string": {
|
314
321
|
const string = schema2;
|
315
322
|
const json = { type: "string" };
|
316
|
-
const { minimum, maximum, format,
|
317
|
-
if (minimum
|
323
|
+
const { minimum, maximum, format, patterns, contentEncoding } = string._zod.bag;
|
324
|
+
if (typeof minimum === "number") {
|
318
325
|
json.minLength = minimum;
|
319
326
|
}
|
320
|
-
if (maximum
|
327
|
+
if (typeof maximum === "number") {
|
321
328
|
json.maxLength = maximum;
|
322
329
|
}
|
323
|
-
if (contentEncoding
|
330
|
+
if (typeof contentEncoding === "string") {
|
324
331
|
json.contentEncoding = this.#handleContentEncoding(contentEncoding);
|
325
332
|
}
|
326
|
-
if (format
|
333
|
+
if (typeof format === "string" && format !== "regex" && json.contentEncoding === void 0) {
|
327
334
|
json.format = this.#handleStringFormat(format);
|
328
335
|
}
|
329
|
-
if (
|
330
|
-
|
336
|
+
if (patterns instanceof Set && json.contentEncoding === void 0 && json.format === void 0) {
|
337
|
+
for (const pattern of patterns) {
|
338
|
+
if (json.pattern === void 0) {
|
339
|
+
json.pattern = pattern.source;
|
340
|
+
} else {
|
341
|
+
json.allOf ??= [];
|
342
|
+
json.allOf.push({ pattern: pattern.source });
|
343
|
+
}
|
344
|
+
}
|
331
345
|
}
|
332
346
|
if (format === "jwt" && json.contentEncoding === void 0 && json.format === void 0 && json.pattern === void 0) {
|
333
347
|
json.pattern = /^[\w-]+\.[\w-]+\.[\w-]+$/.source;
|
@@ -337,25 +351,23 @@ class experimental_ZodToJsonSchemaConverter {
|
|
337
351
|
case "number": {
|
338
352
|
const number = schema2;
|
339
353
|
const json = { type: "number" };
|
340
|
-
const { minimum, maximum, format, multipleOf,
|
341
|
-
if (format?.includes("int")) {
|
354
|
+
const { minimum, maximum, format, multipleOf, exclusiveMaximum, exclusiveMinimum } = number._zod.bag;
|
355
|
+
if (typeof format === "string" && format?.includes("int")) {
|
342
356
|
json.type = "integer";
|
343
357
|
}
|
344
|
-
if (minimum
|
345
|
-
|
346
|
-
json.minimum = minimum;
|
347
|
-
} else {
|
348
|
-
json.exclusiveMinimum = minimum;
|
349
|
-
}
|
358
|
+
if (typeof minimum === "number") {
|
359
|
+
json.minimum = minimum;
|
350
360
|
}
|
351
|
-
if (maximum
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
}
|
361
|
+
if (typeof maximum === "number") {
|
362
|
+
json.maximum = maximum;
|
363
|
+
}
|
364
|
+
if (typeof exclusiveMinimum === "number") {
|
365
|
+
json.exclusiveMinimum = exclusiveMinimum;
|
357
366
|
}
|
358
|
-
if (
|
367
|
+
if (typeof exclusiveMaximum === "number") {
|
368
|
+
json.exclusiveMaximum = exclusiveMaximum;
|
369
|
+
}
|
370
|
+
if (typeof multipleOf === "number") {
|
359
371
|
json.multipleOf = multipleOf;
|
360
372
|
}
|
361
373
|
return [true, json];
|
@@ -388,21 +400,21 @@ class experimental_ZodToJsonSchemaConverter {
|
|
388
400
|
case "array": {
|
389
401
|
const array = schema2;
|
390
402
|
const json = { type: "array" };
|
391
|
-
const { minimum, maximum } = array._zod.
|
392
|
-
if (minimum
|
403
|
+
const { minimum, maximum } = array._zod.bag;
|
404
|
+
if (typeof minimum === "number") {
|
393
405
|
json.minItems = minimum;
|
394
406
|
}
|
395
|
-
if (maximum
|
407
|
+
if (typeof maximum === "number") {
|
396
408
|
json.maxItems = maximum;
|
397
409
|
}
|
398
|
-
json.items = this.#handleArrayItemJsonSchema(
|
410
|
+
json.items = this.#handleArrayItemJsonSchema(this.#convert(array._zod.def.element, options2, lazyDepth2, structureDepth + 1), options2);
|
399
411
|
return [true, json];
|
400
412
|
}
|
401
413
|
case "object": {
|
402
414
|
const object = schema2;
|
403
415
|
const json = { type: "object" };
|
404
416
|
for (const [key, value] of Object.entries(object._zod.def.shape)) {
|
405
|
-
const [itemRequired, itemJson] =
|
417
|
+
const [itemRequired, itemJson] = this.#convert(value, options2, lazyDepth2, structureDepth + 1);
|
406
418
|
json.properties ??= {};
|
407
419
|
json.properties[key] = itemJson;
|
408
420
|
if (itemRequired) {
|
@@ -414,7 +426,7 @@ class experimental_ZodToJsonSchemaConverter {
|
|
414
426
|
if (object._zod.def.catchall._zod.def.type === "never") {
|
415
427
|
json.additionalProperties = false;
|
416
428
|
} else {
|
417
|
-
const [_, addJson] =
|
429
|
+
const [_, addJson] = this.#convert(object._zod.def.catchall, options2, lazyDepth2, structureDepth + 1);
|
418
430
|
json.additionalProperties = addJson;
|
419
431
|
}
|
420
432
|
}
|
@@ -425,7 +437,7 @@ class experimental_ZodToJsonSchemaConverter {
|
|
425
437
|
const anyOf = [];
|
426
438
|
let required = true;
|
427
439
|
for (const item of union._zod.def.options) {
|
428
|
-
const [itemRequired, itemJson] =
|
440
|
+
const [itemRequired, itemJson] = this.#convert(item, options2, lazyDepth2, structureDepth);
|
429
441
|
if (!itemRequired) {
|
430
442
|
required = false;
|
431
443
|
}
|
@@ -446,7 +458,7 @@ class experimental_ZodToJsonSchemaConverter {
|
|
446
458
|
const json = { allOf: [] };
|
447
459
|
let required = false;
|
448
460
|
for (const item of [intersection._zod.def.left, intersection._zod.def.right]) {
|
449
|
-
const [itemRequired, itemJson] =
|
461
|
+
const [itemRequired, itemJson] = this.#convert(item, options2, lazyDepth2, structureDepth);
|
450
462
|
json.allOf.push(itemJson);
|
451
463
|
if (itemRequired) {
|
452
464
|
required = true;
|
@@ -458,16 +470,16 @@ class experimental_ZodToJsonSchemaConverter {
|
|
458
470
|
const tuple = schema2;
|
459
471
|
const json = { type: "array", prefixItems: [] };
|
460
472
|
for (const item of tuple._zod.def.items) {
|
461
|
-
json.prefixItems.push(this.#handleArrayItemJsonSchema(
|
473
|
+
json.prefixItems.push(this.#handleArrayItemJsonSchema(this.#convert(item, options2, lazyDepth2, structureDepth + 1), options2));
|
462
474
|
}
|
463
475
|
if (tuple._zod.def.rest) {
|
464
|
-
json.items = this.#handleArrayItemJsonSchema(
|
476
|
+
json.items = this.#handleArrayItemJsonSchema(this.#convert(tuple._zod.def.rest, options2, lazyDepth2, structureDepth + 1), options2);
|
465
477
|
}
|
466
|
-
const { minimum, maximum } = tuple._zod.
|
467
|
-
if (minimum
|
478
|
+
const { minimum, maximum } = tuple._zod.bag;
|
479
|
+
if (typeof minimum === "number") {
|
468
480
|
json.minItems = minimum;
|
469
481
|
}
|
470
|
-
if (maximum
|
482
|
+
if (typeof maximum === "number") {
|
471
483
|
json.maxItems = maximum;
|
472
484
|
}
|
473
485
|
return [true, json];
|
@@ -475,8 +487,8 @@ class experimental_ZodToJsonSchemaConverter {
|
|
475
487
|
case "record": {
|
476
488
|
const record = schema2;
|
477
489
|
const json = { type: "object" };
|
478
|
-
json.propertyNames =
|
479
|
-
json.additionalProperties =
|
490
|
+
json.propertyNames = this.#convert(record._zod.def.keyType, options2, lazyDepth2, structureDepth + 1)[1];
|
491
|
+
json.additionalProperties = this.#convert(record._zod.def.valueType, options2, lazyDepth2, structureDepth + 1)[1];
|
480
492
|
return [true, json];
|
481
493
|
}
|
482
494
|
case "map": {
|
@@ -486,8 +498,8 @@ class experimental_ZodToJsonSchemaConverter {
|
|
486
498
|
items: {
|
487
499
|
type: "array",
|
488
500
|
prefixItems: [
|
489
|
-
this.#handleArrayItemJsonSchema(
|
490
|
-
this.#handleArrayItemJsonSchema(
|
501
|
+
this.#handleArrayItemJsonSchema(this.#convert(map._zod.def.keyType, options2, lazyDepth2, structureDepth + 1), options2),
|
502
|
+
this.#handleArrayItemJsonSchema(this.#convert(map._zod.def.valueType, options2, lazyDepth2, structureDepth + 1), options2)
|
491
503
|
],
|
492
504
|
maxItems: 2,
|
493
505
|
minItems: 2
|
@@ -499,7 +511,7 @@ class experimental_ZodToJsonSchemaConverter {
|
|
499
511
|
return [true, {
|
500
512
|
type: "array",
|
501
513
|
uniqueItems: true,
|
502
|
-
items: this.#handleArrayItemJsonSchema(
|
514
|
+
items: this.#handleArrayItemJsonSchema(this.#convert(set._zod.def.valueType, options2, lazyDepth2, structureDepth + 1), options2)
|
503
515
|
}];
|
504
516
|
}
|
505
517
|
case "enum": {
|
@@ -523,12 +535,14 @@ class experimental_ZodToJsonSchemaConverter {
|
|
523
535
|
case "file": {
|
524
536
|
const file = schema2;
|
525
537
|
const oneOf = [];
|
526
|
-
const { mime } = file._zod.
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
538
|
+
const { mime } = file._zod.bag;
|
539
|
+
if (mime === void 0 || Array.isArray(mime) && mime.every((m) => typeof m === "string")) {
|
540
|
+
for (const type of mime ?? ["*/*"]) {
|
541
|
+
oneOf.push({
|
542
|
+
type: "string",
|
543
|
+
contentMediaType: type
|
544
|
+
});
|
545
|
+
}
|
532
546
|
}
|
533
547
|
return [true, oneOf.length === 1 ? oneOf[0] : { anyOf: oneOf }];
|
534
548
|
}
|
@@ -537,40 +551,40 @@ class experimental_ZodToJsonSchemaConverter {
|
|
537
551
|
}
|
538
552
|
case "nullable": {
|
539
553
|
const nullable = schema2;
|
540
|
-
const [required, json] =
|
554
|
+
const [required, json] = this.#convert(nullable._zod.def.innerType, options2, lazyDepth2, structureDepth);
|
541
555
|
return [required, { anyOf: [json, { type: "null" }] }];
|
542
556
|
}
|
543
557
|
case "nonoptional": {
|
544
558
|
const nonoptional = schema2;
|
545
|
-
const [, json] =
|
559
|
+
const [, json] = this.#convert(nonoptional._zod.def.innerType, options2, lazyDepth2, structureDepth);
|
546
560
|
return [true, json];
|
547
561
|
}
|
548
562
|
case "success": {
|
549
563
|
return [true, { type: "boolean" }];
|
550
564
|
}
|
551
|
-
case "default":
|
565
|
+
case "default":
|
566
|
+
case "prefault": {
|
552
567
|
const default_ = schema2;
|
553
|
-
const [, json] =
|
568
|
+
const [, json] = this.#convert(default_._zod.def.innerType, options2, lazyDepth2, structureDepth);
|
554
569
|
return [false, {
|
555
570
|
...json,
|
556
|
-
default: default_._zod.def.defaultValue
|
571
|
+
default: default_._zod.def.defaultValue
|
557
572
|
}];
|
558
573
|
}
|
559
574
|
case "catch": {
|
560
575
|
const catch_ = schema2;
|
561
|
-
|
562
|
-
return [false, json];
|
576
|
+
return this.#convert(catch_._zod.def.innerType, options2, lazyDepth2, structureDepth);
|
563
577
|
}
|
564
578
|
case "nan": {
|
565
579
|
return [true, options2.strategy === "input" ? this.unsupportedJsonSchema : { type: "null" }];
|
566
580
|
}
|
567
581
|
case "pipe": {
|
568
582
|
const pipe = schema2;
|
569
|
-
return
|
583
|
+
return this.#convert(options2.strategy === "input" ? pipe._zod.def.in : pipe._zod.def.out, options2, lazyDepth2, structureDepth);
|
570
584
|
}
|
571
585
|
case "readonly": {
|
572
586
|
const readonly_ = schema2;
|
573
|
-
const [required, json] =
|
587
|
+
const [required, json] = this.#convert(readonly_._zod.def.innerType, options2, lazyDepth2, structureDepth);
|
574
588
|
return [required, { ...json, readOnly: true }];
|
575
589
|
}
|
576
590
|
case "template_literal": {
|
@@ -582,15 +596,16 @@ class experimental_ZodToJsonSchemaConverter {
|
|
582
596
|
}
|
583
597
|
case "optional": {
|
584
598
|
const optional = schema2;
|
585
|
-
const [, json] =
|
599
|
+
const [, json] = this.#convert(optional._zod.def.innerType, options2, lazyDepth2, structureDepth);
|
586
600
|
return [false, json];
|
587
601
|
}
|
588
602
|
case "lazy": {
|
589
603
|
const lazy = schema2;
|
590
|
-
|
604
|
+
const currentLazyDepth = lazyDepth2 + 1;
|
605
|
+
if (currentLazyDepth > this.maxLazyDepth) {
|
591
606
|
return [false, this.anyJsonSchema];
|
592
607
|
}
|
593
|
-
return
|
608
|
+
return this.#convert(lazy._zod.def.getter(), options2, currentLazyDepth, structureDepth);
|
594
609
|
}
|
595
610
|
default: {
|
596
611
|
schema2._zod.def.type;
|
@@ -614,12 +629,12 @@ class experimental_ZodToJsonSchemaConverter {
|
|
614
629
|
if (global) {
|
615
630
|
return {
|
616
631
|
description: global.description,
|
617
|
-
examples: global.examples
|
632
|
+
examples: Array.isArray(global.examples) ? global.examples : void 0
|
618
633
|
};
|
619
634
|
}
|
620
635
|
}
|
621
636
|
#handleArrayItemJsonSchema([required, schema], options) {
|
622
|
-
if (required || options.strategy === "input") {
|
637
|
+
if (required || options.strategy === "input" || schema.default !== void 0) {
|
623
638
|
return schema;
|
624
639
|
}
|
625
640
|
if (schema === this.undefinedJsonSchema) {
|
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.d636350",
|
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
|
-
"@zod/core": ">=0.11.4",
|
33
32
|
"zod": ">=3.24.2",
|
34
|
-
"@orpc/contract": "0.0.0-next.
|
35
|
-
"@orpc/server": "0.0.0-next.
|
36
|
-
},
|
37
|
-
"peerDependenciesMeta": {
|
38
|
-
"@zod/core": {
|
39
|
-
"optional": true
|
40
|
-
},
|
41
|
-
"zod": {
|
42
|
-
"optional": true
|
43
|
-
}
|
33
|
+
"@orpc/contract": "0.0.0-next.d636350",
|
34
|
+
"@orpc/server": "0.0.0-next.d636350"
|
44
35
|
},
|
45
36
|
"dependencies": {
|
46
37
|
"escape-string-regexp": "^5.0.0",
|
47
38
|
"wildcard-match": "^5.1.3",
|
48
|
-
"@orpc/openapi": "0.0.0-next.
|
49
|
-
"@orpc/shared": "0.0.0-next.
|
39
|
+
"@orpc/openapi": "0.0.0-next.d636350",
|
40
|
+
"@orpc/shared": "0.0.0-next.d636350"
|
50
41
|
},
|
51
42
|
"devDependencies": {
|
52
|
-
"
|
53
|
-
"
|
54
|
-
"zod": "^3.24.2",
|
55
|
-
"zod-to-json-schema": "^3.24.5",
|
56
|
-
"zod4": "npm:zod@^4.0.0-beta.20250505T012514"
|
43
|
+
"zod": "^3.25.67",
|
44
|
+
"zod-to-json-schema": "^3.24.6"
|
57
45
|
},
|
58
46
|
"scripts": {
|
59
47
|
"build": "unbuild",
|