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

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.d.ts CHANGED
@@ -1,7 +1,54 @@
1
- import { t as __name } from "./chunk-C0LytTxp.js";
2
- import { Exclude, Generator, Group, Include, Output, OutputOptions, Override, PluginFactoryOptions, Resolver, ast } from "@kubb/core";
1
+ import { t as __name } from "./rolldown-runtime-C0LytTxp.js";
2
+ import { Exclude, Group, Include, Output, OutputOptions, Override, PluginFactoryOptions, Resolver, ast } from "@kubb/core";
3
3
  import { AdapterOas } from "@kubb/adapter-oas";
4
4
 
5
+ //#region ../../internals/shared/src/operation.d.ts
6
+ /**
7
+ * Resolver interface for building operation parameters.
8
+ *
9
+ * `ResolverTs` from `@kubb/plugin-ts` satisfies this interface and can be passed directly.
10
+ */
11
+ type OperationParamsResolver = {
12
+ /**
13
+ * Resolves the type name for an individual parameter.
14
+ *
15
+ * @example Individual path parameter name
16
+ * `resolver.resolveParamName(node, param) // → 'DeletePetPathPetId'`
17
+ */
18
+ resolveParamName(node: ast.OperationNode, param: ast.ParameterNode): string;
19
+ /**
20
+ * Resolves the request body type name.
21
+ *
22
+ * @example Request body type name
23
+ * `resolver.resolveDataName(node) // → 'CreatePetData'`
24
+ */
25
+ resolveDataName(node: ast.OperationNode): string;
26
+ /**
27
+ * Resolves the grouped path parameters type name.
28
+ * When the return value equals `resolveParamName`, no indexed access is emitted.
29
+ *
30
+ * @example Grouped path params type name
31
+ * `resolver.resolvePathParamsName(node, param) // → 'DeletePetPathParams'`
32
+ */
33
+ resolvePathParamsName(node: ast.OperationNode, param: ast.ParameterNode): string;
34
+ /**
35
+ * Resolves the grouped query parameters type name.
36
+ * When the return value equals `resolveParamName`, an inline struct type is emitted instead.
37
+ *
38
+ * @example Grouped query params type name
39
+ * `resolver.resolveQueryParamsName(node, param) // → 'FindPetsByStatusQueryParams'`
40
+ */
41
+ resolveQueryParamsName(node: ast.OperationNode, param: ast.ParameterNode): string;
42
+ /**
43
+ * Resolves the grouped header parameters type name.
44
+ * When the return value equals `resolveParamName`, an inline struct type is emitted instead.
45
+ *
46
+ * @example Grouped header params type name
47
+ * `resolver.resolveHeaderParamsName(node, param) // → 'DeletePetHeaderParams'`
48
+ */
49
+ resolveHeaderParamsName(node: ast.OperationNode, param: ast.ParameterNode): string;
50
+ };
51
+ //#endregion
5
52
  //#region src/printers/printerZod.d.ts
6
53
  /**
7
54
  * Partial map of node-type overrides for the Zod printer.
@@ -35,6 +82,13 @@ type PrinterZodOptions = {
35
82
  * @default 'uuid'
36
83
  */
37
84
  guidType?: PluginZod['resolvedOptions']['guidType'];
85
+ /**
86
+ * Output form for an OpenAPI `pattern` inside `.regex(...)`: a regex literal
87
+ * (`'literal'`) or the `RegExp` constructor (`'constructor'`).
88
+ *
89
+ * @default 'literal'
90
+ */
91
+ regexType?: PluginZod['resolvedOptions']['regexType'];
38
92
  /**
39
93
  * Date format in the OpenAPI spec (`'date'` or `'date-time'`).
40
94
  */
