@orpc/zod 0.0.0-next.1431467 → 0.0.0-next.14dd190
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 +31 -23
- package/dist/index.d.mts +30 -19
- package/dist/index.d.ts +30 -19
- package/dist/index.mjs +106 -64
- package/dist/zod4/index.d.mts +314 -0
- package/dist/zod4/index.d.ts +314 -0
- package/dist/zod4/index.mjs +680 -0
- package/package.json +13 -7
package/dist/index.mjs
CHANGED
@@ -1,17 +1,18 @@
|
|
1
|
-
import { custom, ZodFirstPartyTypeKind } from 'zod';
|
1
|
+
import { custom, ZodFirstPartyTypeKind } from 'zod/v3';
|
2
2
|
import wcmatch from 'wildcard-match';
|
3
|
-
import { isObject, guard } from '@orpc/shared';
|
3
|
+
import { isObject, guard, toArray } from '@orpc/shared';
|
4
|
+
import { JsonSchemaXNativeType } from '@orpc/json-schema';
|
4
5
|
import { JSONSchemaFormat } from '@orpc/openapi';
|
5
6
|
import escapeStringRegexp from 'escape-string-regexp';
|
6
7
|
|
7
8
|
const CUSTOM_JSON_SCHEMA_SYMBOL = Symbol("ORPC_CUSTOM_JSON_SCHEMA");
|
8
9
|
const CUSTOM_JSON_SCHEMA_INPUT_SYMBOL = Symbol("ORPC_CUSTOM_JSON_SCHEMA_INPUT");
|
9
10
|
const CUSTOM_JSON_SCHEMA_OUTPUT_SYMBOL = Symbol("ORPC_CUSTOM_JSON_SCHEMA_OUTPUT");
|
10
|
-
function getCustomJsonSchema(def,
|
11
|
-
if (strategy === "input" && CUSTOM_JSON_SCHEMA_INPUT_SYMBOL in def) {
|
11
|
+
function getCustomJsonSchema(def, options) {
|
12
|
+
if (options.strategy === "input" && CUSTOM_JSON_SCHEMA_INPUT_SYMBOL in def) {
|
12
13
|
return def[CUSTOM_JSON_SCHEMA_INPUT_SYMBOL];
|
13
14
|
}
|
14
|
-
if (strategy === "output" && CUSTOM_JSON_SCHEMA_OUTPUT_SYMBOL in def) {
|
15
|
+
if (options.strategy === "output" && CUSTOM_JSON_SCHEMA_OUTPUT_SYMBOL in def) {
|
15
16
|
return def[CUSTOM_JSON_SCHEMA_OUTPUT_SYMBOL];
|
16
17
|
}
|
17
18
|
if (CUSTOM_JSON_SCHEMA_SYMBOL in def) {
|
@@ -19,8 +20,8 @@ function getCustomJsonSchema(def, strategy) {
|
|
19
20
|
}
|
20
21
|
return void 0;
|
21
22
|
}
|
22
|
-
function customJsonSchema(schema, custom,
|
23
|
-
const SYMBOL = strategy === "input" ? CUSTOM_JSON_SCHEMA_INPUT_SYMBOL : strategy === "output" ? CUSTOM_JSON_SCHEMA_OUTPUT_SYMBOL : CUSTOM_JSON_SCHEMA_SYMBOL;
|
23
|
+
function customJsonSchema(schema, custom, options = {}) {
|
24
|
+
const SYMBOL = options.strategy === "input" ? CUSTOM_JSON_SCHEMA_INPUT_SYMBOL : options.strategy === "output" ? CUSTOM_JSON_SCHEMA_OUTPUT_SYMBOL : CUSTOM_JSON_SCHEMA_SYMBOL;
|
24
25
|
const This = schema.constructor;
|
25
26
|
const newSchema = new This({
|
26
27
|
...schema._def,
|
@@ -128,7 +129,7 @@ class ZodSmartCoercionPlugin {
|
|
128
129
|
options.clientInterceptors ??= [];
|
129
130
|
options.clientInterceptors.unshift((options2) => {
|
130
131
|
const inputSchema = options2.procedure["~orpc"].inputSchema;
|
131
|
-
if (!inputSchema || inputSchema["~standard"].vendor !== "zod") {
|
132
|
+
if (!inputSchema || inputSchema["~standard"].vendor !== "zod" || "_zod" in inputSchema) {
|
132
133
|
return options2.next();
|
133
134
|
}
|
134
135
|
const coercedInput = zodCoerceInternal(inputSchema, options2.input);
|
@@ -390,46 +391,61 @@ function safeToDate(value) {
|
|
390
391
|
|
391
392
|
class ZodToJsonSchemaConverter {
|
392
393
|
maxLazyDepth;
|
394
|
+
maxStructureDepth;
|
393
395
|
unsupportedJsonSchema;
|
394
396
|
anyJsonSchema;
|
395
397
|
constructor(options = {}) {
|
396
398
|
this.maxLazyDepth = options.maxLazyDepth ?? 3;
|
399
|
+
this.maxStructureDepth = options.maxStructureDepth ?? 10;
|
397
400
|
this.unsupportedJsonSchema = options.unsupportedJsonSchema ?? { not: {} };
|
398
401
|
this.anyJsonSchema = options.anyJsonSchema ?? {};
|
399
402
|
}
|
400
403
|
condition(schema) {
|
401
|
-
return
|
404
|
+
return schema !== void 0 && schema["~standard"].vendor === "zod" && !("_zod" in schema);
|
402
405
|
}
|
403
|
-
convert(schema,
|
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
|
}
|
415
430
|
if (!isHandledCustomJSONSchema) {
|
416
|
-
const customJSONSchema = getCustomJsonSchema(def,
|
431
|
+
const customJSONSchema = getCustomJsonSchema(def, options);
|
417
432
|
if (customJSONSchema) {
|
418
433
|
const [required, json] = this.convert(
|
419
434
|
schema,
|
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
|
}
|
427
443
|
}
|
428
|
-
const customSchema = this
|
444
|
+
const customSchema = this.#handleCustomZodDef(def);
|
429
445
|
if (customSchema) {
|
430
446
|
return [true, customSchema];
|
431
447
|
}
|
432
|
-
const typeName = this
|
448
|
+
const typeName = this.#getZodTypeName(def);
|
433
449
|
switch (typeName) {
|
434
450
|
case ZodFirstPartyTypeKind.ZodString: {
|
435
451
|
const schema_ = schema;
|
@@ -548,17 +564,25 @@ 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: {
|
555
|
-
return strategy === "input" ? [true, this.unsupportedJsonSchema] : [true, { type: "null" }];
|
575
|
+
return options.strategy === "input" ? [true, this.unsupportedJsonSchema] : [true, { type: "null" }];
|
556
576
|
}
|
557
577
|
case ZodFirstPartyTypeKind.ZodBoolean: {
|
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,8 +615,8 @@ 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,
|
595
|
-
json.items = this
|
618
|
+
const [itemRequired, itemJson] = this.convert(def2.type, options, lazyDepth, false, false, structureDepth + 1);
|
619
|
+
json.items = this.#toArrayItemJsonSchema(itemRequired, itemJson, options.strategy);
|
596
620
|
if (def2.exactLength) {
|
597
621
|
json.maxItems = def2.exactLength.value;
|
598
622
|
json.minItems = def2.exactLength.value;
|
@@ -610,17 +634,17 @@ 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,
|
637
|
+
const [itemRequired, itemJson] = this.convert(item, options, lazyDepth, false, false, structureDepth + 1);
|
614
638
|
prefixItems.push(
|
615
|
-
this
|
639
|
+
this.#toArrayItemJsonSchema(itemRequired, itemJson, options.strategy)
|
616
640
|
);
|
617
641
|
}
|
618
642
|
if (prefixItems?.length) {
|
619
643
|
json.prefixItems = prefixItems;
|
620
644
|
}
|
621
645
|
if (schema_._def.rest) {
|
622
|
-
const [itemRequired, itemJson] = this.convert(schema_._def.rest,
|
623
|
-
json.items = this
|
646
|
+
const [itemRequired, itemJson] = this.convert(schema_._def.rest, options, lazyDepth, false, false, structureDepth + 1);
|
647
|
+
json.items = this.#toArrayItemJsonSchema(itemRequired, itemJson, options.strategy);
|
624
648
|
}
|
625
649
|
return [true, json];
|
626
650
|
}
|
@@ -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,
|
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);
|
@@ -642,13 +666,13 @@ class ZodToJsonSchemaConverter {
|
|
642
666
|
if (required.length) {
|
643
667
|
json.required = required;
|
644
668
|
}
|
645
|
-
const catchAllTypeName = this
|
669
|
+
const catchAllTypeName = this.#getZodTypeName(schema_._def.catchall._def);
|
646
670
|
if (catchAllTypeName === ZodFirstPartyTypeKind.ZodNever) {
|
647
671
|
if (schema_._def.unknownKeys === "strict") {
|
648
672
|
json.additionalProperties = false;
|
649
673
|
}
|
650
674
|
} else {
|
651
|
-
const [_, addJson] = this.convert(schema_._def.catchall,
|
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,33 +680,43 @@ class ZodToJsonSchemaConverter {
|
|
656
680
|
case ZodFirstPartyTypeKind.ZodRecord: {
|
657
681
|
const schema_ = schema;
|
658
682
|
const json = { type: "object" };
|
659
|
-
const [
|
683
|
+
const [__, keyJson] = this.convert(schema_._def.keyType, options, lazyDepth, false, false, structureDepth + 1);
|
684
|
+
if (Object.entries(keyJson).some(([k, v]) => k !== "type" || v !== "string")) {
|
685
|
+
json.propertyNames = keyJson;
|
686
|
+
}
|
687
|
+
const [_, itemJson] = this.convert(schema_._def.valueType, options, lazyDepth, false, false, structureDepth + 1);
|
660
688
|
json.additionalProperties = itemJson;
|
661
689
|
return [true, json];
|
662
690
|
}
|
663
691
|
case ZodFirstPartyTypeKind.ZodSet: {
|
664
692
|
const schema_ = schema;
|
665
|
-
const json = {
|
666
|
-
|
667
|
-
|
693
|
+
const json = {
|
694
|
+
"type": "array",
|
695
|
+
"uniqueItems": true,
|
696
|
+
"x-native-type": JsonSchemaXNativeType.Set
|
697
|
+
};
|
698
|
+
const [itemRequired, itemJson] = this.convert(schema_._def.valueType, options, lazyDepth, false, false, structureDepth + 1);
|
699
|
+
json.items = this.#toArrayItemJsonSchema(itemRequired, itemJson, options.strategy);
|
668
700
|
return [true, json];
|
669
701
|
}
|
670
702
|
case ZodFirstPartyTypeKind.ZodMap: {
|
671
703
|
const schema_ = schema;
|
672
|
-
const [keyRequired, keyJson] = this.convert(schema_._def.keyType,
|
673
|
-
const [valueRequired, valueJson] = this.convert(schema_._def.valueType,
|
674
|
-
|
675
|
-
type: "array",
|
676
|
-
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": {
|
677
709
|
type: "array",
|
678
710
|
prefixItems: [
|
679
|
-
this
|
680
|
-
this
|
711
|
+
this.#toArrayItemJsonSchema(keyRequired, keyJson, options.strategy),
|
712
|
+
this.#toArrayItemJsonSchema(valueRequired, valueJson, options.strategy)
|
681
713
|
],
|
682
714
|
maxItems: 2,
|
683
715
|
minItems: 2
|
684
|
-
}
|
685
|
-
|
716
|
+
},
|
717
|
+
"x-native-type": JsonSchemaXNativeType.Map
|
718
|
+
};
|
719
|
+
return [true, json];
|
686
720
|
}
|
687
721
|
case ZodFirstPartyTypeKind.ZodUnion:
|
688
722
|
case ZodFirstPartyTypeKind.ZodDiscriminatedUnion: {
|
@@ -690,7 +724,7 @@ class ZodToJsonSchemaConverter {
|
|
690
724
|
const anyOf = [];
|
691
725
|
let required = true;
|
692
726
|
for (const item of schema_._def.options) {
|
693
|
-
const [itemRequired, itemJson] = this.convert(item,
|
727
|
+
const [itemRequired, itemJson] = this.convert(item, options, lazyDepth, false, false, structureDepth);
|
694
728
|
if (!itemRequired) {
|
695
729
|
required = false;
|
696
730
|
if (itemJson !== this.unsupportedJsonSchema) {
|
@@ -710,7 +744,7 @@ class ZodToJsonSchemaConverter {
|
|
710
744
|
const allOf = [];
|
711
745
|
let required = false;
|
712
746
|
for (const item of [schema_._def.left, schema_._def.right]) {
|
713
|
-
const [itemRequired, itemJson] = this.convert(item,
|
747
|
+
const [itemRequired, itemJson] = this.convert(item, options, lazyDepth, false, false, structureDepth);
|
714
748
|
allOf.push(itemJson);
|
715
749
|
if (itemRequired) {
|
716
750
|
required = true;
|
@@ -719,60 +753,63 @@ class ZodToJsonSchemaConverter {
|
|
719
753
|
return [required, { allOf }];
|
720
754
|
}
|
721
755
|
case ZodFirstPartyTypeKind.ZodLazy: {
|
722
|
-
|
756
|
+
const currentLazyDepth = lazyDepth + 1;
|
757
|
+
if (currentLazyDepth > this.maxLazyDepth) {
|
723
758
|
return [false, this.anyJsonSchema];
|
724
759
|
}
|
725
760
|
const schema_ = schema;
|
726
|
-
return this.convert(schema_._def.getter(),
|
761
|
+
return this.convert(schema_._def.getter(), options, currentLazyDepth, false, false, structureDepth);
|
727
762
|
}
|
728
763
|
case ZodFirstPartyTypeKind.ZodOptional: {
|
729
764
|
const schema_ = schema;
|
730
|
-
const [_, inner] = this.convert(schema_._def.innerType,
|
765
|
+
const [_, inner] = this.convert(schema_._def.innerType, options, lazyDepth, false, false, structureDepth);
|
731
766
|
return [false, inner];
|
732
767
|
}
|
733
768
|
case ZodFirstPartyTypeKind.ZodReadonly: {
|
734
769
|
const schema_ = schema;
|
735
|
-
|
770
|
+
const [required, json] = this.convert(schema_._def.innerType, options, lazyDepth, false, false, structureDepth);
|
771
|
+
return [required, { ...json, readOnly: true }];
|
736
772
|
}
|
737
773
|
case ZodFirstPartyTypeKind.ZodDefault: {
|
738
774
|
const schema_ = schema;
|
739
|
-
const [_, json] = this.convert(schema_._def.innerType,
|
775
|
+
const [_, json] = this.convert(schema_._def.innerType, options, lazyDepth, false, false, structureDepth);
|
740
776
|
return [false, { default: schema_._def.defaultValue(), ...json }];
|
741
777
|
}
|
742
778
|
case ZodFirstPartyTypeKind.ZodEffects: {
|
743
779
|
const schema_ = schema;
|
744
|
-
if (schema_._def.effect.type === "transform" && strategy === "output") {
|
780
|
+
if (schema_._def.effect.type === "transform" && options.strategy === "output") {
|
745
781
|
return [false, this.anyJsonSchema];
|
746
782
|
}
|
747
|
-
return this.convert(schema_._def.schema,
|
783
|
+
return this.convert(schema_._def.schema, options, lazyDepth, false, false, structureDepth);
|
748
784
|
}
|
749
785
|
case ZodFirstPartyTypeKind.ZodCatch: {
|
750
786
|
const schema_ = schema;
|
751
|
-
return this.convert(schema_._def.innerType,
|
787
|
+
return this.convert(schema_._def.innerType, options, lazyDepth, false, false, structureDepth);
|
752
788
|
}
|
753
789
|
case ZodFirstPartyTypeKind.ZodBranded: {
|
754
790
|
const schema_ = schema;
|
755
|
-
return this.convert(schema_._def.type,
|
791
|
+
return this.convert(schema_._def.type, options, lazyDepth, false, false, structureDepth);
|
756
792
|
}
|
757
793
|
case ZodFirstPartyTypeKind.ZodPipeline: {
|
758
794
|
const schema_ = schema;
|
759
795
|
return this.convert(
|
760
|
-
strategy === "input" ? schema_._def.in : schema_._def.out,
|
761
|
-
|
796
|
+
options.strategy === "input" ? schema_._def.in : schema_._def.out,
|
797
|
+
options,
|
762
798
|
lazyDepth,
|
763
799
|
false,
|
764
|
-
false
|
800
|
+
false,
|
801
|
+
structureDepth
|
765
802
|
);
|
766
803
|
}
|
767
804
|
case ZodFirstPartyTypeKind.ZodNullable: {
|
768
805
|
const schema_ = schema;
|
769
|
-
const [required, json] = this.convert(schema_._def.innerType,
|
770
|
-
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" }] }];
|
771
808
|
}
|
772
809
|
}
|
773
810
|
return [true, this.unsupportedJsonSchema];
|
774
811
|
}
|
775
|
-
handleCustomZodDef(def) {
|
812
|
+
#handleCustomZodDef(def) {
|
776
813
|
const customZodDef = getCustomZodDef(def);
|
777
814
|
if (!customZodDef) {
|
778
815
|
return void 0;
|
@@ -786,19 +823,24 @@ class ZodToJsonSchemaConverter {
|
|
786
823
|
}
|
787
824
|
case "regexp": {
|
788
825
|
return {
|
789
|
-
type: "string",
|
790
|
-
pattern: "^\\/(.*)\\/([a-z]*)$"
|
826
|
+
"type": "string",
|
827
|
+
"pattern": "^\\/(.*)\\/([a-z]*)$",
|
828
|
+
"x-native-type": JsonSchemaXNativeType.RegExp
|
791
829
|
};
|
792
830
|
}
|
793
831
|
case "url": {
|
794
|
-
return {
|
832
|
+
return {
|
833
|
+
"type": "string",
|
834
|
+
"format": JSONSchemaFormat.URI,
|
835
|
+
"x-native-type": JsonSchemaXNativeType.Url
|
836
|
+
};
|
795
837
|
}
|
796
838
|
}
|
797
839
|
}
|
798
|
-
getZodTypeName(def) {
|
840
|
+
#getZodTypeName(def) {
|
799
841
|
return def.typeName;
|
800
842
|
}
|
801
|
-
toArrayItemJsonSchema(required, schema, strategy) {
|
843
|
+
#toArrayItemJsonSchema(required, schema, strategy) {
|
802
844
|
if (required) {
|
803
845
|
return schema;
|
804
846
|
}
|