zod 3.26.0-canary.20250707T201657 → 3.26.0-canary.20250708T225111
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/error-utils.test.ts +27 -2
- 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 +42 -3
- package/src/v4/core/api.ts +2 -0
- package/src/v4/core/checks.ts +8 -10
- package/src/v4/core/errors.ts +13 -7
- package/src/v4/core/registries.ts +7 -1
- package/src/v4/core/schemas.ts +4 -4
- package/src/v4/core/to-json-schema.ts +44 -23
- 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.d.cts +3 -1
- package/v4/core/errors.d.ts +3 -1
- package/v4/core/errors.js +4 -0
- package/v4/core/registries.cjs +6 -1
- package/v4/core/registries.d.cts +2 -1
- package/v4/core/registries.d.ts +2 -1
- package/v4/core/registries.js +6 -1
- package/v4/core/schemas.cjs +2 -2
- package/v4/core/schemas.js +2 -2
- package/v4/core/to-json-schema.cjs +41 -22
- 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 +41 -22
|
@@ -532,6 +532,8 @@ export class JSONSchemaGenerator {
|
|
|
532
532
|
throw new Error("Unprocessed schema. This is a bug in Zod.");
|
|
533
533
|
// initialize result with root schema fields
|
|
534
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 #)
|
|
535
537
|
const makeURI = (entry) => {
|
|
536
538
|
// comparing the seen objects because sometimes
|
|
537
539
|
// multiple schemas map to the same seen object.
|
|
@@ -541,12 +543,14 @@ export class JSONSchemaGenerator {
|
|
|
541
543
|
if (params.external) {
|
|
542
544
|
const externalId = params.external.registry.get(entry[0])?.id; // ?? "__shared";// `__schema${this.counter++}`;
|
|
543
545
|
// check if schema is in the external registry
|
|
544
|
-
|
|
545
|
-
|
|
546
|
+
const uriGenerator = params.external.uri ?? ((id) => id);
|
|
547
|
+
if (externalId) {
|
|
548
|
+
return { ref: uriGenerator(externalId) };
|
|
549
|
+
}
|
|
546
550
|
// otherwise, add to __shared
|
|
547
551
|
const id = entry[1].defId ?? entry[1].schema.id ?? `schema${this.counter++}`;
|
|
548
|
-
entry[1].defId = id;
|
|
549
|
-
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}` };
|
|
550
554
|
}
|
|
551
555
|
if (entry[1] === root) {
|
|
552
556
|
return { ref: "#" };
|
|
@@ -560,6 +564,7 @@ export class JSONSchemaGenerator {
|
|
|
560
564
|
// stored cached version in `def` property
|
|
561
565
|
// remove all properties, set $ref
|
|
562
566
|
const extractToDef = (entry) => {
|
|
567
|
+
// if the schema is already a reference, do not extract it
|
|
563
568
|
if (entry[1].schema.$ref) {
|
|
564
569
|
return;
|
|
565
570
|
}
|
|
@@ -576,14 +581,24 @@ export class JSONSchemaGenerator {
|
|
|
576
581
|
}
|
|
577
582
|
schema.$ref = ref;
|
|
578
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
|
+
}
|
|
579
596
|
// extract schemas into $defs
|
|
580
597
|
for (const entry of this.seen.entries()) {
|
|
581
598
|
const seen = entry[1];
|
|
582
599
|
// convert root schema to # $ref
|
|
583
|
-
// also prevents root schema from being extracted
|
|
584
600
|
if (schema === entry[0]) {
|
|
585
|
-
//
|
|
586
|
-
extractToDef(entry);
|
|
601
|
+
extractToDef(entry); // this has special handling for the root schema
|
|
587
602
|
continue;
|
|
588
603
|
}
|
|
589
604
|
// extract schemas that are in the external registry
|
|
@@ -602,14 +617,8 @@ export class JSONSchemaGenerator {
|
|
|
602
617
|
}
|
|
603
618
|
// break cycles
|
|
604
619
|
if (seen.cycle) {
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
`#/${seen.cycle?.join("/")}/<root>` +
|
|
608
|
-
'\n\nSet the `cycles` parameter to `"ref"` to resolve cyclical schemas with defs.');
|
|
609
|
-
}
|
|
610
|
-
else if (params.cycles === "ref") {
|
|
611
|
-
extractToDef(entry);
|
|
612
|
-
}
|
|
620
|
+
// any
|
|
621
|
+
extractToDef(entry);
|
|
613
622
|
continue;
|
|
614
623
|
}
|
|
615
624
|
// extract reused schemas
|
|
@@ -667,6 +676,12 @@ export class JSONSchemaGenerator {
|
|
|
667
676
|
else {
|
|
668
677
|
console.warn(`Invalid target: ${this.target}`);
|
|
669
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
|
+
}
|
|
670
685
|
Object.assign(result, root.def);
|
|
671
686
|
// build defs object
|
|
672
687
|
const defs = params.external?.defs ?? {};
|
|
@@ -677,12 +692,16 @@ export class JSONSchemaGenerator {
|
|
|
677
692
|
}
|
|
678
693
|
}
|
|
679
694
|
// set definitions in result
|
|
680
|
-
if (
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
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
|
+
}
|
|
686
705
|
}
|
|
687
706
|
}
|
|
688
707
|
try {
|
|
@@ -707,7 +726,7 @@ export function toJSONSchema(input, _params) {
|
|
|
707
726
|
const schemas = {};
|
|
708
727
|
const external = {
|
|
709
728
|
registry: input,
|
|
710
|
-
uri: _params?.uri
|
|
729
|
+
uri: _params?.uri,
|
|
711
730
|
defs,
|
|
712
731
|
};
|
|
713
732
|
for (const entry of input._idmap.entries()) {
|