zod 3.25.74 → 3.25.76
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/package.json +1 -1
- package/src/v4/classic/schemas.ts +4 -7
- package/src/v4/classic/tests/recursive-types.test.ts +30 -0
- package/src/v4/classic/tests/refine.test.ts +109 -0
- package/src/v4/classic/tests/registries.test.ts +9 -0
- package/src/v4/classic/tests/to-json-schema.test.ts +49 -17
- package/src/v4/core/api.ts +2 -0
- package/src/v4/core/checks.ts +8 -10
- package/src/v4/core/errors.ts +4 -0
- package/src/v4/core/registries.ts +11 -1
- package/src/v4/core/schemas.ts +18 -4
- package/src/v4/core/to-json-schema.ts +52 -26
- package/v4/classic/schemas.cjs +4 -4
- package/v4/classic/schemas.d.cts +2 -2
- package/v4/classic/schemas.d.ts +2 -2
- package/v4/classic/schemas.js +4 -4
- package/v4/core/checks.cjs +18 -12
- package/v4/core/checks.d.cts +2 -1
- package/v4/core/checks.d.ts +2 -1
- package/v4/core/checks.js +18 -12
- package/v4/core/errors.cjs +4 -0
- package/v4/core/errors.js +4 -0
- package/v4/core/registries.cjs +10 -1
- package/v4/core/registries.d.cts +2 -1
- package/v4/core/registries.d.ts +2 -1
- package/v4/core/registries.js +10 -1
- package/v4/core/schemas.cjs +2 -2
- package/v4/core/schemas.d.cts +14 -0
- package/v4/core/schemas.d.ts +14 -0
- package/v4/core/schemas.js +2 -2
- package/v4/core/to-json-schema.cjs +49 -25
- package/v4/core/to-json-schema.d.cts +1 -1
- package/v4/core/to-json-schema.d.ts +1 -1
- package/v4/core/to-json-schema.js +49 -25
package/v4/core/schemas.d.ts
CHANGED
|
@@ -635,6 +635,8 @@ export interface $ZodIntersectionDef<Left extends SomeType = $ZodType, Right ext
|
|
|
635
635
|
export interface $ZodIntersectionInternals<A extends SomeType = $ZodType, B extends SomeType = $ZodType> extends $ZodTypeInternals<core.output<A> & core.output<B>, core.input<A> & core.input<B>> {
|
|
636
636
|
def: $ZodIntersectionDef<A, B>;
|
|
637
637
|
isst: never;
|
|
638
|
+
optin: A["_zod"]["optin"] | B["_zod"]["optin"];
|
|
639
|
+
optout: A["_zod"]["optout"] | B["_zod"]["optout"];
|
|
638
640
|
}
|
|
639
641
|
export interface $ZodIntersection<A extends SomeType = $ZodType, B extends SomeType = $ZodType> extends $ZodType {
|
|
640
642
|
_zod: $ZodIntersectionInternals<A, B>;
|
|
@@ -686,6 +688,8 @@ export type $InferZodRecordInput<Key extends $ZodRecordKey = $ZodRecordKey, Valu
|
|
|
686
688
|
export interface $ZodRecordInternals<Key extends $ZodRecordKey = $ZodRecordKey, Value extends SomeType = $ZodType> extends $ZodTypeInternals<$InferZodRecordOutput<Key, Value>, $InferZodRecordInput<Key, Value>> {
|
|
687
689
|
def: $ZodRecordDef<Key, Value>;
|
|
688
690
|
isst: errors.$ZodIssueInvalidType | errors.$ZodIssueInvalidKey<Record<PropertyKey, unknown>>;
|
|
691
|
+
optin?: "optional" | undefined;
|
|
692
|
+
optout?: "optional" | undefined;
|
|
689
693
|
}
|
|
690
694
|
export type $partial = {
|
|
691
695
|
"~~partial": true;
|
|
@@ -702,6 +706,8 @@ export interface $ZodMapDef<Key extends SomeType = $ZodType, Value extends SomeT
|
|
|
702
706
|
export interface $ZodMapInternals<Key extends SomeType = $ZodType, Value extends SomeType = $ZodType> extends $ZodTypeInternals<Map<core.output<Key>, core.output<Value>>, Map<core.input<Key>, core.input<Value>>> {
|
|
703
707
|
def: $ZodMapDef<Key, Value>;
|
|
704
708
|
isst: errors.$ZodIssueInvalidType | errors.$ZodIssueInvalidKey | errors.$ZodIssueInvalidElement<unknown>;
|
|
709
|
+
optin?: "optional" | undefined;
|
|
710
|
+
optout?: "optional" | undefined;
|
|
705
711
|
}
|
|
706
712
|
export interface $ZodMap<Key extends SomeType = $ZodType, Value extends SomeType = $ZodType> extends $ZodType {
|
|
707
713
|
_zod: $ZodMapInternals<Key, Value>;
|
|
@@ -714,6 +720,8 @@ export interface $ZodSetDef<T extends SomeType = $ZodType> extends $ZodTypeDef {
|
|
|
714
720
|
export interface $ZodSetInternals<T extends SomeType = $ZodType> extends $ZodTypeInternals<Set<core.output<T>>, Set<core.input<T>>> {
|
|
715
721
|
def: $ZodSetDef<T>;
|
|
716
722
|
isst: errors.$ZodIssueInvalidType;
|
|
723
|
+
optin?: "optional" | undefined;
|
|
724
|
+
optout?: "optional" | undefined;
|
|
717
725
|
}
|
|
718
726
|
export interface $ZodSet<T extends SomeType = $ZodType> extends $ZodType {
|
|
719
727
|
_zod: $ZodSetInternals<T>;
|
|
@@ -826,6 +834,7 @@ export interface $ZodDefaultDef<T extends SomeType = $ZodType> extends $ZodTypeD
|
|
|
826
834
|
export interface $ZodDefaultInternals<T extends SomeType = $ZodType> extends $ZodTypeInternals<util.NoUndefined<core.output<T>>, core.input<T> | undefined> {
|
|
827
835
|
def: $ZodDefaultDef<T>;
|
|
828
836
|
optin: "optional";
|
|
837
|
+
optout?: "optional" | undefined;
|
|
829
838
|
isst: never;
|
|
830
839
|
values: T["_zod"]["values"];
|
|
831
840
|
}
|
|
@@ -842,6 +851,7 @@ export interface $ZodPrefaultDef<T extends SomeType = $ZodType> extends $ZodType
|
|
|
842
851
|
export interface $ZodPrefaultInternals<T extends SomeType = $ZodType> extends $ZodTypeInternals<util.NoUndefined<core.output<T>>, core.input<T> | undefined> {
|
|
843
852
|
def: $ZodPrefaultDef<T>;
|
|
844
853
|
optin: "optional";
|
|
854
|
+
optout?: "optional" | undefined;
|
|
845
855
|
isst: never;
|
|
846
856
|
values: T["_zod"]["values"];
|
|
847
857
|
}
|
|
@@ -857,6 +867,8 @@ export interface $ZodNonOptionalInternals<T extends SomeType = $ZodType> extends
|
|
|
857
867
|
def: $ZodNonOptionalDef<T>;
|
|
858
868
|
isst: errors.$ZodIssueInvalidType;
|
|
859
869
|
values: T["_zod"]["values"];
|
|
870
|
+
optin: "optional" | undefined;
|
|
871
|
+
optout: "optional" | undefined;
|
|
860
872
|
}
|
|
861
873
|
export interface $ZodNonOptional<T extends SomeType = $ZodType> extends $ZodType {
|
|
862
874
|
_zod: $ZodNonOptionalInternals<T>;
|
|
@@ -869,6 +881,8 @@ export interface $ZodSuccessDef<T extends SomeType = $ZodType> extends $ZodTypeD
|
|
|
869
881
|
export interface $ZodSuccessInternals<T extends SomeType = $ZodType> extends $ZodTypeInternals<boolean, core.input<T>> {
|
|
870
882
|
def: $ZodSuccessDef<T>;
|
|
871
883
|
isst: never;
|
|
884
|
+
optin: T["_zod"]["optin"];
|
|
885
|
+
optout: "optional" | undefined;
|
|
872
886
|
}
|
|
873
887
|
export interface $ZodSuccess<T extends SomeType = $ZodType> extends $ZodType {
|
|
874
888
|
_zod: $ZodSuccessInternals<T>;
|
package/v4/core/schemas.js
CHANGED
|
@@ -35,8 +35,8 @@ export const $ZodType = /*@__PURE__*/ core.$constructor("$ZodType", (inst, def)
|
|
|
35
35
|
let isAborted = util.aborted(payload);
|
|
36
36
|
let asyncResult;
|
|
37
37
|
for (const ch of checks) {
|
|
38
|
-
if (ch._zod.when) {
|
|
39
|
-
const shouldRun = ch._zod.when(payload);
|
|
38
|
+
if (ch._zod.def.when) {
|
|
39
|
+
const shouldRun = ch._zod.def.when(payload);
|
|
40
40
|
if (!shouldRun)
|
|
41
41
|
continue;
|
|
42
42
|
}
|
|
@@ -151,9 +151,10 @@ class JSONSchemaGenerator {
|
|
|
151
151
|
case "unknown": {
|
|
152
152
|
break;
|
|
153
153
|
}
|
|
154
|
-
case "undefined":
|
|
155
|
-
|
|
156
|
-
|
|
154
|
+
case "undefined": {
|
|
155
|
+
if (this.unrepresentable === "throw") {
|
|
156
|
+
throw new Error("Undefined cannot be represented in JSON Schema");
|
|
157
|
+
}
|
|
157
158
|
break;
|
|
158
159
|
}
|
|
159
160
|
case "void": {
|
|
@@ -162,6 +163,10 @@ class JSONSchemaGenerator {
|
|
|
162
163
|
}
|
|
163
164
|
break;
|
|
164
165
|
}
|
|
166
|
+
case "never": {
|
|
167
|
+
_json.not = {};
|
|
168
|
+
break;
|
|
169
|
+
}
|
|
165
170
|
case "date": {
|
|
166
171
|
if (this.unrepresentable === "throw") {
|
|
167
172
|
throw new Error("Date cannot be represented in JSON Schema");
|
|
@@ -531,6 +536,8 @@ class JSONSchemaGenerator {
|
|
|
531
536
|
throw new Error("Unprocessed schema. This is a bug in Zod.");
|
|
532
537
|
// initialize result with root schema fields
|
|
533
538
|
// Object.assign(result, seen.cached);
|
|
539
|
+
// returns a ref to the schema
|
|
540
|
+
// defId will be empty if the ref points to an external schema (or #)
|
|
534
541
|
const makeURI = (entry) => {
|
|
535
542
|
// comparing the seen objects because sometimes
|
|
536
543
|
// multiple schemas map to the same seen object.
|
|
@@ -540,12 +547,14 @@ class JSONSchemaGenerator {
|
|
|
540
547
|
if (params.external) {
|
|
541
548
|
const externalId = params.external.registry.get(entry[0])?.id; // ?? "__shared";// `__schema${this.counter++}`;
|
|
542
549
|
// check if schema is in the external registry
|
|
543
|
-
|
|
544
|
-
|
|
550
|
+
const uriGenerator = params.external.uri ?? ((id) => id);
|
|
551
|
+
if (externalId) {
|
|
552
|
+
return { ref: uriGenerator(externalId) };
|
|
553
|
+
}
|
|
545
554
|
// otherwise, add to __shared
|
|
546
555
|
const id = entry[1].defId ?? entry[1].schema.id ?? `schema${this.counter++}`;
|
|
547
|
-
entry[1].defId = id;
|
|
548
|
-
return { defId: id, ref: `${
|
|
556
|
+
entry[1].defId = id; // set defId so it will be reused if needed
|
|
557
|
+
return { defId: id, ref: `${uriGenerator("__shared")}#/${defsSegment}/${id}` };
|
|
549
558
|
}
|
|
550
559
|
if (entry[1] === root) {
|
|
551
560
|
return { ref: "#" };
|
|
@@ -559,6 +568,7 @@ class JSONSchemaGenerator {
|
|
|
559
568
|
// stored cached version in `def` property
|
|
560
569
|
// remove all properties, set $ref
|
|
561
570
|
const extractToDef = (entry) => {
|
|
571
|
+
// if the schema is already a reference, do not extract it
|
|
562
572
|
if (entry[1].schema.$ref) {
|
|
563
573
|
return;
|
|
564
574
|
}
|
|
@@ -575,14 +585,24 @@ class JSONSchemaGenerator {
|
|
|
575
585
|
}
|
|
576
586
|
schema.$ref = ref;
|
|
577
587
|
};
|
|
588
|
+
// throw on cycles
|
|
589
|
+
// break cycles
|
|
590
|
+
if (params.cycles === "throw") {
|
|
591
|
+
for (const entry of this.seen.entries()) {
|
|
592
|
+
const seen = entry[1];
|
|
593
|
+
if (seen.cycle) {
|
|
594
|
+
throw new Error("Cycle detected: " +
|
|
595
|
+
`#/${seen.cycle?.join("/")}/<root>` +
|
|
596
|
+
'\n\nSet the `cycles` parameter to `"ref"` to resolve cyclical schemas with defs.');
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
}
|
|
578
600
|
// extract schemas into $defs
|
|
579
601
|
for (const entry of this.seen.entries()) {
|
|
580
602
|
const seen = entry[1];
|
|
581
603
|
// convert root schema to # $ref
|
|
582
|
-
// also prevents root schema from being extracted
|
|
583
604
|
if (schema === entry[0]) {
|
|
584
|
-
//
|
|
585
|
-
extractToDef(entry);
|
|
605
|
+
extractToDef(entry); // this has special handling for the root schema
|
|
586
606
|
continue;
|
|
587
607
|
}
|
|
588
608
|
// extract schemas that are in the external registry
|
|
@@ -601,14 +621,8 @@ class JSONSchemaGenerator {
|
|
|
601
621
|
}
|
|
602
622
|
// break cycles
|
|
603
623
|
if (seen.cycle) {
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
`#/${seen.cycle?.join("/")}/<root>` +
|
|
607
|
-
'\n\nSet the `cycles` parameter to `"ref"` to resolve cyclical schemas with defs.');
|
|
608
|
-
}
|
|
609
|
-
else if (params.cycles === "ref") {
|
|
610
|
-
extractToDef(entry);
|
|
611
|
-
}
|
|
624
|
+
// any
|
|
625
|
+
extractToDef(entry);
|
|
612
626
|
continue;
|
|
613
627
|
}
|
|
614
628
|
// extract reused schemas
|
|
@@ -666,6 +680,12 @@ class JSONSchemaGenerator {
|
|
|
666
680
|
else {
|
|
667
681
|
console.warn(`Invalid target: ${this.target}`);
|
|
668
682
|
}
|
|
683
|
+
if (params.external?.uri) {
|
|
684
|
+
const id = params.external.registry.get(schema)?.id;
|
|
685
|
+
if (!id)
|
|
686
|
+
throw new Error("Schema is missing an `id` property");
|
|
687
|
+
result.$id = params.external.uri(id);
|
|
688
|
+
}
|
|
669
689
|
Object.assign(result, root.def);
|
|
670
690
|
// build defs object
|
|
671
691
|
const defs = params.external?.defs ?? {};
|
|
@@ -676,12 +696,16 @@ class JSONSchemaGenerator {
|
|
|
676
696
|
}
|
|
677
697
|
}
|
|
678
698
|
// set definitions in result
|
|
679
|
-
if (
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
699
|
+
if (params.external) {
|
|
700
|
+
}
|
|
701
|
+
else {
|
|
702
|
+
if (Object.keys(defs).length > 0) {
|
|
703
|
+
if (this.target === "draft-2020-12") {
|
|
704
|
+
result.$defs = defs;
|
|
705
|
+
}
|
|
706
|
+
else {
|
|
707
|
+
result.definitions = defs;
|
|
708
|
+
}
|
|
685
709
|
}
|
|
686
710
|
}
|
|
687
711
|
try {
|
|
@@ -707,7 +731,7 @@ function toJSONSchema(input, _params) {
|
|
|
707
731
|
const schemas = {};
|
|
708
732
|
const external = {
|
|
709
733
|
registry: input,
|
|
710
|
-
uri: _params?.uri
|
|
734
|
+
uri: _params?.uri,
|
|
711
735
|
defs,
|
|
712
736
|
};
|
|
713
737
|
for (const entry of input._idmap.entries()) {
|
|
@@ -147,9 +147,10 @@ export class JSONSchemaGenerator {
|
|
|
147
147
|
case "unknown": {
|
|
148
148
|
break;
|
|
149
149
|
}
|
|
150
|
-
case "undefined":
|
|
151
|
-
|
|
152
|
-
|
|
150
|
+
case "undefined": {
|
|
151
|
+
if (this.unrepresentable === "throw") {
|
|
152
|
+
throw new Error("Undefined cannot be represented in JSON Schema");
|
|
153
|
+
}
|
|
153
154
|
break;
|
|
154
155
|
}
|
|
155
156
|
case "void": {
|
|
@@ -158,6 +159,10 @@ export class JSONSchemaGenerator {
|
|
|
158
159
|
}
|
|
159
160
|
break;
|
|
160
161
|
}
|
|
162
|
+
case "never": {
|
|
163
|
+
_json.not = {};
|
|
164
|
+
break;
|
|
165
|
+
}
|
|
161
166
|
case "date": {
|
|
162
167
|
if (this.unrepresentable === "throw") {
|
|
163
168
|
throw new Error("Date cannot be represented in JSON Schema");
|
|
@@ -527,6 +532,8 @@ export class JSONSchemaGenerator {
|
|
|
527
532
|
throw new Error("Unprocessed schema. This is a bug in Zod.");
|
|
528
533
|
// initialize result with root schema fields
|
|
529
534
|
// Object.assign(result, seen.cached);
|
|
535
|
+
// returns a ref to the schema
|
|
536
|
+
// defId will be empty if the ref points to an external schema (or #)
|
|
530
537
|
const makeURI = (entry) => {
|
|
531
538
|
// comparing the seen objects because sometimes
|
|
532
539
|
// multiple schemas map to the same seen object.
|
|
@@ -536,12 +543,14 @@ export class JSONSchemaGenerator {
|
|
|
536
543
|
if (params.external) {
|
|
537
544
|
const externalId = params.external.registry.get(entry[0])?.id; // ?? "__shared";// `__schema${this.counter++}`;
|
|
538
545
|
// check if schema is in the external registry
|
|
539
|
-
|
|
540
|
-
|
|
546
|
+
const uriGenerator = params.external.uri ?? ((id) => id);
|
|
547
|
+
if (externalId) {
|
|
548
|
+
return { ref: uriGenerator(externalId) };
|
|
549
|
+
}
|
|
541
550
|
// otherwise, add to __shared
|
|
542
551
|
const id = entry[1].defId ?? entry[1].schema.id ?? `schema${this.counter++}`;
|
|
543
|
-
entry[1].defId = id;
|
|
544
|
-
return { defId: id, ref: `${
|
|
552
|
+
entry[1].defId = id; // set defId so it will be reused if needed
|
|
553
|
+
return { defId: id, ref: `${uriGenerator("__shared")}#/${defsSegment}/${id}` };
|
|
545
554
|
}
|
|
546
555
|
if (entry[1] === root) {
|
|
547
556
|
return { ref: "#" };
|
|
@@ -555,6 +564,7 @@ export class JSONSchemaGenerator {
|
|
|
555
564
|
// stored cached version in `def` property
|
|
556
565
|
// remove all properties, set $ref
|
|
557
566
|
const extractToDef = (entry) => {
|
|
567
|
+
// if the schema is already a reference, do not extract it
|
|
558
568
|
if (entry[1].schema.$ref) {
|
|
559
569
|
return;
|
|
560
570
|
}
|
|
@@ -571,14 +581,24 @@ export class JSONSchemaGenerator {
|
|
|
571
581
|
}
|
|
572
582
|
schema.$ref = ref;
|
|
573
583
|
};
|
|
584
|
+
// throw on cycles
|
|
585
|
+
// break cycles
|
|
586
|
+
if (params.cycles === "throw") {
|
|
587
|
+
for (const entry of this.seen.entries()) {
|
|
588
|
+
const seen = entry[1];
|
|
589
|
+
if (seen.cycle) {
|
|
590
|
+
throw new Error("Cycle detected: " +
|
|
591
|
+
`#/${seen.cycle?.join("/")}/<root>` +
|
|
592
|
+
'\n\nSet the `cycles` parameter to `"ref"` to resolve cyclical schemas with defs.');
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
}
|
|
574
596
|
// extract schemas into $defs
|
|
575
597
|
for (const entry of this.seen.entries()) {
|
|
576
598
|
const seen = entry[1];
|
|
577
599
|
// convert root schema to # $ref
|
|
578
|
-
// also prevents root schema from being extracted
|
|
579
600
|
if (schema === entry[0]) {
|
|
580
|
-
//
|
|
581
|
-
extractToDef(entry);
|
|
601
|
+
extractToDef(entry); // this has special handling for the root schema
|
|
582
602
|
continue;
|
|
583
603
|
}
|
|
584
604
|
// extract schemas that are in the external registry
|
|
@@ -597,14 +617,8 @@ export class JSONSchemaGenerator {
|
|
|
597
617
|
}
|
|
598
618
|
// break cycles
|
|
599
619
|
if (seen.cycle) {
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
`#/${seen.cycle?.join("/")}/<root>` +
|
|
603
|
-
'\n\nSet the `cycles` parameter to `"ref"` to resolve cyclical schemas with defs.');
|
|
604
|
-
}
|
|
605
|
-
else if (params.cycles === "ref") {
|
|
606
|
-
extractToDef(entry);
|
|
607
|
-
}
|
|
620
|
+
// any
|
|
621
|
+
extractToDef(entry);
|
|
608
622
|
continue;
|
|
609
623
|
}
|
|
610
624
|
// extract reused schemas
|
|
@@ -662,6 +676,12 @@ export class JSONSchemaGenerator {
|
|
|
662
676
|
else {
|
|
663
677
|
console.warn(`Invalid target: ${this.target}`);
|
|
664
678
|
}
|
|
679
|
+
if (params.external?.uri) {
|
|
680
|
+
const id = params.external.registry.get(schema)?.id;
|
|
681
|
+
if (!id)
|
|
682
|
+
throw new Error("Schema is missing an `id` property");
|
|
683
|
+
result.$id = params.external.uri(id);
|
|
684
|
+
}
|
|
665
685
|
Object.assign(result, root.def);
|
|
666
686
|
// build defs object
|
|
667
687
|
const defs = params.external?.defs ?? {};
|
|
@@ -672,12 +692,16 @@ export class JSONSchemaGenerator {
|
|
|
672
692
|
}
|
|
673
693
|
}
|
|
674
694
|
// set definitions in result
|
|
675
|
-
if (
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
695
|
+
if (params.external) {
|
|
696
|
+
}
|
|
697
|
+
else {
|
|
698
|
+
if (Object.keys(defs).length > 0) {
|
|
699
|
+
if (this.target === "draft-2020-12") {
|
|
700
|
+
result.$defs = defs;
|
|
701
|
+
}
|
|
702
|
+
else {
|
|
703
|
+
result.definitions = defs;
|
|
704
|
+
}
|
|
681
705
|
}
|
|
682
706
|
}
|
|
683
707
|
try {
|
|
@@ -702,7 +726,7 @@ export function toJSONSchema(input, _params) {
|
|
|
702
726
|
const schemas = {};
|
|
703
727
|
const external = {
|
|
704
728
|
registry: input,
|
|
705
|
-
uri: _params?.uri
|
|
729
|
+
uri: _params?.uri,
|
|
706
730
|
defs,
|
|
707
731
|
};
|
|
708
732
|
for (const entry of input._idmap.entries()) {
|