@kubb/plugin-zod 5.0.0-beta.81 → 5.0.0-beta.85

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 { Resolver, ast, createResolver, defineGenerator, definePlugin } 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.
@@ -42,31 +41,6 @@ function pascalCase(text, { prefix = "", suffix = "" } = {}) {
42
41
  return toCamelOrPascal(`${prefix} ${text} ${suffix}`, true);
43
42
  }
44
43
  //#endregion
45
- //#region ../../internals/utils/src/fs.ts
46
- /**
47
- * Builds a nested file path from a dotted name. Splits on dots that precede a letter
48
- * (so version numbers embedded in operationIds like `v2025.0` stay intact), camelCases
49
- * every earlier segment, applies `caseLast` to the final segment, and joins with `/`.
50
- *
51
- * Empty segments are dropped before joining. They arise when the name starts with a dot
52
- * followed by a letter (e.g. `..Schema` splits into `['..', 'Schema']` and `'..'` cases to
53
- * an empty string). Without this a leading `/` would form, which `path.resolve` reads as an
54
- * absolute path, letting generated files escape the configured output directory.
55
- *
56
- * @example Nested path from a dotted name
57
- * `toFilePath('pet.petId') // 'pet/petId'`
58
- *
59
- * @example PascalCase the final segment
60
- * `toFilePath('pet.Pet', pascalCase) // 'pet/Pet'`
61
- *
62
- * @example Suffix applied to the final segment only
63
- * `toFilePath('tag.tag', (part) => camelCase(part, { suffix: 'schema' })) // 'tag/tagSchema'`
64
- */
65
- function toFilePath(name, caseLast = camelCase) {
66
- const parts = name.split(/\.(?=[a-zA-Z])/);
67
- return parts.map((part, i) => i === parts.length - 1 ? caseLast(part) : camelCase(part)).filter(Boolean).join("/");
68
- }
69
- //#endregion
70
44
  //#region ../../internals/utils/src/reserved.ts
