@orpc/zod 0.0.0-next.e565b64 → 0.0.0-next.e5e2613
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 -7
- package/dist/index.d.mts +15 -6
- package/dist/index.d.ts +15 -6
- package/dist/index.mjs +75 -38
- package/dist/zod4/index.d.mts +17 -5
- package/dist/zod4/index.d.ts +17 -5
- package/dist/zod4/index.mjs +83 -64
- package/package.json +8 -7
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/).
|
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,7 @@
|
|
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
|
+
import { JsonSchemaXNativeType } from '@orpc/json-schema';
|
4
5
|
import { JSONSchemaFormat } from '@orpc/openapi';
|
5
6
|
import escapeStringRegexp from 'escape-string-regexp';
|
6
7
|
|
@@ -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
404
|
return schema !== void 0 && schema["~standard"].vendor === "zod";
|
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
@@ -6,6 +6,9 @@ import { Interceptor } from '@orpc/shared';
|
|
6
6
|
import * as zod_v4_core from 'zod/v4/core';
|
7
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;
|
@@ -13,13 +16,21 @@ declare class experimental_ZodSmartCoercionPlugin<TContext extends Context> impl
|
|
13
16
|
|
14
17
|
interface experimental_ZodToJsonSchemaOptions {
|
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
|
*
|
@@ -51,6 +62,7 @@ interface experimental_ZodToJsonSchemaOptions {
|
|
51
62
|
declare class experimental_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;
|
@@ -138,7 +150,7 @@ declare const experimental_JSON_SCHEMA_REGISTRY: zod_v4_core.$ZodRegistry<{
|
|
138
150
|
unevaluatedProperties?: JSONSchema;
|
139
151
|
uniqueItems?: boolean;
|
140
152
|
writeOnly?: boolean;
|
141
|
-
}, zod_v4_core.$ZodType<unknown, unknown
|
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
|
*
|
@@ -217,7 +229,7 @@ declare const experimental_JSON_SCHEMA_INPUT_REGISTRY: zod_v4_core.$ZodRegistry<
|
|
217
229
|
unevaluatedProperties?: JSONSchema;
|
218
230
|
uniqueItems?: boolean;
|
219
231
|
writeOnly?: boolean;
|
220
|
-
}, zod_v4_core.$ZodType<unknown, unknown
|
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
|
*
|
@@ -296,7 +308,7 @@ declare const experimental_JSON_SCHEMA_OUTPUT_REGISTRY: zod_v4_core.$ZodRegistry
|
|
296
308
|
unevaluatedProperties?: JSONSchema;
|
297
309
|
uniqueItems?: boolean;
|
298
310
|
writeOnly?: boolean;
|
299
|
-
}, zod_v4_core.$ZodType<unknown, unknown
|
311
|
+
}, zod_v4_core.$ZodType<unknown, unknown, zod_v4_core.$ZodTypeInternals<unknown, unknown>>>;
|
300
312
|
|
301
313
|
export { experimental_JSON_SCHEMA_INPUT_REGISTRY, experimental_JSON_SCHEMA_OUTPUT_REGISTRY, experimental_JSON_SCHEMA_REGISTRY, experimental_ZodSmartCoercionPlugin, experimental_ZodToJsonSchemaConverter };
|
302
314
|
export type { experimental_ZodToJsonSchemaOptions };
|
package/dist/zod4/index.d.ts
CHANGED
@@ -6,6 +6,9 @@ import { Interceptor } from '@orpc/shared';
|
|
6
6
|
import * as zod_v4_core from 'zod/v4/core';
|
7
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;
|
@@ -13,13 +16,21 @@ declare class experimental_ZodSmartCoercionPlugin<TContext extends Context> impl
|
|
13
16
|
|
14
17
|
interface experimental_ZodToJsonSchemaOptions {
|
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
|
*
|
@@ -51,6 +62,7 @@ interface experimental_ZodToJsonSchemaOptions {
|
|
51
62
|
declare class experimental_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;
|
@@ -138,7 +150,7 @@ declare const experimental_JSON_SCHEMA_REGISTRY: zod_v4_core.$ZodRegistry<{
|
|
138
150
|
unevaluatedProperties?: JSONSchema;
|
139
151
|
uniqueItems?: boolean;
|
140
152
|
writeOnly?: boolean;
|
141
|
-
}, zod_v4_core.$ZodType<unknown, unknown
|
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
|
*
|
@@ -217,7 +229,7 @@ declare const experimental_JSON_SCHEMA_INPUT_REGISTRY: zod_v4_core.$ZodRegistry<
|
|
217
229
|
unevaluatedProperties?: JSONSchema;
|
218
230
|
uniqueItems?: boolean;
|
219
231
|
writeOnly?: boolean;
|
220
|
-
}, zod_v4_core.$ZodType<unknown, unknown
|
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
|
*
|
@@ -296,7 +308,7 @@ declare const experimental_JSON_SCHEMA_OUTPUT_REGISTRY: zod_v4_core.$ZodRegistry
|
|
296
308
|
unevaluatedProperties?: JSONSchema;
|
297
309
|
uniqueItems?: boolean;
|
298
310
|
writeOnly?: boolean;
|
299
|
-
}, zod_v4_core.$ZodType<unknown, unknown
|
311
|
+
}, zod_v4_core.$ZodType<unknown, unknown, zod_v4_core.$ZodTypeInternals<unknown, unknown>>>;
|
300
312
|
|
301
313
|
export { experimental_JSON_SCHEMA_INPUT_REGISTRY, experimental_JSON_SCHEMA_OUTPUT_REGISTRY, experimental_JSON_SCHEMA_REGISTRY, experimental_ZodSmartCoercionPlugin, experimental_ZodToJsonSchemaConverter };
|
302
314
|
export type { experimental_ZodToJsonSchemaOptions };
|
package/dist/zod4/index.mjs
CHANGED
@@ -1,4 +1,5 @@
|
|
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
4
|
import { registry, globalRegistry } from 'zod/v4/core';
|
4
5
|
|
@@ -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
|
}
|
@@ -255,30 +267,6 @@ class experimental_ZodSmartCoercionPlugin {
|
|
255
267
|
}
|
256
268
|
return value;
|
257
269
|
}
|
258
|
-
/**
|
259
|
-
* This function is inspired from Zod, because it's not exported
|
260
|
-
* https://github.com/colinhacks/zod/blob/v4/packages/core/src/schemas.ts#L1903C1-L1921C2
|
261
|
-
*/
|
262
|
-
#matchDiscriminators(input, discs) {
|
263
|
-
for (const [key, value] of discs) {
|
264
|
-
const data = input[key];
|
265
|
-
if (value.values.size && !value.values.has(data)) {
|
266
|
-
return false;
|
267
|
-
}
|
268
|
-
if (value.maps.length === 0) {
|
269
|
-
continue;
|
270
|
-
}
|
271
|
-
if (!isObject(data)) {
|
272
|
-
return false;
|
273
|
-
}
|
274
|
-
for (const m of value.maps) {
|
275
|
-
if (!this.#matchDiscriminators(data, m)) {
|
276
|
-
return false;
|
277
|
-
}
|
278
|
-
}
|
279
|
-
}
|
280
|
-
return true;
|
281
|
-
}
|
282
270
|
}
|
283
271
|
|
284
272
|
const experimental_JSON_SCHEMA_REGISTRY = registry();
|
@@ -287,12 +275,14 @@ const experimental_JSON_SCHEMA_OUTPUT_REGISTRY = registry();
|
|
287
275
|
|
288
276
|
class experimental_ZodToJsonSchemaConverter {
|
289
277
|
maxLazyDepth;
|
278
|
+
maxStructureDepth;
|
290
279
|
anyJsonSchema;
|
291
280
|
unsupportedJsonSchema;
|
292
281
|
undefinedJsonSchema;
|
293
282
|
interceptors;
|
294
283
|
constructor(options = {}) {
|
295
284
|
this.maxLazyDepth = options.maxLazyDepth ?? 2;
|
285
|
+
this.maxStructureDepth = options.maxStructureDepth ?? 10;
|
296
286
|
this.anyJsonSchema = options.anyJsonSchema ?? {};
|
297
287
|
this.unsupportedJsonSchema = options.unsupportedJsonSchema ?? { not: {} };
|
298
288
|
this.undefinedJsonSchema = options.undefinedJsonSchema ?? { not: {} };
|
@@ -302,17 +292,28 @@ class experimental_ZodToJsonSchemaConverter {
|
|
302
292
|
return schema !== void 0 && schema["~standard"].vendor === "zod";
|
303
293
|
}
|
304
294
|
convert(schema, options) {
|
305
|
-
return this.#convert(schema, options, 0);
|
295
|
+
return this.#convert(schema, options, 0, 0);
|
306
296
|
}
|
307
|
-
#convert(schema, options, lazyDepth, isHandledCustomJSONSchema = false) {
|
297
|
+
#convert(schema, options, lazyDepth, structureDepth, isHandledCustomJSONSchema = false) {
|
308
298
|
return intercept(
|
309
299
|
this.interceptors,
|
310
300
|
{ schema, options, lazyDepth, isHandledCustomJSONSchema },
|
311
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
|
+
}
|
312
313
|
if (!isHandledCustomJSONSchema2) {
|
313
314
|
const customJSONSchema = this.#getCustomJsonSchema(schema2, options2);
|
314
315
|
if (customJSONSchema) {
|
315
|
-
const [required, json] = this.#convert(schema2, options2, lazyDepth2, true);
|
316
|
+
const [required, json] = this.#convert(schema2, options2, lazyDepth2, structureDepth, true);
|
316
317
|
return [required, { ...json, ...customJSONSchema }];
|
317
318
|
}
|
318
319
|
}
|
@@ -320,7 +321,7 @@ class experimental_ZodToJsonSchemaConverter {
|
|
320
321
|
case "string": {
|
321
322
|
const string = schema2;
|
322
323
|
const json = { type: "string" };
|
323
|
-
const { minimum, maximum, format,
|
324
|
+
const { minimum, maximum, format, patterns, contentEncoding } = string._zod.bag;
|
324
325
|
if (typeof minimum === "number") {
|
325
326
|
json.minLength = minimum;
|
326
327
|
}
|
@@ -333,8 +334,15 @@ class experimental_ZodToJsonSchemaConverter {
|
|
333
334
|
if (typeof format === "string" && format !== "regex" && json.contentEncoding === void 0) {
|
334
335
|
json.format = this.#handleStringFormat(format);
|
335
336
|
}
|
336
|
-
if (
|
337
|
-
|
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
|
+
}
|
338
346
|
}
|
339
347
|
if (format === "jwt" && json.contentEncoding === void 0 && json.format === void 0 && json.pattern === void 0) {
|
340
348
|
json.pattern = /^[\w-]+\.[\w-]+\.[\w-]+$/.source;
|
@@ -369,10 +377,18 @@ class experimental_ZodToJsonSchemaConverter {
|
|
369
377
|
return [true, { type: "boolean" }];
|
370
378
|
}
|
371
379
|
case "bigint": {
|
372
|
-
return [true, {
|
380
|
+
return [true, {
|
381
|
+
"type": "string",
|
382
|
+
"pattern": "^-?[0-9]+$",
|
383
|
+
"x-native-type": JsonSchemaXNativeType.BigInt
|
384
|
+
}];
|
373
385
|
}
|
374
386
|
case "date": {
|
375
|
-
return [true, {
|
387
|
+
return [true, {
|
388
|
+
"type": "string",
|
389
|
+
"format": JSONSchemaFormat.DateTime,
|
390
|
+
"x-native-type": JsonSchemaXNativeType.Date
|
391
|
+
}];
|
376
392
|
}
|
377
393
|
case "null": {
|
378
394
|
return [true, { type: "null" }];
|
@@ -400,14 +416,14 @@ class experimental_ZodToJsonSchemaConverter {
|
|
400
416
|
if (typeof maximum === "number") {
|
401
417
|
json.maxItems = maximum;
|
402
418
|
}
|
403
|
-
json.items = this.#handleArrayItemJsonSchema(this.#convert(array._zod.def.element, options2, lazyDepth2), options2);
|
419
|
+
json.items = this.#handleArrayItemJsonSchema(this.#convert(array._zod.def.element, options2, lazyDepth2, structureDepth + 1), options2);
|
404
420
|
return [true, json];
|
405
421
|
}
|
406
422
|
case "object": {
|
407
423
|
const object = schema2;
|
408
424
|
const json = { type: "object" };
|
409
425
|
for (const [key, value] of Object.entries(object._zod.def.shape)) {
|
410
|
-
const [itemRequired, itemJson] = this.#convert(value, options2, lazyDepth2);
|
426
|
+
const [itemRequired, itemJson] = this.#convert(value, options2, lazyDepth2, structureDepth + 1);
|
411
427
|
json.properties ??= {};
|
412
428
|
json.properties[key] = itemJson;
|
413
429
|
if (itemRequired) {
|
@@ -419,7 +435,7 @@ class experimental_ZodToJsonSchemaConverter {
|
|
419
435
|
if (object._zod.def.catchall._zod.def.type === "never") {
|
420
436
|
json.additionalProperties = false;
|
421
437
|
} else {
|
422
|
-
const [_, addJson] = this.#convert(object._zod.def.catchall, options2, lazyDepth2);
|
438
|
+
const [_, addJson] = this.#convert(object._zod.def.catchall, options2, lazyDepth2, structureDepth + 1);
|
423
439
|
json.additionalProperties = addJson;
|
424
440
|
}
|
425
441
|
}
|
@@ -430,7 +446,7 @@ class experimental_ZodToJsonSchemaConverter {
|
|
430
446
|
const anyOf = [];
|
431
447
|
let required = true;
|
432
448
|
for (const item of union._zod.def.options) {
|
433
|
-
const [itemRequired, itemJson] = this.#convert(item, options2, lazyDepth2);
|
449
|
+
const [itemRequired, itemJson] = this.#convert(item, options2, lazyDepth2, structureDepth);
|
434
450
|
if (!itemRequired) {
|
435
451
|
required = false;
|
436
452
|
}
|
@@ -451,7 +467,7 @@ class experimental_ZodToJsonSchemaConverter {
|
|
451
467
|
const json = { allOf: [] };
|
452
468
|
let required = false;
|
453
469
|
for (const item of [intersection._zod.def.left, intersection._zod.def.right]) {
|
454
|
-
const [itemRequired, itemJson] = this.#convert(item, options2, lazyDepth2);
|
470
|
+
const [itemRequired, itemJson] = this.#convert(item, options2, lazyDepth2, structureDepth);
|
455
471
|
json.allOf.push(itemJson);
|
456
472
|
if (itemRequired) {
|
457
473
|
required = true;
|
@@ -463,10 +479,10 @@ class experimental_ZodToJsonSchemaConverter {
|
|
463
479
|
const tuple = schema2;
|
464
480
|
const json = { type: "array", prefixItems: [] };
|
465
481
|
for (const item of tuple._zod.def.items) {
|
466
|
-
json.prefixItems.push(this.#handleArrayItemJsonSchema(this.#convert(item, options2, lazyDepth2), options2));
|
482
|
+
json.prefixItems.push(this.#handleArrayItemJsonSchema(this.#convert(item, options2, lazyDepth2, structureDepth + 1), options2));
|
467
483
|
}
|
468
484
|
if (tuple._zod.def.rest) {
|
469
|
-
json.items = this.#handleArrayItemJsonSchema(this.#convert(tuple._zod.def.rest, options2, lazyDepth2), options2);
|
485
|
+
json.items = this.#handleArrayItemJsonSchema(this.#convert(tuple._zod.def.rest, options2, lazyDepth2, structureDepth + 1), options2);
|
470
486
|
}
|
471
487
|
const { minimum, maximum } = tuple._zod.bag;
|
472
488
|
if (typeof minimum === "number") {
|
@@ -480,31 +496,33 @@ class experimental_ZodToJsonSchemaConverter {
|
|
480
496
|
case "record": {
|
481
497
|
const record = schema2;
|
482
498
|
const json = { type: "object" };
|
483
|
-
json.propertyNames = this.#convert(record._zod.def.keyType, options2, lazyDepth2)[1];
|
484
|
-
json.additionalProperties = this.#convert(record._zod.def.valueType, options2, lazyDepth2)[1];
|
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];
|
485
501
|
return [true, json];
|
486
502
|
}
|
487
503
|
case "map": {
|
488
504
|
const map = schema2;
|
489
505
|
return [true, {
|
490
|
-
type: "array",
|
491
|
-
items: {
|
506
|
+
"type": "array",
|
507
|
+
"items": {
|
492
508
|
type: "array",
|
493
509
|
prefixItems: [
|
494
|
-
this.#handleArrayItemJsonSchema(this.#convert(map._zod.def.keyType, options2, lazyDepth2), options2),
|
495
|
-
this.#handleArrayItemJsonSchema(this.#convert(map._zod.def.valueType, options2, lazyDepth2), options2)
|
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)
|
496
512
|
],
|
497
513
|
maxItems: 2,
|
498
514
|
minItems: 2
|
499
|
-
}
|
515
|
+
},
|
516
|
+
"x-native-type": JsonSchemaXNativeType.Map
|
500
517
|
}];
|
501
518
|
}
|
502
519
|
case "set": {
|
503
520
|
const set = schema2;
|
504
521
|
return [true, {
|
505
|
-
type: "array",
|
506
|
-
uniqueItems: true,
|
507
|
-
items: this.#handleArrayItemJsonSchema(this.#convert(set._zod.def.valueType, options2, lazyDepth2), options2)
|
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
|
508
526
|
}];
|
509
527
|
}
|
510
528
|
case "enum": {
|
@@ -544,12 +562,12 @@ class experimental_ZodToJsonSchemaConverter {
|
|
544
562
|
}
|
545
563
|
case "nullable": {
|
546
564
|
const nullable = schema2;
|
547
|
-
const [required, json] = this.#convert(nullable._zod.def.innerType, options2, lazyDepth2);
|
565
|
+
const [required, json] = this.#convert(nullable._zod.def.innerType, options2, lazyDepth2, structureDepth);
|
548
566
|
return [required, { anyOf: [json, { type: "null" }] }];
|
549
567
|
}
|
550
568
|
case "nonoptional": {
|
551
569
|
const nonoptional = schema2;
|
552
|
-
const [, json] = this.#convert(nonoptional._zod.def.innerType, options2, lazyDepth2);
|
570
|
+
const [, json] = this.#convert(nonoptional._zod.def.innerType, options2, lazyDepth2, structureDepth);
|
553
571
|
return [true, json];
|
554
572
|
}
|
555
573
|
case "success": {
|
@@ -558,7 +576,7 @@ class experimental_ZodToJsonSchemaConverter {
|
|
558
576
|
case "default":
|
559
577
|
case "prefault": {
|
560
578
|
const default_ = schema2;
|
561
|
-
const [, json] = this.#convert(default_._zod.def.innerType, options2, lazyDepth2);
|
579
|
+
const [, json] = this.#convert(default_._zod.def.innerType, options2, lazyDepth2, structureDepth);
|
562
580
|
return [false, {
|
563
581
|
...json,
|
564
582
|
default: default_._zod.def.defaultValue
|
@@ -566,18 +584,18 @@ class experimental_ZodToJsonSchemaConverter {
|
|
566
584
|
}
|
567
585
|
case "catch": {
|
568
586
|
const catch_ = schema2;
|
569
|
-
return this.#convert(catch_._zod.def.innerType, options2, lazyDepth2);
|
587
|
+
return this.#convert(catch_._zod.def.innerType, options2, lazyDepth2, structureDepth);
|
570
588
|
}
|
571
589
|
case "nan": {
|
572
590
|
return [true, options2.strategy === "input" ? this.unsupportedJsonSchema : { type: "null" }];
|
573
591
|
}
|
574
592
|
case "pipe": {
|
575
593
|
const pipe = schema2;
|
576
|
-
return this.#convert(options2.strategy === "input" ? pipe._zod.def.in : pipe._zod.def.out, options2, lazyDepth2);
|
594
|
+
return this.#convert(options2.strategy === "input" ? pipe._zod.def.in : pipe._zod.def.out, options2, lazyDepth2, structureDepth);
|
577
595
|
}
|
578
596
|
case "readonly": {
|
579
597
|
const readonly_ = schema2;
|
580
|
-
const [required, json] = this.#convert(readonly_._zod.def.innerType, options2, lazyDepth2);
|
598
|
+
const [required, json] = this.#convert(readonly_._zod.def.innerType, options2, lazyDepth2, structureDepth);
|
581
599
|
return [required, { ...json, readOnly: true }];
|
582
600
|
}
|
583
601
|
case "template_literal": {
|
@@ -589,15 +607,16 @@ class experimental_ZodToJsonSchemaConverter {
|
|
589
607
|
}
|
590
608
|
case "optional": {
|
591
609
|
const optional = schema2;
|
592
|
-
const [, json] = this.#convert(optional._zod.def.innerType, options2, lazyDepth2);
|
610
|
+
const [, json] = this.#convert(optional._zod.def.innerType, options2, lazyDepth2, structureDepth);
|
593
611
|
return [false, json];
|
594
612
|
}
|
595
613
|
case "lazy": {
|
596
614
|
const lazy = schema2;
|
597
|
-
|
615
|
+
const currentLazyDepth = lazyDepth2 + 1;
|
616
|
+
if (currentLazyDepth > this.maxLazyDepth) {
|
598
617
|
return [false, this.anyJsonSchema];
|
599
618
|
}
|
600
|
-
return this.#convert(lazy._zod.def.getter(), options2,
|
619
|
+
return this.#convert(lazy._zod.def.getter(), options2, currentLazyDepth, structureDepth);
|
601
620
|
}
|
602
621
|
default: {
|
603
622
|
schema2._zod.def.type;
|
@@ -621,7 +640,7 @@ class experimental_ZodToJsonSchemaConverter {
|
|
621
640
|
if (global) {
|
622
641
|
return {
|
623
642
|
description: global.description,
|
624
|
-
examples: global.examples
|
643
|
+
examples: Array.isArray(global.examples) ? global.examples : void 0
|
625
644
|
};
|
626
645
|
}
|
627
646
|
}
|
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.e5e2613",
|
5
5
|
"license": "MIT",
|
6
6
|
"homepage": "https://orpc.unnoq.com",
|
7
7
|
"repository": {
|
@@ -30,18 +30,19 @@
|
|
30
30
|
],
|
31
31
|
"peerDependencies": {
|
32
32
|
"zod": ">=3.24.2",
|
33
|
-
"@orpc/contract": "0.0.0-next.
|
34
|
-
"@orpc/server": "0.0.0-next.
|
33
|
+
"@orpc/contract": "0.0.0-next.e5e2613",
|
34
|
+
"@orpc/server": "0.0.0-next.e5e2613"
|
35
35
|
},
|
36
36
|
"dependencies": {
|
37
37
|
"escape-string-regexp": "^5.0.0",
|
38
38
|
"wildcard-match": "^5.1.3",
|
39
|
-
"@orpc/
|
40
|
-
"@orpc/
|
39
|
+
"@orpc/json-schema": "0.0.0-next.e5e2613",
|
40
|
+
"@orpc/openapi": "0.0.0-next.e5e2613",
|
41
|
+
"@orpc/shared": "0.0.0-next.e5e2613"
|
41
42
|
},
|
42
43
|
"devDependencies": {
|
43
|
-
"zod": "^3.25.
|
44
|
-
"zod-to-json-schema": "^3.24.
|
44
|
+
"zod": "^3.25.76",
|
45
|
+
"zod-to-json-schema": "^3.24.6"
|
45
46
|
},
|
46
47
|
"scripts": {
|
47
48
|
"build": "unbuild",
|