@kubb/plugin-zod 5.0.0-beta.80 → 5.0.0-beta.84

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/dist/index.js CHANGED
@@ -1,8 +1,7 @@
1
1
  import { t as __name } from "./rolldown-runtime-C0LytTxp.js";
2
- import { ast, defineGenerator, definePlugin, defineResolver } from "@kubb/core";
3
- import { Const, File, Type, jsxRenderer } from "@kubb/renderer-jsx";
4
- import { Fragment, jsx, jsxs } from "@kubb/renderer-jsx/jsx-runtime";
5
- import { buildList, buildObject, containsCircularRef, extractRefName, lazyGetter, mapSchemaItems, mapSchemaMembers, mapSchemaProperties, objectKey, stringify, syncSchemaRef, toRegExpString } from "@kubb/ast/utils";
2
+ import { ast, defineGenerator, definePlugin, defineResolver } from "kubb/kit";
3
+ import { Const, File, Type, jsxRenderer } from "kubb/jsx";
4
+ import { Fragment, jsx, jsxs } from "kubb/jsx/jsx-runtime";
6
5
  //#region ../../internals/utils/src/casing.ts
7
6
  /**
8
7
  * Shared implementation for camelCase and PascalCase conversion.
@@ -386,12 +385,12 @@ function containsCodec(node, seen = /* @__PURE__ */ new Set()) {
386
385
  if (hasCodec(node)) return true;
387
386
  if (node.type === "ref") {
388
387
  if (!node.ref) return false;
389
- const refName = extractRefName(node.ref);
388
+ const refName = ast.extractRefName(node.ref);
390
389
  if (refName) {
391
390
  if (seen.has(refName)) return false;
392
391
  seen.add(refName);
393
392
  }
394
- const resolved = syncSchemaRef(node);
393
+ const resolved = ast.syncSchemaRef(node);
395
394
  if (resolved.type === "ref") return false;
396
395
  return containsCodec(resolved, seen);
397
396
  }
@@ -407,14 +406,54 @@ function containsCodec(node, seen = /* @__PURE__ */ new Set()) {
407
406
  * them to their input (encode) variant.
408
407
  */
409
408
  function collectCodecRefNames(node) {
410
- return ast.collect(node, { schema: (n) => n.type === "ref" && n.ref && containsCodec(n) ? extractRefName(n.ref) ?? void 0 : void 0 });
409
+ return ast.collect(node, { schema: (n) => n.type === "ref" && n.ref && containsCodec(n) ? ast.extractRefName(n.ref) ?? void 0 : void 0 });
410
+ }
411
+ /**
412
+ * Whether the node is a plain inline object whose shape can be lifted into an `.extend({ … })`
413
+ * argument. A catchall, `patternProperties`, or a nullable/optional wrapper cannot, so those stay
414
+ * on `.and(…)`.
415
+ */
416
+ function isPlainInlineObject(node) {
417
+ return node.type === "object" && !node.nullable && !node.optional && !node.nullish && node.additionalProperties === void 0 && !node.patternProperties;
418
+ }
419
+ /**
420
+ * Whether a node renders as a bare Zod object — one that accepts `.extend(…)` and can be a
421
+ * `z.discriminatedUnion` option. Covers object nodes, `$ref`s that resolve to (or are still
422
+ * unresolved) objects, single-member unions of an object, and object-composable `allOf`.
423
+ *
424
+ * `cyclicSchemas` bounds the recursion: a ref into a cycle renders as `z.lazy(…)`, not an object.
425
+ */
426
+ function isObjectSchemaNode(node, cyclicSchemas) {
427
+ if (node.nullable || node.optional || node.nullish) return false;
428
+ if (node.type === "object") return true;
429
+ if (node.type === "ref") {
430
+ const refName = (node.ref ? ast.extractRefName(node.ref) : void 0) ?? node.name;
431
+ if (refName && cyclicSchemas?.has(refName)) return false;
432
+ const resolved = ast.syncSchemaRef(node);
433
+ return resolved.type === "ref" || isObjectSchemaNode(resolved, cyclicSchemas);
434
+ }
435
+ if (node.type === "union") {
436
+ const members = node.members ?? [];
437
+ return members.length === 1 && isObjectSchemaNode(members[0], cyclicSchemas);
438
+ }
439
+ return isObjectComposableIntersection(node, cyclicSchemas);
440
+ }
441
+ /**
442
+ * Whether an `allOf` is a pure object composition — an object base plus inline object members whose
443
+ * shapes merge with `.extend(…)`. These stay a Zod object instead of a `ZodIntersection`, which
444
+ * `z.discriminatedUnion` rejects.
445
+ */
446
+ function isObjectComposableIntersection(node, cyclicSchemas) {
447
+ if (node.type !== "intersection") return false;
448
+ const [first, ...rest] = node.members ?? [];
449
+ return !!first && isObjectSchemaNode(first, cyclicSchemas) && rest.every(isPlainInlineObject);
411
450
  }
412
451
  /**
413
452
  * Format a default value as a code-level literal.
414
453
  * Objects become `{}`, primitives become their string representation, strings are quoted.
415
454
  */
416
455
  function formatDefault(value) {
417
- if (typeof value === "string") return stringify(value);
456
+ if (typeof value === "string") return ast.stringify(value);
418
457
  if (typeof value === "object" && value !== null) return "{}";
419
458
  return String(value ?? "");
420
459
  }
@@ -450,7 +489,7 @@ function defaultLiteral(node, value) {
450
489
  * Strings are quoted; numbers and booleans are emitted raw.
451
490
  */
452
491
  function formatLiteral(v) {
453
- if (typeof v === "string") return stringify(v);
492
+ if (typeof v === "string") return ast.stringify(v);
454
493
  return String(v);
455
494
  }
456
495
  /**
@@ -492,7 +531,8 @@ function patternKeySchemaMini({ patterns, regexType }) {
492
531
  })}))`;
493
532
  }
494
533
  function patternKeySource({ patterns, regexType }) {
495
- return toRegExpString(patterns.length === 1 ? patterns[0] : patterns.map((pattern) => `(${pattern})`).join("|"), regexFunc(regexType));
534
+ const source = patterns.length === 1 ? patterns[0] : patterns.map((pattern) => `(${pattern})`).join("|");
535
+ return ast.toRegExpString(source, regexFunc(regexType));
496
536
  }
497
537
  /**
498
538
  * Build `.min()` / `.max()` / `.gt()` / `.lt()` constraint chains for numbers
@@ -515,7 +555,7 @@ function lengthConstraints({ min, max, pattern, regexType }) {
515
555
  return [
516
556
  min !== void 0 ? `.min(${min})` : "",
517
557
  max !== void 0 ? `.max(${max})` : "",
518
- pattern !== void 0 ? `.regex(${toRegExpString(pattern, regexFunc(regexType))})` : ""
558
+ pattern !== void 0 ? `.regex(${ast.toRegExpString(pattern, regexFunc(regexType))})` : ""
519
559
  ].join("");
520
560
  }
521
561
  /**
@@ -537,7 +577,7 @@ function lengthChecksMini({ min, max, pattern, regexType }) {
537
577
  const checks = [];
538
578
  if (min !== void 0) checks.push(`z.minLength(${min})`);
539
579
  if (max !== void 0) checks.push(`z.maxLength(${max})`);
540
- if (pattern !== void 0) checks.push(`z.regex(${toRegExpString(pattern, regexFunc(regexType))})`);
580
+ if (pattern !== void 0) checks.push(`z.regex(${ast.toRegExpString(pattern, regexFunc(regexType))})`);
541
581
  return checks.length ? `.check(${checks.join(", ")})` : "";
542
582
  }
543
583
  /**
@@ -553,7 +593,7 @@ function applyModifiers({ value, schema, nullable, optional, nullish, defaultVal
553
593
  })();
554
594
  const literal = defaultValue !== void 0 ? defaultLiteral(schema, defaultValue) : null;
555
595
  const withDefault = literal !== null ? `${withModifier}.default(${literal})` : withModifier;
556
- const withDescription = description ? `${withDefault}.describe(${stringify(description)})` : withDefault;
596
+ const withDescription = description ? `${withDefault}.describe(${ast.stringify(description)})` : withDefault;
557
597
  return examples?.length ? `${withDescription}.meta({ examples: [${examples.map(formatDefault).join(", ")}] })` : withDescription;
558
598
  }
559
599
  function modifierDepth(schema) {
@@ -596,9 +636,9 @@ function strictOneOfMember$1(member, node, cyclicSchemas) {
596
636
  if (node.type === "object" && node.additionalProperties === void 0) return `${member}.strict()`;
597
637
  if (node.type === "ref") {
598
638
  if (member.startsWith("z.lazy(")) return member;
599
- const refName = (node.ref ? extractRefName(node.ref) : void 0) ?? node.name;
639
+ const refName = (node.ref ? ast.extractRefName(node.ref) : void 0) ?? node.name;
600
640
  if (refName && cyclicSchemas?.has(refName)) return member;
601
- const schema = syncSchemaRef(node);
641
+ const schema = ast.syncSchemaRef(node);
602
642
  if (schema.nullable || schema.optional || node.nullable || node.optional) return member;
603
643
  if (schema.type === "object" && (schema.additionalProperties === void 0 || schema.additionalProperties === false)) return `${member}.strict()`;
604
644
  }
@@ -617,6 +657,42 @@ function getMemberConstraint({ member, regexType }) {
617
657
  }) || void 0;
618
658
  }
619
659
  /**
660
+ * Builds the `{ key: value, … }` shape for an object node, shared by the `z.object(...)` and
661
+ * `.extend(...)` renderings so they stay in lockstep.
662
+ */
663
+ function buildZodObjectShape(ctx, node) {
664
+ const objectNode = ast.narrowSchema(node, "object");
665
+ if (!objectNode) return "{}";
666
+ const isCyclic = (schema) => ctx.options.cyclicSchemas != null && ast.containsCircularRef(schema, { circularSchemas: ctx.options.cyclicSchemas });
667
+ const entries = ast.mapSchemaProperties(objectNode, (schema) => {
668
+ const hasSelfRef = isCyclic(schema);
669
+ const savedCyclicSchemas = ctx.options.cyclicSchemas;
670
+ if (hasSelfRef) ctx.options.cyclicSchemas = void 0;
671
+ const baseOutput = ctx.transform(schema) ?? ctx.transform(ast.factory.createSchema({ type: "unknown" }));
672
+ if (hasSelfRef) ctx.options.cyclicSchemas = savedCyclicSchemas;
673
+ return baseOutput;
674
+ }).map(({ name: propName, property, output: baseOutput }) => {
675
+ const { schema } = property;
676
+ const meta = ast.syncSchemaRef(schema);
677
+ const descriptionToApply = schema.type !== "ref" && meta.type === "ref" ? void 0 : meta.description;
678
+ const value = applyModifiers({
679
+ value: baseOutput,
680
+ schema,
681
+ nullable: meta.nullable,
682
+ optional: schema.optional || property.required === false,
683
+ nullish: schema.nullish,
684
+ defaultValue: meta.default,
685
+ description: descriptionToApply,
686
+ examples: meta.examples
687
+ });
688
+ return isCyclic(schema) ? ast.lazyGetter({
689
+ name: propName,
690
+ body: value
691
+ }) : `${ast.objectKey(propName)}: ${value}`;
692
+ });
693
+ return ast.buildObject(entries);
694
+ }
695
+ /**
620
696
  * Zod v4 printer built with `definePrinter`.
621
697
  *
622
698
  * Converts a `SchemaNode` AST into a Zod v4 code string using the chainable API
@@ -657,7 +733,10 @@ const printerZod = ast.createPrinter((options) => {
657
733
  },
658
734
  date(node) {
659
735
  const codec = getCodec(node);
660
- if (codec) return this.options.direction === "input" ? codec.encode(node) : codec.decode(node);
736
+ if (codec) {
737
+ if (this.options.direction === "input") return codec.encode(node);
738
+ return shouldCoerce(this.options.coercion, "dates") ? "z.coerce.date()" : codec.decode(node);
739
+ }
661
740
  return "z.iso.date()";
662
741
  },
663
742
  datetime(node) {
@@ -703,45 +782,15 @@ const printerZod = ast.createPrinter((options) => {
703
782
  },
704
783
  ref(node) {
705
784
  if (!node.name) return null;
706
- const refName = node.ref ? this.options.nameMapping?.get(node.ref) ?? extractRefName(node.ref) ?? node.name : node.name;
785
+ const refName = node.ref ? this.options.nameMapping?.get(node.ref) ?? ast.extractRefName(node.ref) ?? node.name : node.name;
707
786
  const useInputVariant = node.ref != null && this.options.direction === "input" && containsCodec(node);
708
787
  const resolvedName = node.ref ? useInputVariant ? this.options.resolver?.resolveInputSchemaName(refName) ?? refName : this.options.resolver?.default(refName, "function") ?? refName : node.name;
709
788
  if (node.ref && this.options.cyclicSchemas?.has(refName)) return `z.lazy(() => ${resolvedName})`;
710
789
  return resolvedName;
711
790
  },
712
791
  object(node) {
713
- const isCyclic = (schema) => this.options.cyclicSchemas != null && containsCircularRef(schema, { circularSchemas: this.options.cyclicSchemas });
714
- const entries = mapSchemaProperties(node, (schema) => {
715
- const hasSelfRef = isCyclic(schema);
716
- const savedCyclicSchemas = this.options.cyclicSchemas;
717
- if (hasSelfRef) this.options.cyclicSchemas = void 0;
718
- const baseOutput = this.transform(schema) ?? this.transform(ast.factory.createSchema({ type: "unknown" }));
719
- if (hasSelfRef) this.options.cyclicSchemas = savedCyclicSchemas;
720
- return baseOutput;
721
- }).map(({ name: propName, property, output: baseOutput }) => {
722
- const { schema } = property;
723
- const meta = syncSchemaRef(schema);
724
- const wrappedOutput = this.options.wrapOutput ? this.options.wrapOutput({
725
- output: baseOutput,
726
- schema
727
- }) || baseOutput : baseOutput;
728
- const descriptionToApply = schema.type !== "ref" && meta.type === "ref" ? void 0 : meta.description;
729
- const value = applyModifiers({
730
- value: wrappedOutput,
731
- schema,
732
- nullable: meta.nullable,
733
- optional: schema.optional || property.required === false,
734
- nullish: schema.nullish,
735
- defaultValue: meta.default,
736
- description: descriptionToApply,
737
- examples: meta.examples
738
- });
739
- return isCyclic(schema) ? lazyGetter({
740
- name: propName,
741
- body: value
742
- }) : `${objectKey(propName)}: ${value}`;
743
- });
744
- const objectBase = `z.object(${buildObject(entries)})`;
792
+ const entries = node.properties ?? [];
793
+ const objectBase = `z.object(${buildZodObjectShape(this, node)})`;
745
794
  return (() => {
746
795
  const patterns = node.patternProperties ? Object.entries(node.patternProperties) : [];
747
796
  if (node.additionalProperties && node.additionalProperties !== true) {
@@ -767,23 +816,24 @@ const printerZod = ast.createPrinter((options) => {
767
816
  })();
768
817
  },
769
818
  array(node) {
770
- const base = `z.array(${mapSchemaItems(node, (item) => this.transform(item)).map(({ output }) => output).filter(Boolean).join(", ") || this.transform(ast.factory.createSchema({ type: "unknown" }))})${lengthConstraints({
819
+ const base = `z.array(${ast.mapSchemaItems(node, (item) => this.transform(item)).map(({ output }) => output).filter(Boolean).join(", ") || this.transform(ast.factory.createSchema({ type: "unknown" }))})${lengthConstraints({
771
820
  ...node,
772
821
  regexType: this.options.regexType
773
822
  })}`;
774
823
  return node.unique ? `${base}.refine(items => new Set(items).size === items.length, { message: "Array entries must be unique" })` : base;
775
824
  },
776
825
  tuple(node) {
777
- return `z.tuple(${buildList(mapSchemaItems(node, (item) => this.transform(item)).map(({ output }) => output).filter(Boolean))})`;
826
+ const items = ast.mapSchemaItems(node, (item) => this.transform(item)).map(({ output }) => output).filter(Boolean);
827
+ return `z.tuple(${ast.buildList(items)})`;
778
828
  },
779
829
  union(node) {
780
830
  const nodeMembers = node.members ?? [];
781
- const members = mapSchemaMembers(node, (memberNode) => this.transform(memberNode)).map(({ schema, output }) => output && node.strategy === "one" ? strictOneOfMember$1(output, schema, cyclicSchemaNames) : output).filter(Boolean);
831
+ const members = ast.mapSchemaMembers(node, (memberNode) => this.transform(memberNode)).map(({ schema, output }) => output && node.strategy === "one" ? strictOneOfMember$1(output, schema, cyclicSchemaNames) : output).filter(Boolean);
782
832
  if (members.length === 0) return "";
783
833
  if (members.length === 1) return members[0];
784
- const allDiscriminable = nodeMembers.every((m) => (m.type === "ref" ? syncSchemaRef(m) : m).type !== "intersection");
785
- if (node.discriminatorPropertyName && allDiscriminable) return `z.discriminatedUnion(${stringify(node.discriminatorPropertyName)}, ${buildList(members)})`;
786
- return `z.union(${buildList(members)})`;
834
+ const allDiscriminable = nodeMembers.every((m) => isObjectSchemaNode(m, cyclicSchemaNames));
835
+ if (node.discriminatorPropertyName && allDiscriminable) return `z.discriminatedUnion(${ast.stringify(node.discriminatorPropertyName)}, ${ast.buildList(members)})`;
836
+ return `z.union(${ast.buildList(members)})`;
787
837
  },
788
838
  intersection(node) {
789
839
  const members = node.members ?? [];
@@ -792,6 +842,7 @@ const printerZod = ast.createPrinter((options) => {
792
842
  if (!first) return "";
793
843
  const firstBase = this.transform(first);
794
844
  if (!firstBase) return "";
845
+ if (rest.length > 0 && isObjectComposableIntersection(node, cyclicSchemaNames)) return rest.reduce((acc, member) => `${acc}.extend(${buildZodObjectShape(this, member)})`, firstBase);
795
846
  return rest.reduce((acc, member) => {
796
847
  const constraint = getMemberConstraint({
797
848
  member,
@@ -801,14 +852,14 @@ const printerZod = ast.createPrinter((options) => {
801
852
  const transformed = this.transform(member);
802
853
  return transformed ? `${acc}.and(${transformed})` : acc;
803
854
  }, firstBase);
804
- },
805
- ...options.nodes
855
+ }
806
856
  },
857
+ overrides: options.nodes,
807
858
  print(node) {
808
859
  const { keysToOmit } = this.options;
809
860
  const transformed = this.transform(node);
810
861
  if (!transformed) return null;
811
- const meta = syncSchemaRef(node);
862
+ const meta = ast.syncSchemaRef(node);
812
863
  return applyModifiers({
813
864
  value: (() => {
814
865
  if (!keysToOmit?.length || meta.primitive !== "object" || meta.type === "union" && meta.discriminatorPropertyName) return transformed;
@@ -847,7 +898,40 @@ function getMemberConstraintMini({ member, regexType }) {
847
898
  }) || void 0;
848
899
  }
849
900
  /**
850
- * Zod v4 **Mini** printer built with `definePrinter`.
901
+ * Builds the `{ key: value, … }` shape for an object node with the functional `zod/mini` modifiers,
902
+ * shared by the `z.object(...)` and `z.extend(...)` renderings so they stay in lockstep.
903
+ */
904
+ function buildZodMiniObjectShape(ctx, node) {
905
+ const objectNode = ast.narrowSchema(node, "object");
906
+ if (!objectNode) return "{}";
907
+ const isCyclic = (schema) => ctx.options.cyclicSchemas != null && ast.containsCircularRef(schema, { circularSchemas: ctx.options.cyclicSchemas });
908
+ const entries = ast.mapSchemaProperties(objectNode, (schema) => {
909
+ const hasSelfRef = isCyclic(schema);
910
+ const savedCyclicSchemas = ctx.options.cyclicSchemas;
911
+ if (hasSelfRef) ctx.options.cyclicSchemas = void 0;
912
+ const baseOutput = ctx.transform(schema) ?? ctx.transform(ast.factory.createSchema({ type: "unknown" }));
913
+ if (hasSelfRef) ctx.options.cyclicSchemas = savedCyclicSchemas;
914
+ return baseOutput;
915
+ }).map(({ name: propName, property, output: baseOutput }) => {
916
+ const { schema } = property;
917
+ const meta = ast.syncSchemaRef(schema);
918
+ const value = applyMiniModifiers({
919
+ value: baseOutput,
920
+ schema,
921
+ nullable: meta.nullable,
922
+ optional: schema.optional || property.required === false,
923
+ nullish: schema.nullish,
924
+ defaultValue: meta.default
925
+ });
926
+ return isCyclic(schema) ? ast.lazyGetter({
927
+ name: propName,
928
+ body: value
929
+ }) : `${ast.objectKey(propName)}: ${value}`;
930
+ });
931
+ return ast.buildObject(entries);
932
+ }
933
+ /**
934
+ * Zod v4 Mini printer built with `definePrinter`.
851
935
  *
852
936
  * Converts a `SchemaNode` AST into a Zod v4 code string using the functional API
853
937
  * (`z.optional(z.string())`) for improved tree-shaking. See {@link printerZod} for the chainable API.
@@ -859,6 +943,7 @@ function getMemberConstraintMini({ member, regexType }) {
859
943
  * ```
860
944
  */
861
945
  const printerZodMini = ast.createPrinter((options) => {
946
+ const cyclicSchemaNames = options.cyclicSchemas;
862
947
  return {
863
948
  name: "zod-mini",
864
949
  options,
@@ -927,40 +1012,14 @@ const printerZodMini = ast.createPrinter((options) => {
927
1012
  },
928
1013
  ref(node) {
929
1014
  if (!node.name) return null;
930
- const refName = node.ref ? this.options.nameMapping?.get(node.ref) ?? extractRefName(node.ref) ?? node.name : node.name;
1015
+ const refName = node.ref ? this.options.nameMapping?.get(node.ref) ?? ast.extractRefName(node.ref) ?? node.name : node.name;
931
1016
  const resolvedName = node.ref ? this.options.resolver?.default(refName, "function") ?? refName : node.name;
932
1017
  if (node.ref && this.options.cyclicSchemas?.has(refName)) return `z.lazy(() => ${resolvedName})`;
933
1018
  return resolvedName;
934
1019
  },
935
1020
  object(node) {
936
- const isCyclic = (schema) => this.options.cyclicSchemas != null && containsCircularRef(schema, { circularSchemas: this.options.cyclicSchemas });
937
- const entries = mapSchemaProperties(node, (schema) => {
938
- const hasSelfRef = isCyclic(schema);
939
- const savedCyclicSchemas = this.options.cyclicSchemas;
940
- if (hasSelfRef) this.options.cyclicSchemas = void 0;
941
- const baseOutput = this.transform(schema) ?? this.transform(ast.factory.createSchema({ type: "unknown" }));
942
- if (hasSelfRef) this.options.cyclicSchemas = savedCyclicSchemas;
943
- return baseOutput;
944
- }).map(({ name: propName, property, output: baseOutput }) => {
945
- const { schema } = property;
946
- const meta = syncSchemaRef(schema);
947
- const value = applyMiniModifiers({
948
- value: this.options.wrapOutput ? this.options.wrapOutput({
949
- output: baseOutput,
950
- schema
951
- }) || baseOutput : baseOutput,
952
- schema,
953
- nullable: meta.nullable,
954
- optional: schema.optional || property.required === false,
955
- nullish: schema.nullish,
956
- defaultValue: meta.default
957
- });
958
- return isCyclic(schema) ? lazyGetter({
959
- name: propName,
960
- body: value
961
- }) : `${objectKey(propName)}: ${value}`;
962
- });
963
- const objectBase = `z.object(${buildObject(entries)})`;
1021
+ const entries = node.properties ?? [];
1022
+ const objectBase = `z.object(${buildZodMiniObjectShape(this, node)})`;
964
1023
  const patterns = node.patternProperties ? Object.entries(node.patternProperties) : [];
965
1024
  if (node.additionalProperties && node.additionalProperties !== true) {
966
1025
  const catchallType = this.transform(node.additionalProperties);
@@ -984,23 +1043,24 @@ const printerZodMini = ast.createPrinter((options) => {
984
1043
  return objectBase;
985
1044
  },
986
1045
  array(node) {
987
- const base = `z.array(${mapSchemaItems(node, (item) => this.transform(item)).map(({ output }) => output).filter(Boolean).join(", ") || this.transform(ast.factory.createSchema({ type: "unknown" }))})${lengthChecksMini({
1046
+ const base = `z.array(${ast.mapSchemaItems(node, (item) => this.transform(item)).map(({ output }) => output).filter(Boolean).join(", ") || this.transform(ast.factory.createSchema({ type: "unknown" }))})${lengthChecksMini({
988
1047
  ...node,
989
1048
  regexType: this.options.regexType
990
1049
  })}`;
991
1050
  return node.unique ? `${base}.refine(items => new Set(items).size === items.length, { message: "Array entries must be unique" })` : base;
992
1051
  },
993
1052
  tuple(node) {
994
- return `z.tuple(${buildList(mapSchemaItems(node, (item) => this.transform(item)).map(({ output }) => output).filter(Boolean))})`;
1053
+ const items = ast.mapSchemaItems(node, (item) => this.transform(item)).map(({ output }) => output).filter(Boolean);
1054
+ return `z.tuple(${ast.buildList(items)})`;
995
1055
  },
996
1056
  union(node) {
997
1057
  const nodeMembers = node.members ?? [];
998
- const members = mapSchemaMembers(node, (memberNode) => this.transform(memberNode)).map(({ schema, output }) => output && node.strategy === "one" ? strictOneOfMember(output, schema) : output).filter(Boolean);
1058
+ const members = ast.mapSchemaMembers(node, (memberNode) => this.transform(memberNode)).map(({ schema, output }) => output && node.strategy === "one" ? strictOneOfMember(output, schema) : output).filter(Boolean);
999
1059
  if (members.length === 0) return "";
1000
1060
  if (members.length === 1) return members[0];
1001
- const allDiscriminable = nodeMembers.every((m) => (m.type === "ref" ? syncSchemaRef(m) : m).type !== "intersection");
1002
- if (node.discriminatorPropertyName && allDiscriminable) return `z.discriminatedUnion(${stringify(node.discriminatorPropertyName)}, ${buildList(members)})`;
1003
- return `z.union(${buildList(members)})`;
1061
+ const allDiscriminable = nodeMembers.every((m) => isObjectSchemaNode(m, cyclicSchemaNames));
1062
+ if (node.discriminatorPropertyName && allDiscriminable) return `z.discriminatedUnion(${ast.stringify(node.discriminatorPropertyName)}, ${ast.buildList(members)})`;
1063
+ return `z.union(${ast.buildList(members)})`;
1004
1064
  },
1005
1065
  intersection(node) {
1006
1066
  const members = node.members ?? [];
@@ -1009,6 +1069,7 @@ const printerZodMini = ast.createPrinter((options) => {
1009
1069
  if (!first) return "";
1010
1070
  const firstBase = this.transform(first);
1011
1071
  if (!firstBase) return "";
1072
+ if (rest.length > 0 && isObjectComposableIntersection(node, cyclicSchemaNames)) return rest.reduce((acc, member) => `z.extend(${acc}, ${buildZodMiniObjectShape(this, member)})`, firstBase);
1012
1073
  return rest.reduce((acc, member) => {
1013
1074
  const constraint = getMemberConstraintMini({
1014
1075
  member,
@@ -1018,14 +1079,14 @@ const printerZodMini = ast.createPrinter((options) => {
1018
1079
  const transformed = this.transform(member);
1019
1080
  return transformed ? `z.intersection(${acc}, ${transformed})` : acc;
1020
1081
  }, firstBase);
1021
- },
1022
- ...options.nodes
1082
+ }
1023
1083
  },
1084
+ overrides: options.nodes,
1024
1085
  print(node) {
1025
1086
  const { keysToOmit } = this.options;
1026
1087
  const transformed = this.transform(node);
1027
1088
  if (!transformed) return null;
1028
- const meta = syncSchemaRef(node);
1089
+ const meta = ast.syncSchemaRef(node);
1029
1090
  return applyMiniModifiers({
1030
1091
  value: (() => {
1031
1092
  if (!keysToOmit?.length || meta.primitive !== "object" || meta.type === "union" && meta.discriminatorPropertyName) return transformed;
@@ -1050,12 +1111,12 @@ const zodPrinterCache = /* @__PURE__ */ new WeakMap();
1050
1111
  const zodMiniPrinterCache = /* @__PURE__ */ new WeakMap();
1051
1112
  /**
1052
1113
  * Returns the cached `output`/`input` direction printers for a resolver, building them on
1053
- * first use. The `input` printer encodes `Date → string` for request bodies; `output` decodes
1114
+ * first use. The `input` printer encodes `Date → string` for request bodies, and `output` decodes
1054
1115
  * `string → Date` for responses. Schemas without `dateType: 'date'` fields print identically.
1055
1116
  */
1056
1117
  function getStdPrinters(resolver, params) {
1057
1118
  const cached = zodPrinterCache.get(resolver);
1058
- if (cached && cached.coercion === params.coercion && cached.guidType === params.guidType && cached.regexType === params.regexType && cached.dateType === params.dateType) return {
1119
+ if (cached && cached.coercion === params.coercion && cached.guidType === params.guidType && cached.regexType === params.regexType && cached.dateType === params.dateType && cached.nodes === params.nodes) return {
1059
1120
  output: cached.output,
1060
1121
  input: cached.input
1061
1122
  };
@@ -1077,7 +1138,8 @@ function getStdPrinters(resolver, params) {
1077
1138
  coercion: params.coercion,
1078
1139
  guidType: params.guidType,
1079
1140
  regexType: params.regexType,
1080
- dateType: params.dateType
1141
+ dateType: params.dateType,
1142
+ nodes: params.nodes
1081
1143
  });
1082
1144
  return {
1083
1145
  output,
@@ -1086,7 +1148,7 @@ function getStdPrinters(resolver, params) {
1086
1148
  }
1087
1149
  function getMiniPrinter(resolver, params) {
1088
1150
  const cached = zodMiniPrinterCache.get(resolver);
1089
- if (cached && cached.guidType === params.guidType && cached.regexType === params.regexType) return cached.printer;
1151
+ if (cached && cached.guidType === params.guidType && cached.regexType === params.regexType && cached.nodes === params.nodes) return cached.printer;
1090
1152
  const p = printerZodMini({
1091
1153
  ...params,
1092
1154
  resolver
@@ -1094,7 +1156,8 @@ function getMiniPrinter(resolver, params) {
1094
1156
  zodMiniPrinterCache.set(resolver, {
1095
1157
  printer: p,
1096
1158
  guidType: params.guidType,
1097
- regexType: params.regexType
1159
+ regexType: params.regexType,
1160
+ nodes: params.nodes
1098
1161
  });
1099
1162
  return p;
1100
1163
  }
@@ -1109,7 +1172,7 @@ const zodGenerator = defineGenerator({
1109
1172
  renderer: jsxRenderer,
1110
1173
  schema(node, ctx) {
1111
1174
  const { adapter, config, resolver, root } = ctx;
1112
- const { output, coercion, guidType, regexType, mini, wrapOutput, inferred, importPath, group, printer } = ctx.options;
1175
+ const { output, coercion, guidType, regexType, mini, inferred, importPath, group, printer } = ctx.options;
1113
1176
  const dateType = adapter.options.dateType;
1114
1177
  if (!node.name) return;
1115
1178
  const isZodImport = ZOD_NAMESPACE_IMPORTS.has(importPath);
@@ -1163,7 +1226,6 @@ const zodGenerator = defineGenerator({
1163
1226
  guidType,
1164
1227
  regexType,
1165
1228
  dateType,
1166
- wrapOutput,
1167
1229
  cyclicSchemas,
1168
1230
  nameMapping,
1169
1231
  nodes: printer?.nodes
@@ -1171,7 +1233,6 @@ const zodGenerator = defineGenerator({
1171
1233
  const schemaPrinter = mini ? getMiniPrinter(resolver, {
1172
1234
  guidType,
1173
1235
  regexType,
1174
- wrapOutput,
1175
1236
  cyclicSchemas,
1176
1237
  nameMapping,
1177
1238
  nodes: printer?.nodes
@@ -1231,7 +1292,7 @@ const zodGenerator = defineGenerator({
1231
1292
  operation(node, ctx) {
1232
1293
  if (!ast.isHttpOperationNode(node)) return null;
1233
1294
  const { adapter, config, resolver, root } = ctx;
1234
- const { output, coercion, guidType, regexType, mini, wrapOutput, inferred, importPath, group, printer } = ctx.options;
1295
+ const { output, coercion, guidType, regexType, mini, inferred, importPath, group, printer } = ctx.options;
1235
1296
  const dateType = adapter.options.dateType;
1236
1297
  const isZodImport = ZOD_NAMESPACE_IMPORTS.has(importPath);
1237
1298
  const params = caseParams(node.parameters, "camelcase");
@@ -1265,7 +1326,6 @@ const zodGenerator = defineGenerator({
1265
1326
  const schemaPrinter = mini ? keysToOmit?.length ? printerZodMini({
1266
1327
  guidType,
1267
1328
  regexType,
1268
- wrapOutput,
1269
1329
  resolver,
1270
1330
  keysToOmit,
1271
1331
  cyclicSchemas,
@@ -1274,7 +1334,6 @@ const zodGenerator = defineGenerator({
1274
1334
  }) : getMiniPrinter(resolver, {
1275
1335
  guidType,
1276
1336
  regexType,
1277
- wrapOutput,
1278
1337
  cyclicSchemas,
1279
1338
  nameMapping,
1280
1339
  nodes: printer?.nodes
@@ -1283,7 +1342,6 @@ const zodGenerator = defineGenerator({
1283
1342
  guidType,
1284
1343
  regexType,
1285
1344
  dateType,
1286
- wrapOutput,
1287
1345
  resolver,
1288
1346
  keysToOmit,
1289
1347
  cyclicSchemas,
@@ -1295,7 +1353,6 @@ const zodGenerator = defineGenerator({
1295
1353
  guidType,
1296
1354
  regexType,
1297
1355
  dateType,
1298
- wrapOutput,
1299
1356
  cyclicSchemas,
1300
1357
  nameMapping,
1301
1358
  nodes: printer?.nodes
@@ -1538,7 +1595,7 @@ const pluginZodName = "plugin-zod";
1538
1595
  *
1539
1596
  * @example
1540
1597
  * ```ts
1541
- * import { defineConfig } from 'kubb'
1598
+ * import { defineConfig } from 'kubb/config'
1542
1599
  * import { pluginTs } from '@kubb/plugin-ts'
1543
1600
  * import { pluginZod } from '@kubb/plugin-zod'
1544
1601
  *
@@ -1549,7 +1606,7 @@ const pluginZodName = "plugin-zod";
1549
1606
  * pluginTs(),
1550
1607
  * pluginZod({
1551
1608
  * output: { path: './zod' },
1552
- * typed: true,
1609
+ * inferred: true,
1553
1610
  * }),
1554
1611
  * ],
1555
1612
  * })
@@ -1559,7 +1616,7 @@ const pluginZod = definePlugin((options) => {
1559
1616
  const { output = {
1560
1617
  path: "zod",
1561
1618
  barrel: { type: "named" }
1562
- }, group, exclude = [], include, override = [], typed = false, mini = false, guidType = "uuid", regexType = "literal", importPath = mini ? "zod/mini" : "zod", coercion = false, inferred = false, wrapOutput = void 0, printer, resolver: userResolver, macros: userMacros } = options;
1619
+ }, group, exclude = [], include, override = [], mini = false, guidType = "uuid", regexType = "literal", importPath = mini ? "zod/mini" : "zod", coercion = false, inferred = false, printer, resolver: userResolver, macros: userMacros } = options;
1563
1620
  const groupConfig = createGroupConfig(group);
1564
1621
  return {
1565
1622
  name: pluginZodName,
@@ -1571,14 +1628,12 @@ const pluginZod = definePlugin((options) => {
1571
1628
  include,
1572
1629
  override,
1573
1630
  group: groupConfig,
1574
- typed,
1575
1631
  importPath,
1576
1632
  coercion,
1577
1633
  inferred,
1578
1634
  guidType,
1579
1635
  regexType,
1580
1636
  mini,
1581
- wrapOutput,
1582
1637
  printer
1583
1638
  });
1584
1639
  ctx.setResolver(userResolver ? {