@@ -118,6 +172,13 @@ type PrinterZodMiniOptions = {
118
172
  * @default 'uuid'
119
173
  */
120
174
  guidType?: PluginZod['resolvedOptions']['guidType'];
175
+ /**
176
+ * Output form for an OpenAPI `pattern` inside `z.regex(...)`: a regex literal
177
+ * (`'literal'`) or the `RegExp` constructor (`'constructor'`).
178
+ *
179
+ * @default 'literal'
180
+ */
181
+ regexType?: PluginZod['resolvedOptions']['regexType'];
121
182
  /**
122
183
  * Hook to transform generated Zod schema before output.
123
184
  */
@@ -162,7 +223,7 @@ declare const printerZodMini: (options?: PrinterZodMiniOptions | undefined) => a
162
223
  /**
163
224
  * Resolver for Zod that provides naming methods for schema types.
164
225
  */
165
- type ResolverZod = Resolver & ast.OperationParamsResolver & {
226
+ type ResolverZod = Resolver & OperationParamsResolver & {
166
227
  /**
167
228
  * Resolves a camelCase schema function name with a `Schema` suffix.
168
229
  */
@@ -307,6 +368,14 @@ type Options = OutputOptions & {
307
368
  * @default 'uuid'
308
369
  */
309
370
  guidType?: 'uuid' | 'guid';
371
+ /**
372
+ * Output form for an OpenAPI `pattern` inside `.regex(...)`.
373
+ * - `'literal'` — a regex literal: `.regex(/^[a-z]+$/)`.
374
+ * - `'constructor'` — the `RegExp` constructor: `.regex(new RegExp("^[a-z]+$"))`.
375
+ *
376
+ * @default 'literal'
377
+ */
378
+ regexType?: 'literal' | 'constructor';
310
379
  /**
311
380
  * Switch to Zod Mini's functional API for better tree-shaking. Also defaults
312
381
  * `importPath` to `'zod/mini'`.
@@ -324,16 +393,6 @@ type Options = OutputOptions & {
324
393
  output: string;
325
394
  schema: ast.SchemaNode;
326
395
  }) => string | undefined;
327
- /**
328
- * Rename properties inside path/query/header schemas. Body schemas are unaffected.
329
- *
330
- * @note Must match the value of `paramsCasing` on `@kubb/plugin-ts`.
331
- */
332
- paramsCasing?: 'camelcase';
333
- /**
334
- * Custom generators that run alongside the built-in Zod generators.
335
- */
336
- generators?: Array<Generator<PluginZod>>;
337
396
  /**
338
397
  * Override how schema and operation names are built. Methods you omit fall back
339
398
  * to the default `resolverZod`.
@@ -363,9 +422,9 @@ type ResolvedOptions = {
363
422
  coercion: NonNullable<Options['coercion']>;
364
423
  operations: NonNullable<Options['operations']>;
365
424
  guidType: NonNullable<Options['guidType']>;
425
+ regexType: NonNullable<Options['regexType']>;
366
426
  mini: NonNullable<Options['mini']>;
367
427
  wrapOutput: Options['wrapOutput'];
368
- paramsCasing: Options['paramsCasing'];
369
428
  printer: Options['printer'];
370
429
  };
371
430
  type PluginZod = PluginFactoryOptions<'plugin-zod', Options, ResolvedOptions, ResolverZod>;
@@ -395,8 +454,9 @@ declare const pluginZodName = "plugin-zod";
395
454
  /**
396
455
  * Generates Zod v4 schemas from an OpenAPI spec. Use them to validate API
397
456
  * responses at runtime, build form schemas, or feed back into router libraries
398
- * that consume Zod (tRPC, Hono, Elysia). Pair with `@kubb/plugin-client` and
399
- * set the client's `parser: 'zod'` to validate every response automatically.
457
+ * that consume Zod (tRPC, Hono, Elysia). Pair with `@kubb/plugin-axios` or
458
+ * `@kubb/plugin-fetch` and set the client's `parser: 'zod'` to validate every response
459
+ * automatically.
400
460
  *
401
461
  * @example
402
462
  * ```ts
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
- import { t as __name } from "./chunk-C0LytTxp.js";
1
+ import { t as __name } from "./rolldown-runtime-C0LytTxp.js";
2
2
  import { ast, defineGenerator, definePlugin, defineResolver } from "@kubb/core";
3
- import { buildList, buildObject, caseParams, containsCircularRef, extractRefName, lazyGetter, mapSchemaItems, mapSchemaMembers, mapSchemaProperties, objectKey, stringify, stringifyObject, syncSchemaRef, toRegExpString } from "@kubb/ast/utils";
4
3
  import { Const, File, Type, jsxRenderer } from "@kubb/renderer-jsx";
4
+ import { buildList, buildObject, containsCircularRef, extractRefName, lazyGetter, mapSchemaItems, mapSchemaMembers, mapSchemaProperties, objectKey, stringify, stringifyObject, syncSchemaRef, toRegExpString } from "@kubb/ast/utils";
5
5
  import { Fragment, jsx, jsxs } from "@kubb/renderer-jsx/jsx-runtime";
6
6
  //#region ../../internals/utils/src/casing.ts
7
7
  /**
@@ -190,6 +190,27 @@ function ensureValidVarName(name) {
190
190
  return `_${name}`;
191
191
  }
192
192
  //#endregion
193
+ //#region ../../internals/shared/src/params.ts
194
+ const caseParamsCache = /* @__PURE__ */ new WeakMap();
195
+ /**
196
+ * Applies camelCase to parameter names and returns a new array without mutating the input.
197
+ *
198
+ * Run it before handing parameters to schema builders so output property keys get the right casing
199
+ * while `OperationNode.parameters` stays intact for other consumers. When `casing` is unset, the
200
+ * original array is returned unchanged. Results are cached per input array.
201
+ */
202
+ function caseParams(params, casing) {
203
+ if (!casing) return params;
204
+ const cached = caseParamsCache.get(params);
205
+ if (cached) return cached;
206
+ const result = params.map((param) => ({
207
+ ...param,
208
+ name: camelCase(param.name)
209
+ }));
210
+ caseParamsCache.set(params, result);
211
+ return result;
212
+ }
213
+ //#endregion
193
214
  //#region ../../internals/shared/src/operation.ts
194
215
  /**
195
216
  * Maps a content type to the PascalCase suffix used to name per-content-type variants
@@ -239,6 +260,17 @@ function resolveContentTypeVariants(entries, baseName) {
239
260
  };
240
261
  });
241
262
  }
263
+ function getStatusCodeNumber(statusCode) {
264
+ const code = Number(statusCode);
265
+ return Number.isNaN(code) ? null : code;
266
+ }
267
+ function isSuccessStatusCode(statusCode) {
268
+ const code = getStatusCodeNumber(statusCode);
269
+ return code !== null && code >= 200 && code < 300;
270
+ }
271
+ function getSuccessResponses(responses) {
272
+ return responses.filter((response) => isSuccessStatusCode(response.statusCode));
273
+ }
242
274
  //#endregion
243
275
  //#region ../../internals/shared/src/group.ts
244
276
  /**
@@ -497,6 +529,13 @@ function formatLiteral(v) {
497
529
  return String(v);
498
530
  }
499
531
  /**
532
+ * Map a `regexType` to the `func` argument of `toRegExpString`: `'constructor'` emits
533
+ * `new RegExp(...)`, while `'literal'` (the default) emits a regex literal.
534
+ */
535
+ function regexFunc(regexType) {
536
+ return regexType === "constructor" ? "RegExp" : null;
537
+ }
538
+ /**
500
539
  * Build `.min()` / `.max()` / `.gt()` / `.lt()` constraint chains for numbers
501
540
  * using the standard chainable Zod v4 API.
502
541
  */
@@ -513,11 +552,11 @@ function numberConstraints({ min, max, exclusiveMinimum, exclusiveMaximum, multi
513
552
  * Build `.min()` / `.max()` / `.regex()` chains for strings/arrays
514
553
  * using the standard chainable Zod v4 API.
515
554
  */
516
- function lengthConstraints({ min, max, pattern }) {
555
+ function lengthConstraints({ min, max, pattern, regexType }) {
517
556
  return [
518
557
  min !== void 0 ? `.min(${min})` : "",
519
558
  max !== void 0 ? `.max(${max})` : "",
520
- pattern !== void 0 ? `.regex(${toRegExpString(pattern, null)})` : ""
559
+ pattern !== void 0 ? `.regex(${toRegExpString(pattern, regexFunc(regexType))})` : ""
521
560
  ].join("");
522
561
  }
523
562
  /**
@@ -535,18 +574,18 @@ function numberChecksMini({ min, max, exclusiveMinimum, exclusiveMaximum, multip
535
574
  /**
536
575
  * Build `.check(z.minLength(), z.maxLength(), z.regex())` for `zod/mini` length constraints.
537
576
  */
538
- function lengthChecksMini({ min, max, pattern }) {
577
+ function lengthChecksMini({ min, max, pattern, regexType }) {
539
578
  const checks = [];
540
579
  if (min !== void 0) checks.push(`z.minLength(${min})`);
541
580
  if (max !== void 0) checks.push(`z.maxLength(${max})`);
542
- if (pattern !== void 0) checks.push(`z.regex(${toRegExpString(pattern, null)})`);
581
+ if (pattern !== void 0) checks.push(`z.regex(${toRegExpString(pattern, regexFunc(regexType))})`);
543
582
  return checks.length ? `.check(${checks.join(", ")})` : "";
544
583
  }
545
584
  /**
546
- * Apply nullable / optional / nullish modifiers and an optional `.describe()` call
547
- * to a schema value string using the chainable Zod v4 API.
585
+ * Apply nullable / optional / nullish modifiers, an optional `.describe()` call, and an
586
+ * optional `.meta({ examples })` call to a schema value string using the chainable Zod v4 API.
548
587
  */
549
- function applyModifiers({ value, nullable, optional, nullish, defaultValue, description }) {
588
+ function applyModifiers({ value, nullable, optional, nullish, defaultValue, description, examples }) {
550
589
  const withModifier = (() => {
551
590
  if (nullish || nullable && optional) return `${value}.nullish()`;
552
591
  if (optional) return `${value}.optional()`;
@@ -554,7 +593,8 @@ function applyModifiers({ value, nullable, optional, nullish, defaultValue, desc
554
593
  return value;
555
594
  })();
556
595
  const withDefault = defaultValue !== void 0 ? `${withModifier}.default(${formatDefault(defaultValue)})` : withModifier;
557
- return description ? `${withDefault}.describe(${stringify(description)})` : withDefault;
596
+ const withDescription = description ? `${withDefault}.describe(${stringify(description)})` : withDefault;
597
+ return examples?.length ? `${withDescription}.meta({ examples: [${examples.map(formatDefault).join(", ")}] })` : withDescription;
558
598
  }
559
599
  /**
560
600
  * Apply nullable / optional / nullish modifiers using the functional `zod/mini` API
@@ -580,10 +620,16 @@ function strictOneOfMember$1(member, node) {
580
620
  return member;
581
621
  }
582
622
  __name(strictOneOfMember$1, "strictOneOfMember");
583
- function getMemberConstraint(member) {
584
- if (member.primitive === "string") return lengthConstraints(ast.narrowSchema(member, "string") ?? {}) || void 0;
623
+ function getMemberConstraint({ member, regexType }) {
624
+ if (member.primitive === "string") return lengthConstraints({
625
+ ...ast.narrowSchema(member, "string") ?? {},
626
+ regexType
627
+ }) || void 0;
585
628
  if (member.primitive === "number" || member.primitive === "integer") return numberConstraints(ast.narrowSchema(member, "number") ?? ast.narrowSchema(member, "integer") ?? {}) || void 0;
586
- if (member.primitive === "array") return lengthConstraints(ast.narrowSchema(member, "array") ?? {}) || void 0;
629
+ if (member.primitive === "array") return lengthConstraints({
630
+ ...ast.narrowSchema(member, "array") ?? {},
631
+ regexType
632
+ }) || void 0;
587
633
  }
588
634
  /**
589
635
  * Zod v4 printer built with `definePrinter`.
@@ -597,7 +643,7 @@ function getMemberConstraint(member) {
597
643
  * const code = printer.print(stringNode) // "z.string()"
598
644
  * ```
599
645
  */
600
- const printerZod = ast.definePrinter((options) => {
646
+ const printerZod = ast.createPrinter((options) => {
601
647
  return {
602
648
  name: "zod",
603
649
  options,
@@ -609,7 +655,10 @@ const printerZod = ast.definePrinter((options) => {
609
655
  boolean: () => "z.boolean()",
610
656
  null: () => "z.null()",
611
657
  string(node) {
612
- return `${shouldCoerce(this.options.coercion, "strings") ? "z.coerce.string()" : "z.string()"}${lengthConstraints(node)}`;
658
+ return `${shouldCoerce(this.options.coercion, "strings") ? "z.coerce.string()" : "z.string()"}${lengthConstraints({
659
+ ...node,
660
+ regexType: this.options.regexType
661
+ })}`;
613
662
  },
614
663
  number(node) {
615
664
  return `${shouldCoerce(this.options.coercion, "numbers") ? "z.coerce.number()" : "z.number()"}${numberConstraints(node)}`;
@@ -637,13 +686,22 @@ const printerZod = ast.definePrinter((options) => {
637
686
  return shouldCoerce(this.options.coercion, "dates") ? "z.coerce.date()" : "z.date()";
638
687
  },
639
688
  uuid(node) {
640
- return `${this.options.guidType === "guid" ? "z.guid()" : "z.uuid()"}${lengthConstraints(node)}`;
689
+ return `${this.options.guidType === "guid" ? "z.guid()" : "z.uuid()"}${lengthConstraints({
690
+ ...node,
691
+ regexType: this.options.regexType
692
+ })}`;
641
693
  },
642
694
  email(node) {
643
- return `z.email()${lengthConstraints(node)}`;
695
+ return `z.email()${lengthConstraints({
696
+ ...node,
697
+ regexType: this.options.regexType
698
+ })}`;
644
699
  },
645
700
  url(node) {
646
- return `z.url()${lengthConstraints(node)}`;
701
+ return `z.url()${lengthConstraints({
702
+ ...node,
703
+ regexType: this.options.regexType
704
+ })}`;
647
705
  },
648
706
  ipv4: () => "z.ipv4()",
649
707
  ipv6: () => "z.ipv6()",
@@ -688,7 +746,8 @@ const printerZod = ast.definePrinter((options) => {
688
746
  optional: schema.optional || property.required === false,
689
747
  nullish: schema.nullish,
690
748
  defaultValue: meta.default,
691
- description: descriptionToApply
749
+ description: descriptionToApply,
750
+ examples: meta.examples
692
751
  });
693
752
  return isCyclic(schema) ? lazyGetter({
694
753
  name: propName,
@@ -706,7 +765,10 @@ const printerZod = ast.definePrinter((options) => {
706
765
  })();
707
766
  },
708
767
  array(node) {
709
- const base = `z.array(${mapSchemaItems(node, (item) => this.transform(item)).map(({ output }) => output).filter(Boolean).join(", ") || this.transform(ast.factory.createSchema({ type: "unknown" }))})${lengthConstraints(node)}`;
768
+ const base = `z.array(${mapSchemaItems(node, (item) => this.transform(item)).map(({ output }) => output).filter(Boolean).join(", ") || this.transform(ast.factory.createSchema({ type: "unknown" }))})${lengthConstraints({
769
+ ...node,
770
+ regexType: this.options.regexType
771
+ })}`;
710
772
  return node.unique ? `${base}.refine(items => new Set(items).size === items.length, { message: "Array entries must be unique" })` : base;
711
773
  },
712
774
  tuple(node) {
@@ -728,7 +790,10 @@ const printerZod = ast.definePrinter((options) => {
728
790
  const firstBase = this.transform(first);
729
791
  if (!firstBase) return "";
730
792
  return rest.reduce((acc, member) => {
731
- const constraint = getMemberConstraint(member);
793
+ const constraint = getMemberConstraint({
794
+ member,
795
+ regexType: this.options.regexType
796
+ });
732
797
  if (constraint) return acc + constraint;
733
798
  const transformed = this.transform(member);
734
799
  return transformed ? `${acc}.and(${transformed})` : acc;
@@ -752,7 +817,8 @@ const printerZod = ast.definePrinter((options) => {
752
817
  optional: meta.optional,
753
818
  nullish: meta.nullish,
754
819
  defaultValue: meta.default,
755
- description: meta.description
820
+ description: meta.description,
821
+ examples: meta.examples
756
822
  });
757
823
  }
758
824
  };
@@ -763,10 +829,16 @@ function strictOneOfMember(member, node) {
763
829
  if (node.type === "object" && (node.additionalProperties === void 0 || node.additionalProperties === false)) return member.replace(/^z\.object\(/, "z.strictObject(");
764
830
  return member;
765
831
  }
766
- function getMemberConstraintMini(member) {
767
- if (member.primitive === "string") return lengthChecksMini(ast.narrowSchema(member, "string") ?? {}) || void 0;
832
+ function getMemberConstraintMini({ member, regexType }) {
833
+ if (member.primitive === "string") return lengthChecksMini({
834
+ ...ast.narrowSchema(member, "string") ?? {},
835
+ regexType
836
+ }) || void 0;
768
837
  if (member.primitive === "number" || member.primitive === "integer") return numberChecksMini(ast.narrowSchema(member, "number") ?? ast.narrowSchema(member, "integer") ?? {}) || void 0;
769
- if (member.primitive === "array") return lengthChecksMini(ast.narrowSchema(member, "array") ?? {}) || void 0;
838
+ if (member.primitive === "array") return lengthChecksMini({
839
+ ...ast.narrowSchema(member, "array") ?? {},
840
+ regexType
841
+ }) || void 0;
770
842
  }
771
843
  /**
772
844
  * Zod v4 **Mini** printer built with `definePrinter`.
@@ -780,7 +852,7 @@ function getMemberConstraintMini(member) {
780
852
  * const code = printer.print(optionalStringNode) // "z.optional(z.string())"
781
853
  * ```
782
854
  */
783
- const printerZodMini = ast.definePrinter((options) => {
855
+ const printerZodMini = ast.createPrinter((options) => {
784
856
  return {
785
857
  name: "zod-mini",
786
858
  options,
@@ -792,7 +864,10 @@ const printerZodMini = ast.definePrinter((options) => {
792
864
  boolean: () => "z.boolean()",
793
865
  null: () => "z.null()",
794
866
  string(node) {
795
- return `z.string()${lengthChecksMini(node)}`;
867
+ return `z.string()${lengthChecksMini({
868
+ ...node,
869
+ regexType: this.options.regexType
870
+ })}`;
796
871
  },
797
872
  number(node) {
798
873
  return `z.number()${numberChecksMini(node)}`;
@@ -815,13 +890,22 @@ const printerZodMini = ast.definePrinter((options) => {
815
890
  return "z.date()";
816
891
  },
817
892
  uuid(node) {
818
- return `${this.options.guidType === "guid" ? "z.guid()" : "z.uuid()"}${lengthChecksMini(node)}`;
893
+ return `${this.options.guidType === "guid" ? "z.guid()" : "z.uuid()"}${lengthChecksMini({
894
+ ...node,
895
+ regexType: this.options.regexType
896
+ })}`;
819
897
  },
820
898
  email(node) {
821
- return `z.email()${lengthChecksMini(node)}`;
899
+ return `z.email()${lengthChecksMini({
900
+ ...node,
901
+ regexType: this.options.regexType
902
+ })}`;
822
903
  },
823
904
  url(node) {
824
- return `z.url()${lengthChecksMini(node)}`;
905
+ return `z.url()${lengthChecksMini({
906
+ ...node,
907
+ regexType: this.options.regexType
908
+ })}`;
825
909
  },
826
910
  ipv4: () => "z.ipv4()",
827
911
  ipv6: () => "z.ipv6()",
@@ -871,7 +955,10 @@ const printerZodMini = ast.definePrinter((options) => {
871
955
  }))})`;
872
956
  },
873
957
  array(node) {
874
- const base = `z.array(${mapSchemaItems(node, (item) => this.transform(item)).map(({ output }) => output).filter(Boolean).join(", ") || this.transform(ast.factory.createSchema({ type: "unknown" }))})${lengthChecksMini(node)}`;
958
+ const base = `z.array(${mapSchemaItems(node, (item) => this.transform(item)).map(({ output }) => output).filter(Boolean).join(", ") || this.transform(ast.factory.createSchema({ type: "unknown" }))})${lengthChecksMini({
959
+ ...node,
960
+ regexType: this.options.regexType
961
+ })}`;
875
962
  return node.unique ? `${base}.refine(items => new Set(items).size === items.length, { message: "Array entries must be unique" })` : base;
876
963
  },
877
964
  tuple(node) {
@@ -893,7 +980,10 @@ const printerZodMini = ast.definePrinter((options) => {
893
980
  const firstBase = this.transform(first);
894
981
  if (!firstBase) return "";
895
982
  return rest.reduce((acc, member) => {
896
- const constraint = getMemberConstraintMini(member);
983
+ const constraint = getMemberConstraintMini({
984
+ member,
985
+ regexType: this.options.regexType
986
+ });
897
987
  if (constraint) return acc + constraint;
898
988
  const transformed = this.transform(member);
899
989
  return transformed ? `z.intersection(${acc}, ${transformed})` : acc;
@@ -932,7 +1022,7 @@ const zodMiniPrinterCache = /* @__PURE__ */ new WeakMap();
932
1022
  */
933
1023
  function getStdPrinters(resolver, params) {
934
1024
  const cached = zodPrinterCache.get(resolver);
935
- if (cached && cached.coercion === params.coercion && cached.guidType === params.guidType && cached.dateType === params.dateType) return {
1025
+ if (cached && cached.coercion === params.coercion && cached.guidType === params.guidType && cached.regexType === params.regexType && cached.dateType === params.dateType) return {
936
1026
  output: cached.output,
937
1027
  input: cached.input
938
1028
  };
@@ -953,6 +1043,7 @@ function getStdPrinters(resolver, params) {
953
1043
  input,
954
1044
  coercion: params.coercion,
955
1045
  guidType: params.guidType,
1046
+ regexType: params.regexType,
956
1047
  dateType: params.dateType
957
1048
  });
958
1049
  return {
@@ -962,14 +1053,15 @@ function getStdPrinters(resolver, params) {
962
1053
  }
963
1054
  function getMiniPrinter(resolver, params) {
964
1055
  const cached = zodMiniPrinterCache.get(resolver);
965
- if (cached && cached.guidType === params.guidType) return cached.printer;
1056
+ if (cached && cached.guidType === params.guidType && cached.regexType === params.regexType) return cached.printer;
966
1057
  const p = printerZodMini({
967
1058
  ...params,
968
1059
  resolver
969
1060
  });
970
1061
  zodMiniPrinterCache.set(resolver, {
971
1062
  printer: p,
972
- guidType: params.guidType
1063
+ guidType: params.guidType,
1064
+ regexType: params.regexType
973
1065
  });
974
1066
  return p;
975
1067
  }
@@ -984,7 +1076,7 @@ const zodGenerator = defineGenerator({
984
1076
  renderer: jsxRenderer,
985
1077
  schema(node, ctx) {
986
1078
  const { adapter, config, resolver, root } = ctx;
987
- const { output, coercion, guidType, mini, wrapOutput, inferred, importPath, group, printer } = ctx.options;
1079
+ const { output, coercion, guidType, regexType, mini, wrapOutput, inferred, importPath, group, printer } = ctx.options;
988
1080
  const dateType = adapter.options.dateType;
989
1081
  if (!node.name) return;
990
1082
  const isZodImport = ZOD_NAMESPACE_IMPORTS.has(importPath);
@@ -1035,6 +1127,7 @@ const zodGenerator = defineGenerator({
1035
1127
  const stdPrinters = mini ? null : getStdPrinters(resolver, {
1036
1128
  coercion,
1037
1129
  guidType,
1130
+ regexType,
1038
1131
  dateType,
1039
1132
  wrapOutput,
1040
1133
  cyclicSchemas,
@@ -1042,6 +1135,7 @@ const zodGenerator = defineGenerator({
1042
1135
  });
1043
1136
  const schemaPrinter = mini ? getMiniPrinter(resolver, {
1044
1137
  guidType,
1138
+ regexType,
1045
1139
  wrapOutput,
1046
1140
  cyclicSchemas,
1047
1141
  nodes: printer?.nodes
@@ -1099,10 +1193,10 @@ const zodGenerator = defineGenerator({
1099
1193
  operation(node, ctx) {
1100
1194
  if (!ast.isHttpOperationNode(node)) return null;
1101
1195
  const { adapter, config, resolver, root } = ctx;
1102
- const { output, coercion, guidType, mini, wrapOutput, inferred, importPath, group, paramsCasing, printer } = ctx.options;
1196
+ const { output, coercion, guidType, regexType, mini, wrapOutput, inferred, importPath, group, printer } = ctx.options;
1103
1197
  const dateType = adapter.options.dateType;
1104
1198
  const isZodImport = ZOD_NAMESPACE_IMPORTS.has(importPath);
1105
- const params = caseParams(node.parameters, paramsCasing);
1199
+ const params = caseParams(node.parameters, "camelcase");
1106
1200
  const meta = { file: resolver.resolveFile({
1107
1201
  name: node.operationId,
1108
1202
  extname: ".ts",
@@ -1131,6 +1225,7 @@ const zodGenerator = defineGenerator({
1131
1225
  }));
1132
1226
  const schemaPrinter = mini ? keysToOmit?.length ? printerZodMini({
1133
1227
  guidType,
1228
+ regexType,
1134
1229
  wrapOutput,
1135
1230
  resolver,
1136
1231
  keysToOmit,
@@ -1138,12 +1233,14 @@ const zodGenerator = defineGenerator({
1138
1233
  nodes: printer?.nodes
1139
1234
  }) : getMiniPrinter(resolver, {
1140
1235
  guidType,
1236
+ regexType,
1141
1237
  wrapOutput,
1142
1238
  cyclicSchemas,
1143
1239
  nodes: printer?.nodes
1144
1240
  }) : keysToOmit?.length ? printerZod({
1145
1241
  coercion,
1146
1242
  guidType,
1243
+ regexType,
1147
1244
  dateType,
1148
1245
  wrapOutput,
1149
1246
  resolver,
@@ -1154,6 +1251,7 @@ const zodGenerator = defineGenerator({
1154
1251
  }) : getStdPrinters(resolver, {
1155
1252
  coercion,
1156
1253
  guidType,
1254
+ regexType,
1157
1255
  dateType,
1158
1256
  wrapOutput,
1159
1257
  cyclicSchemas,
@@ -1210,16 +1308,21 @@ const zodGenerator = defineGenerator({
1210
1308
  });
1211
1309
  });
1212
1310
  const responsesWithSchema = node.responses.filter((res) => res.content?.some((entry) => entry.schema));
1311
+ const successResponsesWithSchema = getSuccessResponses(responsesWithSchema);
1213
1312
  const responseUnionSchema = responsesWithSchema.length > 0 ? (() => {
1214
1313
  const responseUnionName = resolver.resolveResponseName(node);
1215
- if (new Set(responsesWithSchema.flatMap((res) => (res.content ?? []).flatMap((entry) => entry.schema ? adapter.getImports(entry.schema, (schemaName) => ({
1314
+ if (new Set(successResponsesWithSchema.flatMap((res) => (res.content ?? []).flatMap((entry) => entry.schema ? adapter.getImports(entry.schema, (schemaName) => ({
1216
1315
  name: resolver.resolveSchemaName(schemaName),
1217
1316
  path: ""
1218
1317
  })).flatMap((imp) => Array.isArray(imp.name) ? imp.name : [imp.name]) : []))).has(responseUnionName)) return null;
1219
- const members = responsesWithSchema.map((res) => ast.factory.createSchema({
1318
+ const members = successResponsesWithSchema.map((res) => ast.factory.createSchema({
1220
1319
  type: "ref",
1221
1320
  name: resolver.resolveResponseStatusName(node, res.statusCode)
1222
1321
  }));
1322
+ if (members.length === 0) return renderSchemaEntry({
1323
+ schema: ast.factory.createSchema({ type: "unknown" }),
1324
+ name: responseUnionName
1325
+ });
1223
1326
  return renderSchemaEntry({
1224
1327
  schema: members.length === 1 ? members[0] : ast.factory.createSchema({
1225
1328
  type: "union",
@@ -1284,7 +1387,7 @@ const zodGenerator = defineGenerator({
1284
1387
  },
1285
1388
  operations(nodes, ctx) {
1286
1389
  const { config, resolver, root } = ctx;
1287
- const { output, importPath, group, operations, paramsCasing } = ctx.options;
1390
+ const { output, importPath, group, operations } = ctx.options;
1288
1391
  if (!operations) return;
1289
1392
  const isZodImport = ZOD_NAMESPACE_IMPORTS.has(importPath);
1290
1393
  const meta = { file: resolver.resolveFile({
@@ -1299,7 +1402,7 @@ const zodGenerator = defineGenerator({
1299
1402
  return {
1300
1403
  node,
1301
1404
  data: buildSchemaNames(node, {
1302
- params: caseParams(node.parameters, paramsCasing),
1405
+ params: caseParams(node.parameters, "camelcase"),
1303
1406
  resolver
1304
1407
  })
1305
1408
  };
@@ -1441,8 +1544,9 @@ const pluginZodName = "plugin-zod";
1441
1544
  /**
1442
1545
  * Generates Zod v4 schemas from an OpenAPI spec. Use them to validate API
1443
1546
  * responses at runtime, build form schemas, or feed back into router libraries
1444
- * that consume Zod (tRPC, Hono, Elysia). Pair with `@kubb/plugin-client` and
1445
- * set the client's `parser: 'zod'` to validate every response automatically.
1547
+ * that consume Zod (tRPC, Hono, Elysia). Pair with `@kubb/plugin-axios` or
1548
+ * `@kubb/plugin-fetch` and set the client's `parser: 'zod'` to validate every response
1549
+ * automatically.
1446
1550
  *
1447
1551
  * @example
1448
1552
  * ```ts
@@ -1467,7 +1571,7 @@ const pluginZod = definePlugin((options) => {
1467
1571
  const { output = {
1468
1572
  path: "zod",
1469
1573
  barrel: { type: "named" }
1470
- }, 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;
1574
+ }, 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;
1471
1575
  const groupConfig = createGroupConfig(group);
1472
1576
  return {
1473
1577
  name: pluginZodName,
@@ -1485,9 +1589,9 @@ const pluginZod = definePlugin((options) => {
1485
1589
  operations,
1486
1590
  inferred,
1487
1591
  guidType,
1592
+ regexType,
1488
1593
  mini,
1489
1594
  wrapOutput,
1490
- paramsCasing,
1491
1595
  printer
1492
1596
  });
1493
1597
  ctx.setResolver(userResolver ? {
@@ -1496,7 +1600,6 @@ const pluginZod = definePlugin((options) => {
1496
1600
  } : resolverZod);
1497
1601
  if (userMacros?.length) ctx.setMacros(userMacros);
1498
1602
  ctx.addGenerator(zodGenerator);
1499
- for (const gen of userGenerators) ctx.addGenerator(gen);
1500
1603
  } }
1501
1604
  };
1502
1605
  });