@kubb/plugin-zod 5.0.0-beta.64 → 5.0.0-beta.73

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 CHANGED
@@ -22,9 +22,9 @@
22
22
 
23
23
  # @kubb/plugin-zod
24
24
 
25
- ### Generate Zod schemas from OpenAPI
25
+ ### Generate Zod schemas with Kubb
26
26
 
27
- `@kubb/plugin-zod` generates Zod validation schemas from your OpenAPI specification. Each schema becomes a Zod object you can use to parse and validate data at runtime.
27
+ `@kubb/plugin-zod` generates Zod validation schemas with Kubb. Each schema becomes a Zod object you can use to parse and validate data at runtime.
28
28
 
29
29
  ## Installation
30
30
 
package/dist/index.cjs CHANGED
@@ -10,8 +10,8 @@ var __name = (target, value) => __defProp(target, "name", {
10
10
  });
11
11
  //#endregion
12
12
  let _kubb_core = require("@kubb/core");
13
- let _kubb_ast_utils = require("@kubb/ast/utils");
14
13
  let _kubb_renderer_jsx = require("@kubb/renderer-jsx");
14
+ let _kubb_ast_utils = require("@kubb/ast/utils");
15
15
  let _kubb_renderer_jsx_jsx_runtime = require("@kubb/renderer-jsx/jsx-runtime");
16
16
  //#region ../../internals/utils/src/casing.ts
17
17
  /**
@@ -200,6 +200,27 @@ function ensureValidVarName(name) {
200
200
  return `_${name}`;
201
201
  }
202
202
  //#endregion
203
+ //#region ../../internals/shared/src/params.ts
204
+ const caseParamsCache = /* @__PURE__ */ new WeakMap();
205
+ /**
206
+ * Applies camelCase to parameter names and returns a new array without mutating the input.
207
+ *
208
+ * Run it before handing parameters to schema builders so output property keys get the right casing
209
+ * while `OperationNode.parameters` stays intact for other consumers. When `casing` is unset, the
210
+ * original array is returned unchanged. Results are cached per input array.
211
+ */
212
+ function caseParams(params, casing) {
213
+ if (!casing) return params;
214
+ const cached = caseParamsCache.get(params);
215
+ if (cached) return cached;
216
+ const result = params.map((param) => ({
217
+ ...param,
218
+ name: camelCase(param.name)
219
+ }));
220
+ caseParamsCache.set(params, result);
221
+ return result;
222
+ }
223
+ //#endregion
203
224
  //#region ../../internals/shared/src/operation.ts
204
225
  /**
205
226
  * Maps a content type to the PascalCase suffix used to name per-content-type variants
@@ -249,6 +270,17 @@ function resolveContentTypeVariants(entries, baseName) {
249
270
  };
250
271
  });
251
272
  }
273
+ function getStatusCodeNumber(statusCode) {
274
+ const code = Number(statusCode);
275
+ return Number.isNaN(code) ? null : code;
276
+ }
277
+ function isSuccessStatusCode(statusCode) {
278
+ const code = getStatusCodeNumber(statusCode);
279
+ return code !== null && code >= 200 && code < 300;
280
+ }
281
+ function getSuccessResponses(responses) {
282
+ return responses.filter((response) => isSuccessStatusCode(response.statusCode));
283
+ }
252
284
  //#endregion
253
285
  //#region ../../internals/shared/src/group.ts
254
286
  /**
@@ -507,6 +539,13 @@ function formatLiteral(v) {
507
539
  return String(v);
508
540
  }
509
541
  /**
542
+ * Map a `regexType` to the `func` argument of `toRegExpString`: `'constructor'` emits
543
+ * `new RegExp(...)`, while `'literal'` (the default) emits a regex literal.
544
+ */
545
+ function regexFunc(regexType) {
546
+ return regexType === "constructor" ? "RegExp" : null;
547
+ }
548
+ /**
510
549
  * Build `.min()` / `.max()` / `.gt()` / `.lt()` constraint chains for numbers
511
550
  * using the standard chainable Zod v4 API.
512
551
  */
