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.
@@ -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
- if (externalId)
545
- return { ref: params.external.uri(externalId) };
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: `${params.external.uri("__shared")}#/${defsSegment}/${id}` };
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
- // do not copy to defs...this is the root schema
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
- if (params.cycles === "throw") {
606
- throw new Error("Cycle detected: " +
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 (!params.external && Object.keys(defs).length > 0) {
681
- if (this.target === "draft-2020-12") {
682
- result.$defs = defs;
683
- }
684
- else {
685
- result.definitions = defs;
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 || ((id) => id),
729
+ uri: _params?.uri,
711
730
  defs,
712
731
  };
713
732
  for (const entry of input._idmap.entries()) {