71
45
  /**
72
46
  * JavaScript and Java reserved words.
@@ -189,6 +163,188 @@ function ensureValidVarName(name) {
189
163
  if (!name || isValidVarName(name)) return name;
190
164
  return `_${name}`;
191
165
  }
166
+ /**
167
+ * Returns `true` when `name` is syntactically a valid identifier, ignoring reserved words.
168
+ *
169
+ * Reserved words and globals (`class`, `name`, `Date`, …) are valid as bare object-literal keys
170
+ * even though they are not valid variable names, so use this (not {@link isValidVarName}) when
171
+ * deciding whether an object key needs quoting.
172
+ *
173
+ * @example
174
+ * ```ts
175
+ * isIdentifier('name') // true
176
+ * isIdentifier('x-total')// false
177
+ * ```
178
+ */
179
+ function isIdentifier(name) {
180
+ return /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name);
181
+ }
182
+ //#endregion
183
+ //#region ../../internals/utils/src/strings.ts
184
+ /**
185
+ * Wraps a value in single quotes for emitting a single-quoted JavaScript string literal, escaping
186
+ * any backslash or single quote in the content.
187
+ *
188
+ * @example
189
+ * ```ts
190
+ * singleQuote('foo') // "'foo'"
191
+ * singleQuote("o'clock") // "'o\\'clock'"
192
+ * ```
193
+ */
194
+ function singleQuote(value) {
195
+ if (value === void 0 || value === null) return "''";
196
+ return `'${String(value).replace(/\\/g, "\\\\").replace(/'/g, "\\'")}'`;
197
+ }
198
+ /**
199
+ * Strips a single matching pair of `"..."`, `'...'`, or `` `...` `` from both ends of `text`.
200
+ * Returns the string unchanged when no balanced quote pair is found.
201
+ *
202
+ * @example
203
+ * ```ts
204
+ * trimQuotes('"hello"') // 'hello'
205
+ * trimQuotes('hello') // 'hello'
206
+ * ```
207
+ */
208
+ function trimQuotes(text) {
209
+ if (text.length >= 2) {
210
+ const first = text[0];
211
+ const last = text[text.length - 1];
212
+ if (first === "\"" && last === "\"" || first === "'" && last === "'" || first === "`" && last === "`") return text.slice(1, -1);
213
+ }
214
+ return text;
215
+ }
216
+ /**
217
+ * Serializes a primitive to a single-quoted string literal, stripping any surrounding quotes first.
218
+ *
219
+ * Escaping runs through `JSON.stringify`, then the result switches to single quotes so the generated
220
+ * code matches the repo style without a formatter.
221
+ *
222
+ * @example
223
+ * ```ts
224
+ * stringify('hello') // "'hello'"
225
+ * stringify('"hello"') // "'hello'"
226
+ * ```
227
+ */
228
+ function stringify(value) {
229
+ if (value === void 0 || value === null) return "''";
230
+ return `'${JSON.stringify(trimQuotes(value.toString())).slice(1, -1).replace(/\\"/g, "\"").replace(/'/g, "\\'")}'`;
231
+ }
232
+ /**
233
+ * Converts a pattern string into a `new RegExp(...)` constructor call or a regex literal string.
234
+ * Inline flags expressed as a `^(?im)` prefix are extracted and applied to the resulting expression.
235
+ * Pass `null` as the second argument to emit a `/pattern/flags` literal instead.
236
+ *
237
+ * @example
238
+ * ```ts
239
+ * toRegExpString('^(?im)foo') // 'new RegExp("^foo", "im")'
240
+ * toRegExpString('^(?im)foo', null) // '/^foo/im'
241
+ * ```
242
+ */
243
+ function toRegExpString(text, func = "RegExp") {
244
+ const raw = trimQuotes(text);
245
+ const match = raw.match(/^\^(\(\?([igmsuy]+)\))/i);
246
+ const replacementTarget = match?.[1] ?? "";
247
+ const matchedFlags = match?.[2];
248
+ const cleaned = raw.replace(/^\\?\//, "").replace(/\\?\/$/, "").replace(replacementTarget, "");
249
+ const { source, flags } = new RegExp(cleaned, matchedFlags);
250
+ if (func === null) return `/${source}/${flags}`;
251
+ return `new ${func}(${JSON.stringify(source)}${flags ? `, ${JSON.stringify(flags)}` : ""})`;
252
+ }
253
+ //#endregion
254
+ //#region ../../internals/utils/src/codegen.ts
255
+ const INDENT = " ";
256
+ /**
257
+ * Indents every non-empty line of `text` by one indent level, leaving blank lines empty.
258
+ */
259
+ function indentLines(text) {
260
+ if (!text) return "";
261
+ return text.split("\n").map((line) => line.trim() ? `${INDENT}${line}` : "").join("\n");
262
+ }
263
+ /**
264
+ * Renders an object key, quoting it with single quotes only when it is not a valid identifier.
265
+ * Reserved words and globals (`name`, `class`, …) are valid bare keys and stay unquoted.
266
+ *
267
+ * @example
268
+ * ```ts
269
+ * objectKey('name') // 'name'
270
+ * objectKey('x-total') // "'x-total'"
271
+ * ```
272
+ */
273
+ function objectKey(name) {
274
+ return isIdentifier(name) ? name : singleQuote(name);
275
+ }
276
+ /**
277
+ * Assembles a multi-line object literal from already-rendered `entries`, indenting each entry one
278
+ * level and closing the brace at column zero. Entries that are themselves multi-line objects indent
279
+ * cumulatively. Each entry ends with a trailing comma to match the formatter's multi-line style.
280
+ *
281
+ * @example
282
+ * ```ts
283
+ * buildObject(['id: z.number()', 'name: z.string()'])
284
+ * // '{\n id: z.number(),\n name: z.string(),\n}'
285
+ * ```
286
+ */
287
+ function buildObject(entries) {
288
+ if (entries.length === 0) return "{}";
289
+ return `{\n${entries.map((entry) => `${indentLines(entry)},`).join("\n")}\n}`;
290
+ }
291
+ /**
292
+ * Assembles a bracketed list (array by default) from already-rendered `items`. Keeps everything on
293
+ * one line when no item spans multiple lines, and otherwise puts each item on its own line, indented
294
+ * one level with a trailing comma and the closing bracket at column zero. Used for member lists such
295
+ * as `z.union([…])` and `z.array([…])`.
296
+ *
297
+ * @example
298
+ * ```ts
299
+ * buildList(['z.string()', 'z.number()'])
300
+ * // '[z.string(), z.number()]'
301
+ * ```
302
+ */
303
+ function buildList(items, brackets = ["[", "]"]) {
304
+ const [open, close] = brackets;
305
+ if (items.length === 0) return `${open}${close}`;
306
+ if (!items.some((item) => item.includes("\n"))) return `${open}${items.join(", ")}${close}`;
307
+ return `${open}\n${items.map((item) => `${indentLines(item)},`).join("\n")}\n${close}`;
308
+ }
309
+ /**
310
+ * Emits a lazy getter for a circular-ref property position, `get name() { return body }`. The key
311
+ * is quoted only when it is not a valid identifier. Used by the string printers to defer evaluation
312
+ * of a recursive schema until first access.
313
+ *
314
+ * @example
315
+ * ```ts
316
+ * lazyGetter({ name: 'parent', body: 'z.lazy(() => Pet)' })
317
+ * // "get parent() { return z.lazy(() => Pet) }"
318
+ * ```
319
+ */
320
+ function lazyGetter({ name, body }) {
321
+ return `get ${objectKey(name)}() { return ${body} }`;
322
+ }
323
+ //#endregion
324
+ //#region ../../internals/utils/src/fs.ts
325
+ /**
326
+ * Builds a nested file path from a dotted name. Splits on dots that precede a letter
327
+ * (so version numbers embedded in operationIds like `v2025.0` stay intact), camelCases
328
+ * every earlier segment, applies `caseLast` to the final segment, and joins with `/`.
329
+ *
330
+ * Empty segments are dropped before joining. They arise when the name starts with a dot
331
+ * followed by a letter (e.g. `..Schema` splits into `['..', 'Schema']` and `'..'` cases to
332
+ * an empty string). Without this a leading `/` would form, which `path.resolve` reads as an
333
+ * absolute path, letting generated files escape the configured output directory.
334
+ *
335
+ * @example Nested path from a dotted name
336
+ * `toFilePath('pet.petId') // 'pet/petId'`
337
+ *
338
+ * @example PascalCase the final segment
339
+ * `toFilePath('pet.Pet', pascalCase) // 'pet/Pet'`
340
+ *
341
+ * @example Suffix applied to the final segment only
342
+ * `toFilePath('tag.tag', (part) => camelCase(part, { suffix: 'schema' })) // 'tag/tagSchema'`
343
+ */
344
+ function toFilePath(name, caseLast = camelCase) {
345
+ const parts = name.split(/\.(?=[a-zA-Z])/);
346
+ return parts.map((part, i) => i === parts.length - 1 ? caseLast(part) : camelCase(part)).filter(Boolean).join("/");
347
+ }
192
348
  //#endregion
193
349
  //#region ../../internals/shared/src/params.ts
194
350
  const caseParamsCache = /* @__PURE__ */ new WeakMap();
@@ -386,12 +542,12 @@ function containsCodec(node, seen = /* @__PURE__ */ new Set()) {
386
542
  if (hasCodec(node)) return true;
387
543
  if (node.type === "ref") {
388
544
  if (!node.ref) return false;
389
- const refName = extractRefName(node.ref);
545
+ const refName = ast.extractRefName(node.ref);
390
546
  if (refName) {
391
547
  if (seen.has(refName)) return false;
392
548
  seen.add(refName);
393
549
  }
394
- const resolved = syncSchemaRef(node);
550
+ const resolved = ast.syncSchemaRef(node);
395
551
  if (resolved.type === "ref") return false;
396
552
  return containsCodec(resolved, seen);
397
553
  }
@@ -407,7 +563,7 @@ function containsCodec(node, seen = /* @__PURE__ */ new Set()) {
407
563
  * them to their input (encode) variant.
408
564
  */
409
565
  function collectCodecRefNames(node) {
410
- return ast.collect(node, { schema: (n) => n.type === "ref" && n.ref && containsCodec(n) ? extractRefName(n.ref) ?? void 0 : void 0 });
566
+ return ast.collect(node, { schema: (n) => n.type === "ref" && n.ref && containsCodec(n) ? ast.extractRefName(n.ref) ?? void 0 : void 0 });
411
567
  }
412
568
  /**
413
569
  * Whether the node is a plain inline object whose shape can be lifted into an `.extend({ … })`
@@ -428,9 +584,9 @@ function isObjectSchemaNode(node, cyclicSchemas) {
428
584
  if (node.nullable || node.optional || node.nullish) return false;
429
585
  if (node.type === "object") return true;
430
586
  if (node.type === "ref") {
431
- const refName = (node.ref ? extractRefName(node.ref) : void 0) ?? node.name;
587
+ const refName = (node.ref ? ast.extractRefName(node.ref) : void 0) ?? node.name;
432
588
  if (refName && cyclicSchemas?.has(refName)) return false;
433
- const resolved = syncSchemaRef(node);
589
+ const resolved = ast.syncSchemaRef(node);
434
590
  return resolved.type === "ref" || isObjectSchemaNode(resolved, cyclicSchemas);
435
591
  }
436
592
  if (node.type === "union") {
@@ -636,9 +792,9 @@ function strictOneOfMember$1(member, node, cyclicSchemas) {
636
792
  if (node.type === "object" && node.additionalProperties === void 0) return `${member}.strict()`;
637
793
  if (node.type === "ref") {
638
794
  if (member.startsWith("z.lazy(")) return member;
639
- const refName = (node.ref ? extractRefName(node.ref) : void 0) ?? node.name;
795
+ const refName = (node.ref ? ast.extractRefName(node.ref) : void 0) ?? node.name;
640
796
  if (refName && cyclicSchemas?.has(refName)) return member;
641
- const schema = syncSchemaRef(node);
797
+ const schema = ast.syncSchemaRef(node);
642
798
  if (schema.nullable || schema.optional || node.nullable || node.optional) return member;
643
799
  if (schema.type === "object" && (schema.additionalProperties === void 0 || schema.additionalProperties === false)) return `${member}.strict()`;
644
800
  }
@@ -663,8 +819,8 @@ function getMemberConstraint({ member, regexType }) {
663
819
  function buildZodObjectShape(ctx, node) {
664
820
  const objectNode = ast.narrowSchema(node, "object");
665
821
  if (!objectNode) return "{}";
666
- const isCyclic = (schema) => ctx.options.cyclicSchemas != null && containsCircularRef(schema, { circularSchemas: ctx.options.cyclicSchemas });
667
- return buildObject(mapSchemaProperties(objectNode, (schema) => {
822
+ const isCyclic = (schema) => ctx.options.cyclicSchemas != null && ast.containsCircularRef(schema, { circularSchemas: ctx.options.cyclicSchemas });
823
+ return buildObject(ast.mapSchemaProperties(objectNode, (schema) => {
668
824
  const hasSelfRef = isCyclic(schema);
669
825
  const savedCyclicSchemas = ctx.options.cyclicSchemas;
670
826
  if (hasSelfRef) ctx.options.cyclicSchemas = void 0;
@@ -673,7 +829,7 @@ function buildZodObjectShape(ctx, node) {
673
829
  return baseOutput;
674
830
  }).map(({ name: propName, property, output: baseOutput }) => {
675
831
  const { schema } = property;
676
- const meta = syncSchemaRef(schema);
832
+ const meta = ast.syncSchemaRef(schema);
677
833
  const descriptionToApply = schema.type !== "ref" && meta.type === "ref" ? void 0 : meta.description;
678
834
  const value = applyModifiers({
679
835
  value: baseOutput,
@@ -781,9 +937,9 @@ const printerZod = ast.createPrinter((options) => {
781
937
  },
782
938
  ref(node) {
783
939
  if (!node.name) return null;
784
- const refName = node.ref ? this.options.nameMapping?.get(node.ref) ?? extractRefName(node.ref) ?? node.name : node.name;
940
+ const refName = node.ref ? this.options.nameMapping?.get(node.ref) ?? ast.extractRefName(node.ref) ?? node.name : node.name;
785
941
  const useInputVariant = node.ref != null && this.options.direction === "input" && containsCodec(node);
786
- const resolvedName = node.ref ? useInputVariant ? this.options.resolver?.resolveInputSchemaName(refName) ?? refName : this.options.resolver?.default(refName, "function") ?? refName : node.name;
942
+ const resolvedName = node.ref ? useInputVariant ? this.options.resolver?.schema.inputName(refName) ?? refName : this.options.resolver?.name(refName) ?? refName : node.name;
787
943
  if (node.ref && this.options.cyclicSchemas?.has(refName)) return `z.lazy(() => ${resolvedName})`;
788
944
  return resolvedName;
789
945
  },
@@ -815,18 +971,18 @@ const printerZod = ast.createPrinter((options) => {
815
971
  })();
816
972
  },
817
973
  array(node) {
818
- const base = `z.array(${mapSchemaItems(node, (item) => this.transform(item)).map(({ output }) => output).filter(Boolean).join(", ") || this.transform(ast.factory.createSchema({ type: "unknown" }))})${lengthConstraints({
974
+ 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({
819
975
  ...node,
820
976
  regexType: this.options.regexType
821
977
  })}`;
822
978
  return node.unique ? `${base}.refine(items => new Set(items).size === items.length, { message: "Array entries must be unique" })` : base;
823
979
  },
824
980
  tuple(node) {
825
- return `z.tuple(${buildList(mapSchemaItems(node, (item) => this.transform(item)).map(({ output }) => output).filter(Boolean))})`;
981
+ return `z.tuple(${buildList(ast.mapSchemaItems(node, (item) => this.transform(item)).map(({ output }) => output).filter(Boolean))})`;
826
982
  },
827
983
  union(node) {
828
984
  const nodeMembers = node.members ?? [];
829
- const members = mapSchemaMembers(node, (memberNode) => this.transform(memberNode)).map(({ schema, output }) => output && node.strategy === "one" ? strictOneOfMember$1(output, schema, cyclicSchemaNames) : output).filter(Boolean);
985
+ const members = ast.mapSchemaMembers(node, (memberNode) => this.transform(memberNode)).map(({ schema, output }) => output && node.strategy === "one" ? strictOneOfMember$1(output, schema, cyclicSchemaNames) : output).filter(Boolean);
830
986
  if (members.length === 0) return "";
831
987
  if (members.length === 1) return members[0];
832
988
  const allDiscriminable = nodeMembers.every((m) => isObjectSchemaNode(m, cyclicSchemaNames));
@@ -857,7 +1013,7 @@ const printerZod = ast.createPrinter((options) => {
857
1013
  const { keysToOmit } = this.options;
858
1014
  const transformed = this.transform(node);
859
1015
  if (!transformed) return null;
860
- const meta = syncSchemaRef(node);
1016
+ const meta = ast.syncSchemaRef(node);
861
1017
  return applyModifiers({
862
1018
  value: (() => {
863
1019
  if (!keysToOmit?.length || meta.primitive !== "object" || meta.type === "union" && meta.discriminatorPropertyName) return transformed;
@@ -902,8 +1058,8 @@ function getMemberConstraintMini({ member, regexType }) {
902
1058
  function buildZodMiniObjectShape(ctx, node) {
903
1059
  const objectNode = ast.narrowSchema(node, "object");
904
1060
  if (!objectNode) return "{}";
905
- const isCyclic = (schema) => ctx.options.cyclicSchemas != null && containsCircularRef(schema, { circularSchemas: ctx.options.cyclicSchemas });
906
- return buildObject(mapSchemaProperties(objectNode, (schema) => {
1061
+ const isCyclic = (schema) => ctx.options.cyclicSchemas != null && ast.containsCircularRef(schema, { circularSchemas: ctx.options.cyclicSchemas });
1062
+ return buildObject(ast.mapSchemaProperties(objectNode, (schema) => {
907
1063
  const hasSelfRef = isCyclic(schema);
908
1064
  const savedCyclicSchemas = ctx.options.cyclicSchemas;
909
1065
  if (hasSelfRef) ctx.options.cyclicSchemas = void 0;
@@ -912,7 +1068,7 @@ function buildZodMiniObjectShape(ctx, node) {
912
1068
  return baseOutput;
913
1069
  }).map(({ name: propName, property, output: baseOutput }) => {
914
1070
  const { schema } = property;
915
- const meta = syncSchemaRef(schema);
1071
+ const meta = ast.syncSchemaRef(schema);
916
1072
  const value = applyMiniModifiers({
917
1073
  value: baseOutput,
918
1074
  schema,
@@ -1009,8 +1165,8 @@ const printerZodMini = ast.createPrinter((options) => {
1009
1165
  },
1010
1166
  ref(node) {
1011
1167
  if (!node.name) return null;
1012
- const refName = node.ref ? this.options.nameMapping?.get(node.ref) ?? extractRefName(node.ref) ?? node.name : node.name;
1013
- const resolvedName = node.ref ? this.options.resolver?.default(refName, "function") ?? refName : node.name;
1168
+ const refName = node.ref ? this.options.nameMapping?.get(node.ref) ?? ast.extractRefName(node.ref) ?? node.name : node.name;
1169
+ const resolvedName = node.ref ? this.options.resolver?.name(refName) ?? refName : node.name;
1014
1170
  if (node.ref && this.options.cyclicSchemas?.has(refName)) return `z.lazy(() => ${resolvedName})`;
1015
1171
  return resolvedName;
1016
1172
  },
@@ -1040,18 +1196,18 @@ const printerZodMini = ast.createPrinter((options) => {
1040
1196
  return objectBase;
1041
1197
  },
1042
1198
  array(node) {
1043
- const base = `z.array(${mapSchemaItems(node, (item) => this.transform(item)).map(({ output }) => output).filter(Boolean).join(", ") || this.transform(ast.factory.createSchema({ type: "unknown" }))})${lengthChecksMini({
1199
+ 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({
1044
1200
  ...node,
1045
1201
  regexType: this.options.regexType
1046
1202
  })}`;
1047
1203
  return node.unique ? `${base}.refine(items => new Set(items).size === items.length, { message: "Array entries must be unique" })` : base;
1048
1204
  },
1049
1205
  tuple(node) {
1050
- return `z.tuple(${buildList(mapSchemaItems(node, (item) => this.transform(item)).map(({ output }) => output).filter(Boolean))})`;
1206
+ return `z.tuple(${buildList(ast.mapSchemaItems(node, (item) => this.transform(item)).map(({ output }) => output).filter(Boolean))})`;
1051
1207
  },
1052
1208
  union(node) {
1053
1209
  const nodeMembers = node.members ?? [];
1054
- const members = mapSchemaMembers(node, (memberNode) => this.transform(memberNode)).map(({ schema, output }) => output && node.strategy === "one" ? strictOneOfMember(output, schema) : output).filter(Boolean);
1210
+ const members = ast.mapSchemaMembers(node, (memberNode) => this.transform(memberNode)).map(({ schema, output }) => output && node.strategy === "one" ? strictOneOfMember(output, schema) : output).filter(Boolean);
1055
1211
  if (members.length === 0) return "";
1056
1212
  if (members.length === 1) return members[0];
1057
1213
  const allDiscriminable = nodeMembers.every((m) => isObjectSchemaNode(m, cyclicSchemaNames));
@@ -1082,7 +1238,7 @@ const printerZodMini = ast.createPrinter((options) => {
1082
1238
  const { keysToOmit } = this.options;
1083
1239
  const transformed = this.transform(node);
1084
1240
  if (!transformed) return null;
1085
- const meta = syncSchemaRef(node);
1241
+ const meta = ast.syncSchemaRef(node);
1086
1242
  return applyMiniModifiers({
1087
1243
  value: (() => {
1088
1244
  if (!keysToOmit?.length || meta.primitive !== "object" || meta.type === "union" && meta.discriminatorPropertyName) return transformed;
@@ -1176,22 +1332,20 @@ const zodGenerator = defineGenerator({
1176
1332
  const hasCodec = !mini && containsCodec(node);
1177
1333
  const codecRefNames = new Set(hasCodec ? collectCodecRefNames(node) : []);
1178
1334
  const importEntries = adapter.getImports(node, (schemaName) => ({
1179
- name: resolver.resolveSchemaName(schemaName),
1180
- path: resolver.resolveFile({
1335
+ name: resolver.name(schemaName),
1336
+ path: resolver.file({
1181
1337
  name: schemaName,
1182
- extname: ".ts"
1183
- }, {
1338
+ extname: ".ts",
1184
1339
  root,
1185
1340
  output,
1186
1341
  group: group ?? void 0
1187
1342
  }).path
1188
1343
  }));
1189
1344
  const inputImportEntries = hasCodec ? [...codecRefNames].map((schemaName) => ({
1190
- name: [resolver.resolveInputSchemaName(schemaName)],
1191
- path: resolver.resolveFile({
1345
+ name: [resolver.schema.inputName(schemaName)],
1346
+ path: resolver.file({
1192
1347
  name: schemaName,
1193
- extname: ".ts"
1194
- }, {
1348
+ extname: ".ts",
1195
1349
  root,
1196
1350
  output,
1197
1351
  group: group ?? void 0
@@ -1205,17 +1359,16 @@ const zodGenerator = defineGenerator({
1205
1359
  return true;
1206
1360
  });
1207
1361
  const meta = {
1208
- name: resolver.resolveSchemaName(node.name),
1209
- file: resolver.resolveFile({
1362
+ name: resolver.name(node.name),
1363
+ file: resolver.file({
1210
1364
  name: node.name,
1211
- extname: ".ts"
1212
- }, {
1365
+ extname: ".ts",
1213
1366
  root,
1214
1367
  output,
1215
1368
  group: group ?? void 0
1216
1369
  })
1217
1370
  };
1218
- const inferTypeName = inferred ? resolver.resolveSchemaTypeName(node.name) : null;
1371
+ const inferTypeName = inferred ? resolver.schema.typeName(node.name) : null;
1219
1372
  const nameMapping = adapter.options.nameMapping;
1220
1373
  const stdPrinters = mini ? null : getStdPrinters(resolver, {
1221
1374
  coercion,
@@ -1237,7 +1390,7 @@ const zodGenerator = defineGenerator({
1237
1390
  baseName: meta.file.baseName,
1238
1391
  path: meta.file.path,
1239
1392
  meta: meta.file.meta,
1240
- banner: resolver.resolveBanner(ctx.meta, {
1393
+ banner: resolver.default.banner(ctx.meta, {
1241
1394
  output,
1242
1395
  config,
1243
1396
  file: {
@@ -1245,7 +1398,7 @@ const zodGenerator = defineGenerator({
1245
1398
  baseName: meta.file.baseName
1246
1399
  }
1247
1400
  }),
1248
- footer: resolver.resolveFooter(ctx.meta, {
1401
+ footer: resolver.default.footer(ctx.meta, {
1249
1402
  output,
1250
1403
  config,
1251
1404
  file: {
@@ -1276,10 +1429,10 @@ const zodGenerator = defineGenerator({
1276
1429
  cyclic: cyclicSchemas.has(node.name)
1277
1430
  }),
1278
1431
  hasCodec && stdPrinters && /* @__PURE__ */ jsx(Zod, {
1279
- name: resolver.resolveInputSchemaName(node.name),
1432
+ name: resolver.schema.inputName(node.name),
1280
1433
  node,
1281
1434
  printer: stdPrinters.input,
1282
- inferTypeName: inferred ? resolver.resolveInputSchemaTypeName(node.name) : null,
1435
+ inferTypeName: inferred ? resolver.schema.inputTypeName(node.name) : null,
1283
1436
  cyclic: cyclicSchemas.has(node.name)
1284
1437
  })
1285
1438
  ]
@@ -1292,12 +1445,11 @@ const zodGenerator = defineGenerator({
1292
1445
  const dateType = adapter.options.dateType;
1293
1446
  const isZodImport = ZOD_NAMESPACE_IMPORTS.has(importPath);
1294
1447
  const params = caseParams(node.parameters, "camelcase");
1295
- const meta = { file: resolver.resolveFile({
1448
+ const meta = { file: resolver.file({
1296
1449
  name: node.operationId,
1297
1450
  extname: ".ts",
1298
1451
  tag: node.tags[0] ?? "default",
1299
- path: node.path
1300
- }, {
1452
+ path: node.path,
1301
1453
  root,
1302
1454
  output,
1303
1455
  group: group ?? void 0
@@ -1306,14 +1458,13 @@ const zodGenerator = defineGenerator({
1306
1458
  const nameMapping = adapter.options.nameMapping;
1307
1459
  function renderSchemaEntry({ schema, name, keysToOmit, direction = "output" }) {
1308
1460
  if (!schema) return null;
1309
- const inferTypeName = inferred ? resolver.resolveTypeName(name) : null;
1461
+ const inferTypeName = inferred ? resolver.schema.type(name) : null;
1310
1462
  const codecRefNames = direction === "input" && !mini ? new Set(collectCodecRefNames(schema)) : null;
1311
1463
  const imports = adapter.getImports(schema, (schemaName) => ({
1312
- name: codecRefNames?.has(schemaName) ? resolver.resolveInputSchemaName(schemaName) : resolver.resolveSchemaName(schemaName),
1313
- path: resolver.resolveFile({
1464
+ name: codecRefNames?.has(schemaName) ? resolver.schema.inputName(schemaName) : resolver.name(schemaName),
1465
+ path: resolver.file({
1314
1466
  name: schemaName,
1315
- extname: ".ts"
1316
- }, {
1467
+ extname: ".ts",
1317
1468
  root,
1318
1469
  output,
1319
1470
  group: group ?? void 0
@@ -1391,30 +1542,30 @@ const zodGenerator = defineGenerator({
1391
1542
  }
1392
1543
  const paramSchemas = params.map((param) => renderSchemaEntry({
1393
1544
  schema: param.schema,
1394
- name: resolver.resolveParamName(node, param),
1545
+ name: resolver.param.name(node, param),
1395
1546
  direction: "input"
1396
1547
  }));
1397
1548
  const responseSchemas = node.responses.map((res) => {
1398
1549
  const variants = (res.content ?? []).filter((entry) => entry.schema);
1399
- if (variants.length > 1) return buildContentTypeVariants(res.content, resolver.resolveResponseStatusName(node, res.statusCode));
1550
+ if (variants.length > 1) return buildContentTypeVariants(res.content, resolver.response.status(node, res.statusCode));
1400
1551
  const primary = variants[0] ?? res.content?.[0];
1401
1552
  return renderSchemaEntry({
1402
1553
  schema: primary?.schema ?? null,
1403
- name: resolver.resolveResponseStatusName(node, res.statusCode),
1554
+ name: resolver.response.status(node, res.statusCode),
1404
1555
  keysToOmit: primary?.keysToOmit
1405
1556
  });
1406
1557
  });
1407
1558
  const responsesWithSchema = node.responses.filter((res) => res.content?.some((entry) => entry.schema));
1408
1559
  const successResponsesWithSchema = getSuccessResponses(responsesWithSchema);
1409
1560
  const responseUnionSchema = responsesWithSchema.length > 0 ? (() => {
1410
- const responseUnionName = resolver.resolveResponseName(node);
1561
+ const responseUnionName = resolver.response.response(node);
1411
1562
  if (new Set(successResponsesWithSchema.flatMap((res) => (res.content ?? []).flatMap((entry) => entry.schema ? adapter.getImports(entry.schema, (schemaName) => ({
1412
- name: resolver.resolveSchemaName(schemaName),
1563
+ name: resolver.name(schemaName),
1413
1564
  path: ""
1414
1565
  })).flatMap((imp) => Array.isArray(imp.name) ? imp.name : [imp.name]) : []))).has(responseUnionName)) return null;
1415
1566
  const members = successResponsesWithSchema.map((res) => ast.factory.createSchema({
1416
1567
  type: "ref",
1417
- name: resolver.resolveResponseStatusName(node, res.statusCode)
1568
+ name: resolver.response.status(node, res.statusCode)
1418
1569
  }));
1419
1570
  if (members.length === 0) return renderSchemaEntry({
1420
1571
  schema: ast.factory.createSchema({ type: "unknown" }),
@@ -1430,14 +1581,14 @@ const zodGenerator = defineGenerator({
1430
1581
  })() : null;
1431
1582
  const errorResponsesWithSchema = responsesWithSchema.filter((res) => !isSuccessStatusCode(res.statusCode));
1432
1583
  const errorUnionSchema = errorResponsesWithSchema.length > 0 ? (() => {
1433
- const errorUnionName = resolver.resolveErrorName(node);
1584
+ const errorUnionName = resolver.response.error(node);
1434
1585
  if (new Set(errorResponsesWithSchema.flatMap((res) => (res.content ?? []).flatMap((entry) => entry.schema ? adapter.getImports(entry.schema, (schemaName) => ({
1435
- name: resolver.resolveSchemaName(schemaName),
1586
+ name: resolver.name(schemaName),
1436
1587
  path: ""
1437
1588
  })).flatMap((imp) => Array.isArray(imp.name) ? imp.name : [imp.name]) : []))).has(errorUnionName)) return null;
1438
1589
  const members = errorResponsesWithSchema.map((res) => ast.factory.createSchema({
1439
1590
  type: "ref",
1440
- name: resolver.resolveResponseStatusName(node, res.statusCode)
1591
+ name: resolver.response.status(node, res.statusCode)
1441
1592
  }));
1442
1593
  return renderSchemaEntry({
1443
1594
  schema: members.length === 1 ? members[0] : ast.factory.createSchema({
@@ -1458,12 +1609,12 @@ const zodGenerator = defineGenerator({
1458
1609
  ...entry.schema,
1459
1610
  description: node.requestBody.description ?? entry.schema.description
1460
1611
  },
1461
- name: resolver.resolveDataName(node),
1612
+ name: resolver.response.body(node),
1462
1613
  keysToOmit: entry.keysToOmit,
1463
1614
  direction: "input"
1464
1615
  });
1465
1616
  }
1466
- return buildContentTypeVariants(requestBodyContent, resolver.resolveDataName(node), (schema) => ({
1617
+ return buildContentTypeVariants(requestBodyContent, resolver.response.body(node), (schema) => ({
1467
1618
  ...schema,
1468
1619
  description: node.requestBody.description ?? schema.description
1469
1620
  }), "input");
@@ -1472,7 +1623,7 @@ const zodGenerator = defineGenerator({
1472
1623
  baseName: meta.file.baseName,
1473
1624
  path: meta.file.path,
1474
1625
  meta: meta.file.meta,
1475
- banner: resolver.resolveBanner(ctx.meta, {
1626
+ banner: resolver.default.banner(ctx.meta, {
1476
1627
  output,
1477
1628
  config,
1478
1629
  file: {
@@ -1480,7 +1631,7 @@ const zodGenerator = defineGenerator({
1480
1631
  baseName: meta.file.baseName
1481
1632
  }
1482
1633
  }),
1483
- footer: resolver.resolveFooter(ctx.meta, {
1634
+ footer: resolver.default.footer(ctx.meta, {
1484
1635
  output,
1485
1636
  config,
1486
1637
  file: {
@@ -1516,64 +1667,63 @@ const zodGenerator = defineGenerator({
1516
1667
  * ```ts
1517
1668
  * import { resolverZod } from '@kubb/plugin-zod'
1518
1669
  *
1519
- * resolverZod.default('list pets', 'function') // 'listPetsSchema'
1520
- * resolverZod.resolveSchemaTypeName('pet') // 'PetSchemaType'
1670
+ * resolverZod.name('list pets') // 'listPetsSchema'
1671
+ * resolverZod.schema.typeName('pet') // 'PetSchemaType'
1521
1672
  * ```
1522
1673
  */
1523
- const resolverZod = defineResolver(() => {
1524
- return {
1525
- name: "default",
1526
- pluginName: "plugin-zod",
1527
- default(name, type) {
1528
- if (type === "file") return toFilePath(name, (part) => camelCase(part, { suffix: "schema" }));
1529
- return ensureValidVarName(camelCase(name, { suffix: type ? "schema" : void 0 }));
1530
- },
1531
- resolveSchemaName(name) {
1532
- return ensureValidVarName(camelCase(name, { suffix: "schema" }));
1533
- },
1534
- resolveSchemaTypeName(name) {
1674
+ const resolverZod = createResolver({
1675
+ pluginName: "plugin-zod",
1676
+ name(name) {
1677
+ return ensureValidVarName(camelCase(name, { suffix: "schema" }));
1678
+ },
1679
+ file: { baseName({ name, extname }) {
1680
+ return `${toFilePath(name, (part) => camelCase(part, { suffix: "schema" }))}${extname}`;
1681
+ } },
1682
+ schema: {
1683
+ typeName(name) {
1535
1684
  return ensureValidVarName(pascalCase(name, { suffix: "schema type" }));
1536
1685
  },
1537
- resolveInputSchemaName(name) {
1538
- return this.resolveSchemaName(`${name} input`);
1539
- },
1540
- resolveInputSchemaTypeName(name) {
1541
- return this.resolveSchemaTypeName(`${name} input`);
1542
- },
1543
- resolveTypeName(name) {
1686
+ type(name) {
1544
1687
  return ensureValidVarName(pascalCase(name, { suffix: "type" }));
1545
1688
  },
1546
- resolvePathName(name, type) {
1547
- return this.default(name, type);
1548
- },
1549
- resolveParamName(node, param) {
1550
- return this.resolveSchemaName(`${node.operationId} ${param.in} ${param.name}`);
1689
+ inputName(name) {
1690
+ return this.name(`${name} input`);
1551
1691
  },
1552
- resolveResponseStatusName(node, statusCode) {
1553
- return this.resolveSchemaName(`${node.operationId} Status ${statusCode}`);
1692
+ inputTypeName(name) {
1693
+ return this.schema.typeName(`${name} input`);
1694
+ }
1695
+ },
1696
+ param: {
1697
+ name(node, param) {
1698
+ return this.name(`${node.operationId} ${param.in} ${param.name}`);
1554
1699
  },
1555
- resolveDataName(node) {
1556
- return this.resolveSchemaName(`${node.operationId} Data`);
1700
+ path(node, param) {
1701
+ return this.param.name(node, param);
1557
1702
  },
1558
- resolveResponsesName(node) {
1559
- return this.resolveSchemaName(`${node.operationId} Responses`);
1703
+ query(node, param) {
1704
+ return this.param.name(node, param);
1560
1705
  },
1561
- resolveResponseName(node) {
1562
- return this.resolveSchemaName(`${node.operationId} Response`);
1706
+ headers(node, param) {
1707
+ return this.param.name(node, param);
1708
+ }
1709
+ },
1710
+ response: {
1711
+ status(node, statusCode) {
1712
+ return this.name(`${node.operationId} Status ${statusCode}`);
1563
1713
  },
1564
- resolveErrorName(node) {
1565
- return this.resolveSchemaName(`${node.operationId} Error`);
1714
+ body(node) {
1715
+ return this.name(`${node.operationId} Body`);
1566
1716
  },
1567
- resolvePathParamsName(node, param) {
1568
- return this.resolveParamName(node, param);
1717
+ responses(node) {
1718
+ return this.name(`${node.operationId} Responses`);
1569
1719
  },
1570
- resolveQueryParamsName(node, param) {
1571
- return this.resolveParamName(node, param);
1720
+ response(node) {
1721
+ return this.name(`${node.operationId} Response`);
1572
1722
  },
1573
- resolveHeaderParamsName(node, param) {
1574
- return this.resolveParamName(node, param);
1723
+ error(node) {
1724
+ return this.name(`${node.operationId} Error`);
1575
1725
  }
1576
- };
1726
+ }
1577
1727
  });
1578
1728
  //#endregion
1579
1729
  //#region src/plugin.ts
@@ -1591,7 +1741,7 @@ const pluginZodName = "plugin-zod";
1591
1741
  *
1592
1742
  * @example
1593
1743
  * ```ts
1594
- * import { defineConfig } from 'kubb'
1744
+ * import { defineConfig } from 'kubb/config'
1595
1745
  * import { pluginTs } from '@kubb/plugin-ts'
1596
1746
  * import { pluginZod } from '@kubb/plugin-zod'
1597
1747
  *
@@ -1632,10 +1782,7 @@ const pluginZod = definePlugin((options) => {
1632
1782
  mini,
1633
1783
  printer
1634
1784
  });
1635
- ctx.setResolver(userResolver ? {
1636
- ...resolverZod,
1637
- ...userResolver
1638
- } : resolverZod);
1785
+ ctx.setResolver(userResolver ? Resolver.merge(resolverZod, userResolver) : resolverZod);
1639
1786
  if (userMacros?.length) ctx.setMacros(userMacros);
1640
1787
  ctx.addGenerator(zodGenerator);
1641
1788
  } }