@@ -523,11 +562,11 @@ function numberConstraints({ min, max, exclusiveMinimum, exclusiveMaximum, multi
523
562
  * Build `.min()` / `.max()` / `.regex()` chains for strings/arrays
524
563
  * using the standard chainable Zod v4 API.
525
564
  */
526
- function lengthConstraints({ min, max, pattern }) {
565
+ function lengthConstraints({ min, max, pattern, regexType }) {
527
566
  return [
528
567
  min !== void 0 ? `.min(${min})` : "",
529
568
  max !== void 0 ? `.max(${max})` : "",
530
- pattern !== void 0 ? `.regex(${(0, _kubb_ast_utils.toRegExpString)(pattern, null)})` : ""
569
+ pattern !== void 0 ? `.regex(${(0, _kubb_ast_utils.toRegExpString)(pattern, regexFunc(regexType))})` : ""
531
570
  ].join("");
532
571
  }
533
572
  /**
@@ -545,18 +584,18 @@ function numberChecksMini({ min, max, exclusiveMinimum, exclusiveMaximum, multip
545
584
  /**
546
585
  * Build `.check(z.minLength(), z.maxLength(), z.regex())` for `zod/mini` length constraints.
547
586
  */
548
- function lengthChecksMini({ min, max, pattern }) {
587
+ function lengthChecksMini({ min, max, pattern, regexType }) {
549
588
  const checks = [];
550
589
  if (min !== void 0) checks.push(`z.minLength(${min})`);
551
590
  if (max !== void 0) checks.push(`z.maxLength(${max})`);
552
- if (pattern !== void 0) checks.push(`z.regex(${(0, _kubb_ast_utils.toRegExpString)(pattern, null)})`);
591
+ if (pattern !== void 0) checks.push(`z.regex(${(0, _kubb_ast_utils.toRegExpString)(pattern, regexFunc(regexType))})`);
553
592
  return checks.length ? `.check(${checks.join(", ")})` : "";
554
593
  }
555
594
  /**
556
- * Apply nullable / optional / nullish modifiers and an optional `.describe()` call
557
- * to a schema value string using the chainable Zod v4 API.
595
+ * Apply nullable / optional / nullish modifiers, an optional `.describe()` call, and an
596
+ * optional `.meta({ examples })` call to a schema value string using the chainable Zod v4 API.
558
597
  */
559
- function applyModifiers({ value, nullable, optional, nullish, defaultValue, description }) {
598
+ function applyModifiers({ value, nullable, optional, nullish, defaultValue, description, examples }) {
560
599
  const withModifier = (() => {
561
600
  if (nullish || nullable && optional) return `${value}.nullish()`;
562
601
  if (optional) return `${value}.optional()`;
@@ -564,7 +603,8 @@ function applyModifiers({ value, nullable, optional, nullish, defaultValue, desc
564
603
  return value;
565
604
  })();
566
605
  const withDefault = defaultValue !== void 0 ? `${withModifier}.default(${formatDefault(defaultValue)})` : withModifier;
567
- return description ? `${withDefault}.describe(${(0, _kubb_ast_utils.stringify)(description)})` : withDefault;
606
+ const withDescription = description ? `${withDefault}.describe(${(0, _kubb_ast_utils.stringify)(description)})` : withDefault;
607
+ return examples?.length ? `${withDescription}.meta({ examples: [${examples.map(formatDefault).join(", ")}] })` : withDescription;
568
608
  }
569
609
  /**
570
610
  * Apply nullable / optional / nullish modifiers using the functional `zod/mini` API
@@ -590,10 +630,16 @@ function strictOneOfMember$1(member, node) {
590
630
  return member;
591
631
  }
592
632
  __name(strictOneOfMember$1, "strictOneOfMember");
593
- function getMemberConstraint(member) {
594
- if (member.primitive === "string") return lengthConstraints(_kubb_core.ast.narrowSchema(member, "string") ?? {}) || void 0;
633
+ function getMemberConstraint({ member, regexType }) {
634
+ if (member.primitive === "string") return lengthConstraints({
635
+ ..._kubb_core.ast.narrowSchema(member, "string") ?? {},
636
+ regexType
637
+ }) || void 0;
595
638
  if (member.primitive === "number" || member.primitive === "integer") return numberConstraints(_kubb_core.ast.narrowSchema(member, "number") ?? _kubb_core.ast.narrowSchema(member, "integer") ?? {}) || void 0;
596
- if (member.primitive === "array") return lengthConstraints(_kubb_core.ast.narrowSchema(member, "array") ?? {}) || void 0;
639
+ if (member.primitive === "array") return lengthConstraints({
640
+ ..._kubb_core.ast.narrowSchema(member, "array") ?? {},
641
+ regexType
642
+ }) || void 0;
597
643
  }
598
644
  /**
599
645
  * Zod v4 printer built with `definePrinter`.
@@ -607,7 +653,7 @@ function getMemberConstraint(member) {
607
653
  * const code = printer.print(stringNode) // "z.string()"
608
654
  * ```
609
655
  */
610
- const printerZod = _kubb_core.ast.definePrinter((options) => {
656
+ const printerZod = _kubb_core.ast.createPrinter((options) => {
611
657
  return {
612
658
  name: "zod",
613
659
  options,
@@ -619,7 +665,10 @@ const printerZod = _kubb_core.ast.definePrinter((options) => {
619
665
  boolean: () => "z.boolean()",
620
666
  null: () => "z.null()",
621
667
  string(node) {
622
- return `${shouldCoerce(this.options.coercion, "strings") ? "z.coerce.string()" : "z.string()"}${lengthConstraints(node)}`;
668
+ return `${shouldCoerce(this.options.coercion, "strings") ? "z.coerce.string()" : "z.string()"}${lengthConstraints({
669
+ ...node,
670
+ regexType: this.options.regexType
671
+ })}`;
623
672
  },
624
673
  number(node) {
625
674
  return `${shouldCoerce(this.options.coercion, "numbers") ? "z.coerce.number()" : "z.number()"}${numberConstraints(node)}`;
@@ -647,13 +696,22 @@ const printerZod = _kubb_core.ast.definePrinter((options) => {
647
696
  return shouldCoerce(this.options.coercion, "dates") ? "z.coerce.date()" : "z.date()";
648
697
  },
649
698
  uuid(node) {
650
- return `${this.options.guidType === "guid" ? "z.guid()" : "z.uuid()"}${lengthConstraints(node)}`;
699
+ return `${this.options.guidType === "guid" ? "z.guid()" : "z.uuid()"}${lengthConstraints({
700
+ ...node,
701
+ regexType: this.options.regexType
702
+ })}`;
651
703
  },
652
704
  email(node) {
653
- return `z.email()${lengthConstraints(node)}`;
705
+ return `z.email()${lengthConstraints({
706
+ ...node,
707
+ regexType: this.options.regexType
708
+ })}`;
654
709
  },
655
710
  url(node) {
656
- return `z.url()${lengthConstraints(node)}`;
711
+ return `z.url()${lengthConstraints({
712
+ ...node,
713
+ regexType: this.options.regexType
714
+ })}`;
657
715
  },
658
716
  ipv4: () => "z.ipv4()",
659
717
  ipv6: () => "z.ipv6()",
@@ -698,7 +756,8 @@ const printerZod = _kubb_core.ast.definePrinter((options) => {
698
756
  optional: schema.optional || property.required === false,
699
757
  nullish: schema.nullish,
700
758
  defaultValue: meta.default,
701
- description: descriptionToApply
759
+ description: descriptionToApply,
760
+ examples: meta.examples
702
761
  });
703
762
  return isCyclic(schema) ? (0, _kubb_ast_utils.lazyGetter)({
704
763
  name: propName,
@@ -716,7 +775,10 @@ const printerZod = _kubb_core.ast.definePrinter((options) => {
716
775
  })();
717
776
  },
718
777
  array(node) {
719
- const base = `z.array(${(0, _kubb_ast_utils.mapSchemaItems)(node, (item) => this.transform(item)).map(({ output }) => output).filter(Boolean).join(", ") || this.transform(_kubb_core.ast.factory.createSchema({ type: "unknown" }))})${lengthConstraints(node)}`;
778
+ const base = `z.array(${(0, _kubb_ast_utils.mapSchemaItems)(node, (item) => this.transform(item)).map(({ output }) => output).filter(Boolean).join(", ") || this.transform(_kubb_core.ast.factory.createSchema({ type: "unknown" }))})${lengthConstraints({
779
+ ...node,
780
+ regexType: this.options.regexType
781
+ })}`;
720
782
  return node.unique ? `${base}.refine(items => new Set(items).size === items.length, { message: "Array entries must be unique" })` : base;
721
783
  },
722
784
  tuple(node) {
@@ -738,7 +800,10 @@ const printerZod = _kubb_core.ast.definePrinter((options) => {
738
800
  const firstBase = this.transform(first);
739
801
  if (!firstBase) return "";
740
802
  return rest.reduce((acc, member) => {
741
- const constraint = getMemberConstraint(member);
803
+ const constraint = getMemberConstraint({
804
+ member,
805
+ regexType: this.options.regexType
806
+ });
742
807
  if (constraint) return acc + constraint;
743
808
  const transformed = this.transform(member);
744
809
  return transformed ? `${acc}.and(${transformed})` : acc;
@@ -762,7 +827,8 @@ const printerZod = _kubb_core.ast.definePrinter((options) => {
762
827
  optional: meta.optional,
763
828
  nullish: meta.nullish,
764
829
  defaultValue: meta.default,
765
- description: meta.description
830
+ description: meta.description,
831
+ examples: meta.examples
766
832
  });
767
833
  }
768
834
  };
@@ -773,10 +839,16 @@ function strictOneOfMember(member, node) {
773
839
  if (node.type === "object" && (node.additionalProperties === void 0 || node.additionalProperties === false)) return member.replace(/^z\.object\(/, "z.strictObject(");
774
840
  return member;
775
841
  }
776
- function getMemberConstraintMini(member) {
777
- if (member.primitive === "string") return lengthChecksMini(_kubb_core.ast.narrowSchema(member, "string") ?? {}) || void 0;
842
+ function getMemberConstraintMini({ member, regexType }) {
843
+ if (member.primitive === "string") return lengthChecksMini({
844
+ ..._kubb_core.ast.narrowSchema(member, "string") ?? {},
845
+ regexType
846
+ }) || void 0;
778
847
  if (member.primitive === "number" || member.primitive === "integer") return numberChecksMini(_kubb_core.ast.narrowSchema(member, "number") ?? _kubb_core.ast.narrowSchema(member, "integer") ?? {}) || void 0;
779
- if (member.primitive === "array") return lengthChecksMini(_kubb_core.ast.narrowSchema(member, "array") ?? {}) || void 0;
848
+ if (member.primitive === "array") return lengthChecksMini({
849
+ ..._kubb_core.ast.narrowSchema(member, "array") ?? {},
850
+ regexType
851
+ }) || void 0;
780
852
  }
781
853
  /**
782
854
  * Zod v4 **Mini** printer built with `definePrinter`.
@@ -790,7 +862,7 @@ function getMemberConstraintMini(member) {
790
862
  * const code = printer.print(optionalStringNode) // "z.optional(z.string())"
791
863
  * ```
792
864
  */
793
- const printerZodMini = _kubb_core.ast.definePrinter((options) => {
865
+ const printerZodMini = _kubb_core.ast.createPrinter((options) => {
794
866
  return {
795
867
  name: "zod-mini",
796
868
  options,
@@ -802,7 +874,10 @@ const printerZodMini = _kubb_core.ast.definePrinter((options) => {
802
874
  boolean: () => "z.boolean()",
803
875
  null: () => "z.null()",
804
876
  string(node) {
805
- return `z.string()${lengthChecksMini(node)}`;
877
+ return `z.string()${lengthChecksMini({
878
+ ...node,
879
+ regexType: this.options.regexType
880
+ })}`;
806
881
  },
807
882
  number(node) {
808
883
  return `z.number()${numberChecksMini(node)}`;
@@ -825,13 +900,22 @@ const printerZodMini = _kubb_core.ast.definePrinter((options) => {
825
900
  return "z.date()";
826
901
  },
827
902
  uuid(node) {
828
- return `${this.options.guidType === "guid" ? "z.guid()" : "z.uuid()"}${lengthChecksMini(node)}`;
903
+ return `${this.options.guidType === "guid" ? "z.guid()" : "z.uuid()"}${lengthChecksMini({
904
+ ...node,
905
+ regexType: this.options.regexType
906
+ })}`;
829
907
  },
830
908
  email(node) {
831
- return `z.email()${lengthChecksMini(node)}`;
909
+ return `z.email()${lengthChecksMini({
910
+ ...node,
911
+ regexType: this.options.regexType
912
+ })}`;
832
913
  },
833
914
  url(node) {
834
- return `z.url()${lengthChecksMini(node)}`;
915
+ return `z.url()${lengthChecksMini({
916
+ ...node,
917
+ regexType: this.options.regexType
918
+ })}`;
835
919
  },
836
920
  ipv4: () => "z.ipv4()",
837
921
  ipv6: () => "z.ipv6()",
@@ -881,7 +965,10 @@ const printerZodMini = _kubb_core.ast.definePrinter((options) => {
881
965
  }))})`;
882
966
  },
883
967
  array(node) {
884
- const base = `z.array(${(0, _kubb_ast_utils.mapSchemaItems)(node, (item) => this.transform(item)).map(({ output }) => output).filter(Boolean).join(", ") || this.transform(_kubb_core.ast.factory.createSchema({ type: "unknown" }))})${lengthChecksMini(node)}`;
968
+ const base = `z.array(${(0, _kubb_ast_utils.mapSchemaItems)(node, (item) => this.transform(item)).map(({ output }) => output).filter(Boolean).join(", ") || this.transform(_kubb_core.ast.factory.createSchema({ type: "unknown" }))})${lengthChecksMini({
969
+ ...node,
970
+ regexType: this.options.regexType
971
+ })}`;
885
972
  return node.unique ? `${base}.refine(items => new Set(items).size === items.length, { message: "Array entries must be unique" })` : base;
886
973
  },
887
974
  tuple(node) {
@@ -903,7 +990,10 @@ const printerZodMini = _kubb_core.ast.definePrinter((options) => {
903
990
  const firstBase = this.transform(first);
904
991
  if (!firstBase) return "";
905
992
  return rest.reduce((acc, member) => {
906
- const constraint = getMemberConstraintMini(member);
993
+ const constraint = getMemberConstraintMini({
994
+ member,
995
+ regexType: this.options.regexType
996
+ });
907
997
  if (constraint) return acc + constraint;
908
998
  const transformed = this.transform(member);
909
999
  return transformed ? `z.intersection(${acc}, ${transformed})` : acc;
@@ -942,7 +1032,7 @@ const zodMiniPrinterCache = /* @__PURE__ */ new WeakMap();
942
1032
  */
943
1033
  function getStdPrinters(resolver, params) {
944
1034
  const cached = zodPrinterCache.get(resolver);
945
- if (cached && cached.coercion === params.coercion && cached.guidType === params.guidType && cached.dateType === params.dateType) return {
1035
+ if (cached && cached.coercion === params.coercion && cached.guidType === params.guidType && cached.regexType === params.regexType && cached.dateType === params.dateType) return {
946
1036
  output: cached.output,
947
1037
  input: cached.input
948
1038
  };
@@ -963,6 +1053,7 @@ function getStdPrinters(resolver, params) {
963
1053
  input,
964
1054
  coercion: params.coercion,
965
1055
  guidType: params.guidType,
1056
+ regexType: params.regexType,
966
1057
  dateType: params.dateType
967
1058
  });
968
1059
  return {
@@ -972,14 +1063,15 @@ function getStdPrinters(resolver, params) {
972
1063
  }
973
1064
  function getMiniPrinter(resolver, params) {
974
1065
  const cached = zodMiniPrinterCache.get(resolver);
975
- if (cached && cached.guidType === params.guidType) return cached.printer;
1066
+ if (cached && cached.guidType === params.guidType && cached.regexType === params.regexType) return cached.printer;
976
1067
  const p = printerZodMini({
977
1068
  ...params,
978
1069
  resolver
979
1070
  });
980
1071
  zodMiniPrinterCache.set(resolver, {
981
1072
  printer: p,
982
- guidType: params.guidType
1073
+ guidType: params.guidType,
1074
+ regexType: params.regexType
983
1075
  });
984
1076
  return p;
985
1077
  }
@@ -994,7 +1086,7 @@ const zodGenerator = (0, _kubb_core.defineGenerator)({
994
1086
  renderer: _kubb_renderer_jsx.jsxRenderer,
995
1087
  schema(node, ctx) {
996
1088
  const { adapter, config, resolver, root } = ctx;
997
- const { output, coercion, guidType, mini, wrapOutput, inferred, importPath, group, printer } = ctx.options;
1089
+ const { output, coercion, guidType, regexType, mini, wrapOutput, inferred, importPath, group, printer } = ctx.options;
998
1090
  const dateType = adapter.options.dateType;
999
1091
  if (!node.name) return;
1000
1092
  const isZodImport = ZOD_NAMESPACE_IMPORTS.has(importPath);
@@ -1045,6 +1137,7 @@ const zodGenerator = (0, _kubb_core.defineGenerator)({
1045
1137
  const stdPrinters = mini ? null : getStdPrinters(resolver, {
1046
1138
  coercion,
1047
1139
  guidType,
1140
+ regexType,
1048
1141
  dateType,
1049
1142
  wrapOutput,
1050
1143
  cyclicSchemas,
@@ -1052,6 +1145,7 @@ const zodGenerator = (0, _kubb_core.defineGenerator)({
1052
1145
  });
1053
1146
  const schemaPrinter = mini ? getMiniPrinter(resolver, {
1054
1147
  guidType,
1148
+ regexType,
1055
1149
  wrapOutput,
1056
1150
  cyclicSchemas,
1057
1151
  nodes: printer?.nodes
@@ -1109,10 +1203,10 @@ const zodGenerator = (0, _kubb_core.defineGenerator)({
1109
1203
  operation(node, ctx) {
1110
1204
  if (!_kubb_core.ast.isHttpOperationNode(node)) return null;
1111
1205
  const { adapter, config, resolver, root } = ctx;
1112
- const { output, coercion, guidType, mini, wrapOutput, inferred, importPath, group, paramsCasing, printer } = ctx.options;
1206
+ const { output, coercion, guidType, regexType, mini, wrapOutput, inferred, importPath, group, printer } = ctx.options;
1113
1207
  const dateType = adapter.options.dateType;
1114
1208
  const isZodImport = ZOD_NAMESPACE_IMPORTS.has(importPath);
1115
- const params = (0, _kubb_ast_utils.caseParams)(node.parameters, paramsCasing);
1209
+ const params = caseParams(node.parameters, "camelcase");
1116
1210
  const meta = { file: resolver.resolveFile({
1117
1211
  name: node.operationId,
1118
1212
  extname: ".ts",
@@ -1141,6 +1235,7 @@ const zodGenerator = (0, _kubb_core.defineGenerator)({
1141
1235
  }));
1142
1236
  const schemaPrinter = mini ? keysToOmit?.length ? printerZodMini({
1143
1237
  guidType,
1238
+ regexType,
1144
1239
  wrapOutput,
1145
1240
  resolver,
1146
1241
  keysToOmit,
@@ -1148,12 +1243,14 @@ const zodGenerator = (0, _kubb_core.defineGenerator)({
1148
1243
  nodes: printer?.nodes
1149
1244
  }) : getMiniPrinter(resolver, {
1150
1245
  guidType,
1246
+ regexType,
1151
1247
  wrapOutput,
1152
1248
  cyclicSchemas,
1153
1249
  nodes: printer?.nodes
1154
1250
  }) : keysToOmit?.length ? printerZod({
1155
1251
  coercion,
1156
1252
  guidType,
1253
+ regexType,
1157
1254
  dateType,
1158
1255
  wrapOutput,
1159
1256
  resolver,
@@ -1164,6 +1261,7 @@ const zodGenerator = (0, _kubb_core.defineGenerator)({
1164
1261
  }) : getStdPrinters(resolver, {
1165
1262
  coercion,
1166
1263
  guidType,
1264
+ regexType,
1167
1265
  dateType,
1168
1266
  wrapOutput,
1169
1267
  cyclicSchemas,
@@ -1220,16 +1318,21 @@ const zodGenerator = (0, _kubb_core.defineGenerator)({
1220
1318
  });
1221
1319
  });
1222
1320
  const responsesWithSchema = node.responses.filter((res) => res.content?.some((entry) => entry.schema));
1321
+ const successResponsesWithSchema = getSuccessResponses(responsesWithSchema);
1223
1322
  const responseUnionSchema = responsesWithSchema.length > 0 ? (() => {
1224
1323
  const responseUnionName = resolver.resolveResponseName(node);
1225
- if (new Set(responsesWithSchema.flatMap((res) => (res.content ?? []).flatMap((entry) => entry.schema ? adapter.getImports(entry.schema, (schemaName) => ({
1324
+ if (new Set(successResponsesWithSchema.flatMap((res) => (res.content ?? []).flatMap((entry) => entry.schema ? adapter.getImports(entry.schema, (schemaName) => ({
1226
1325
  name: resolver.resolveSchemaName(schemaName),
1227
1326
  path: ""
1228
1327
  })).flatMap((imp) => Array.isArray(imp.name) ? imp.name : [imp.name]) : []))).has(responseUnionName)) return null;
1229
- const members = responsesWithSchema.map((res) => _kubb_core.ast.factory.createSchema({
1328
+ const members = successResponsesWithSchema.map((res) => _kubb_core.ast.factory.createSchema({
1230
1329
  type: "ref",
1231
1330
  name: resolver.resolveResponseStatusName(node, res.statusCode)
1232
1331
  }));
1332
+ if (members.length === 0) return renderSchemaEntry({
1333
+ schema: _kubb_core.ast.factory.createSchema({ type: "unknown" }),
1334
+ name: responseUnionName
1335
+ });
1233
1336
  return renderSchemaEntry({
1234
1337
  schema: members.length === 1 ? members[0] : _kubb_core.ast.factory.createSchema({
1235
1338
  type: "union",
@@ -1294,7 +1397,7 @@ const zodGenerator = (0, _kubb_core.defineGenerator)({
1294
1397
  },
1295
1398
  operations(nodes, ctx) {
1296
1399
  const { config, resolver, root } = ctx;
1297
- const { output, importPath, group, operations, paramsCasing } = ctx.options;
1400
+ const { output, importPath, group, operations } = ctx.options;
1298
1401
  if (!operations) return;
1299
1402
  const isZodImport = ZOD_NAMESPACE_IMPORTS.has(importPath);
1300
1403
  const meta = { file: resolver.resolveFile({
@@ -1309,7 +1412,7 @@ const zodGenerator = (0, _kubb_core.defineGenerator)({
1309
1412
  return {
1310
1413
  node,
1311
1414
  data: buildSchemaNames(node, {
1312
- params: (0, _kubb_ast_utils.caseParams)(node.parameters, paramsCasing),
1415
+ params: caseParams(node.parameters, "camelcase"),
1313
1416
  resolver
1314
1417
  })
1315
1418
  };
@@ -1451,8 +1554,9 @@ const pluginZodName = "plugin-zod";
1451
1554
  /**
1452
1555
  * Generates Zod v4 schemas from an OpenAPI spec. Use them to validate API
1453
1556
  * responses at runtime, build form schemas, or feed back into router libraries
1454
- * that consume Zod (tRPC, Hono, Elysia). Pair with `@kubb/plugin-client` and
1455
- * set the client's `parser: 'zod'` to validate every response automatically.
1557
+ * that consume Zod (tRPC, Hono, Elysia). Pair with `@kubb/plugin-axios` or
1558
+ * `@kubb/plugin-fetch` and set the client's `parser: 'zod'` to validate every response
1559
+ * automatically.
1456
1560
  *
1457
1561
  * @example
1458
1562
  * ```ts
@@ -1477,7 +1581,7 @@ const pluginZod = (0, _kubb_core.definePlugin)((options) => {
1477
1581
  const { output = {
1478
1582
  path: "zod",
1479
1583
  barrel: { type: "named" }
1480
- }, group, exclude = [], include, override = [], typed = false, operations = false, mini = false, guidType = "uuid", importPath = mini ? "zod/mini" : "zod", coercion = false, inferred = false, wrapOutput = void 0, paramsCasing, printer, resolver: userResolver, macros: userMacros, generators: userGenerators = [] } = options;
1584
+ }, group, exclude = [], include, override = [], typed = false, operations = 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;
1481
1585
  const groupConfig = createGroupConfig(group);
1482
1586
  return {
1483
1587
  name: pluginZodName,
@@ -1495,9 +1599,9 @@ const pluginZod = (0, _kubb_core.definePlugin)((options) => {
1495
1599
  operations,
1496
1600
  inferred,
1497
1601
  guidType,
1602
+ regexType,
1498
1603
  mini,
1499
1604
  wrapOutput,
1500
- paramsCasing,
1501
1605
  printer
1502
1606
  });
1503
1607
  ctx.setResolver(userResolver ? {
@@ -1506,7 +1610,6 @@ const pluginZod = (0, _kubb_core.definePlugin)((options) => {
1506
1610
  } : resolverZod);
1507
1611
  if (userMacros?.length) ctx.setMacros(userMacros);
1508
1612
  ctx.addGenerator(zodGenerator);
1509
- for (const gen of userGenerators) ctx.addGenerator(gen);
1510
1613
  } }
1511
1614
  };
1512
1615
  });