@kubb/plugin-zod 5.0.0-beta.22 → 5.0.0-beta.27

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
@@ -222,41 +222,53 @@ type ResolverZod = Resolver & ast.OperationParamsResolver & {
222
222
  };
223
223
  type Options = {
224
224
  /**
225
- * @default 'zod'
225
+ * Where the generated Zod schemas are written and how they are exported.
226
+ *
227
+ * @default { path: 'zod', barrel: { type: 'named' } }
226
228
  */
227
229
  output?: Output;
228
230
  /**
229
- * Group the Zod schemas based on the provided name.
231
+ * Split generated files into subfolders based on the operation's tag.
230
232
  */
231
233
  group?: Group;
232
234
  /**
233
- * Tags, operations, or paths to exclude from generation.
235
+ * Skip operations matching at least one entry in the list.
234
236
  */
235
237
  exclude?: Array<Exclude>;
236
238
  /**
237
- * Tags, operations, or paths to include in generation.
239
+ * Restrict generation to operations matching at least one entry in the list.
238
240
  */
239
241
  include?: Array<Include>;
240
242
  /**
241
- * Override options for specific tags, operations, or paths.
243
+ * Apply a different options object to operations matching a pattern.
242
244
  */
243
245
  override?: Array<Override<ResolvedOptions>>;
244
246
  /**
245
- * Import path for Zod package.
247
+ * Module specifier used in the `import { z } from '...'` statement.
248
+ * Use `'zod/mini'` for the tree-shakeable bundle.
246
249
  *
247
250
  * @default 'zod'
248
251
  */
249
252
  importPath?: 'zod' | 'zod/mini' | (string & {});
250
253
  /**
251
- * Add TypeScript type annotations to generated schemas.
254
+ * Tie each Zod schema to its TypeScript type from `@kubb/plugin-ts`. Requires
255
+ * `@kubb/plugin-ts` in the plugins list. TypeScript fails compilation when the
256
+ * schema drifts from the type.
252
257
  */
253
258
  typed?: boolean;
254
259
  /**
255
- * Return schemas as inferred types using `z.infer`.
260
+ * Export a `z.infer<typeof schema>` type alias next to every generated schema.
261
+ * Lets the Zod schema act as the single source of truth.
256
262
  */
257
263
  inferred?: boolean;
258
264
  /**
259
- * Apply coercion to string values or configure coercion per type.
265
+ * Wrap schemas in `z.coerce` so input is coerced before validation. Useful for
266
+ * form data and query params where everything arrives as a string.
267
+ * - `true` coerces strings, numbers, and dates.
268
+ * - Object form picks per-primitive coercion.
269
+ *
270
+ * @default false
271
+ * @see https://zod.dev/?id=coercion-for-primitives
260
272
  */
261
273
  coercion?: boolean | {
262
274
  dates?: boolean;
@@ -264,50 +276,59 @@ type Options = {
264
276
  numbers?: boolean;
265
277
  };
266
278
  /**
267
- * Generate operation-level schemas (grouped by operationId).
279
+ * Emit an `operations.ts` file with request body, query/path params, and per-status
280
+ * response schemas grouped by operation.
268
281
  */
269
282
  operations?: boolean;
270
283
  /**
271
- * Validator to use for UUID format: `uuid` or `guid`.
284
+ * Validator for `format: uuid` properties.
285
+ * - `'uuid'` — `z.uuid()`. Standard RFC 4122.
286
+ * - `'guid'` — `z.guid()`. Accepts Microsoft-style GUIDs.
272
287
  *
273
288
  * @default 'uuid'
274
289
  */
275
290
  guidType?: 'uuid' | 'guid';
276
291
  /**
277
- * Use Zod Mini's functional API for better tree-shaking.
292
+ * Switch to Zod Mini's functional API for better tree-shaking. Also defaults
293
+ * `importPath` to `'zod/mini'`.
278
294
  *
279
295
  * @default false
296
+ * @beta
280
297
  */
281
298
  mini?: boolean;
282
299
  /**
283
- * Callback to wrap the generated schema output.
284
- *
285
- * Useful for adding metadata like `.openapi()` or extension helpers.
300
+ * Wrap the generated Zod schema string with extra calls. Receives the raw output
301
+ * and the originating `SchemaNode`. Useful for round-tripping OpenAPI metadata
302
+ * back into Zod (e.g. `.openapi(...)`).
286
303
  */
287
304
  wrapOutput?: (arg: {
288
305
  output: string;
289
306
  schema: ast.SchemaNode;
290
307
  }) => string | undefined;
291
308
  /**
292
- * Apply casing to parameter names.
309
+ * Rename properties inside path/query/header schemas. Body schemas are unaffected.
310
+ *
311
+ * @note Must match the value of `paramsCasing` on `@kubb/plugin-ts`.
293
312
  */
294
313
  paramsCasing?: 'camelcase';
295
314
  /**
296
- * Additional generators alongside the default generators.
315
+ * Custom generators that run alongside the built-in Zod generators.
297
316
  */
298
317
  generators?: Array<Generator<PluginZod>>;
299
318
  /**
300
- * Override naming conventions for schema names and types.
319
+ * Override how schema and operation names are built. Methods you omit fall back
320
+ * to the default `resolverZod`.
301
321
  */
302
322
  resolver?: Partial<ResolverZod> & ThisType<ResolverZod>;
303
323
  /**
304
- * Override printer node handlers to customize rendering of specific schema types.
324
+ * Replace the Zod handler for a specific schema type (`'integer'`, `'date'`, ...).
325
+ * When `mini: true`, overrides target the Zod Mini printer instead.
305
326
  */
306
327
  printer?: {
307
328
  nodes?: PrinterZodNodes | PrinterZodMiniNodes;
308
329
  };
309
330
  /**
310
- * AST visitor to transform schema and operation nodes.
331
+ * AST visitor applied to each schema or operation node before printing.
311
332
  */
312
333
  transformer?: ast.Visitor;
313
334
  };
@@ -316,7 +337,7 @@ type ResolvedOptions = {
316
337
  exclude: Array<Exclude>;
317
338
  include: Array<Include> | undefined;
318
339
  override: Array<Override<ResolvedOptions>>;
319
- group: Group | undefined;
340
+ group: Group | null;
320
341
  typed: NonNullable<Options['typed']>;
321
342
  inferred: NonNullable<Options['inferred']>;
322
343
  importPath: NonNullable<Options['importPath']>;
@@ -338,23 +359,42 @@ declare global {
338
359
  }
339
360
  //#endregion
340
361
  //#region src/generators/zodGenerator.d.ts
362
+ /**
363
+ * Built-in generator for `@kubb/plugin-zod`. Emits one Zod schema per
364
+ * schema in the spec plus per-operation request/response/parameter schemas.
365
+ * When `mini: true`, schemas use the Zod Mini functional API instead of
366
+ * chainable methods.
367
+ */
341
368
  declare const zodGenerator: _$_kubb_core0.Generator<PluginZod, unknown>;
342
369
  //#endregion
343
370
  //#region src/plugin.d.ts
344
371
  /**
345
- * Canonical plugin name for `@kubb/plugin-zod`, used in driver lookups and warnings.
372
+ * Canonical plugin name for `@kubb/plugin-zod`. Used for driver lookups and
373
+ * cross-plugin dependency references.
346
374
  */
347
375
  declare const pluginZodName = "plugin-zod";
348
376
  /**
349
- * Generates Zod validation schemas from an OpenAPI specification.
350
- * Walks schemas and operations, delegates to generators, and writes barrel files
351
- * based on the configured `barrelType`.
377
+ * Generates Zod v4 schemas from an OpenAPI spec. Use them to validate API
378
+ * responses at runtime, build form schemas, or feed back into router libraries
379
+ * that consume Zod (tRPC, Hono, Elysia). Pair with `@kubb/plugin-client` and
380
+ * set the client's `parser: 'zod'` to validate every response automatically.
352
381
  *
353
- * @example Zod schema generator
382
+ * @example
354
383
  * ```ts
355
- * import pluginZod from '@kubb/plugin-zod'
384
+ * import { defineConfig } from 'kubb'
385
+ * import { pluginTs } from '@kubb/plugin-ts'
386
+ * import { pluginZod } from '@kubb/plugin-zod'
387
+ *
356
388
  * export default defineConfig({
357
- * plugins: [pluginZod({ output: { path: 'zod' } })]
389
+ * input: { path: './petStore.yaml' },
390
+ * output: { path: './src/gen' },
391
+ * plugins: [
392
+ * pluginTs(),
393
+ * pluginZod({
394
+ * output: { path: './zod' },
395
+ * typed: true,
396
+ * }),
397
+ * ],
358
398
  * })
359
399
  * ```
360
400
  */
@@ -362,12 +402,17 @@ declare const pluginZod: (options?: Options | undefined) => _$_kubb_core0.Plugin
362
402
  //#endregion
363
403
  //#region src/resolvers/resolverZod.d.ts
364
404
  /**
365
- * Naming convention resolver for Zod plugin.
405
+ * Default resolver used by `@kubb/plugin-zod`. Decides the names and file
406
+ * paths for every generated Zod schema. Schemas use camelCase with a
407
+ * `Schema` suffix (`listPetsSchema`); their inferred types use PascalCase.
366
408
  *
367
- * Provides default naming helpers using camelCase with a `Schema` suffix for schemas.
409
+ * @example Resolve schema and type names
410
+ * ```ts
411
+ * import { resolverZod } from '@kubb/plugin-zod'
368
412
  *
369
- * @example
370
- * `resolverZod.default('list pets', 'function') // 'listPetsSchema'`
413
+ * resolverZod.default('list pets', 'function') // 'listPetsSchema'
414
+ * resolverZod.resolveSchemaTypeName('pet') // 'PetSchema'
415
+ * ```
371
416
  */
372
417
  declare const resolverZod: ResolverZod;
373
418
  //#endregion
package/dist/index.js CHANGED
@@ -126,6 +126,129 @@ function toRegExpString(text, func = "RegExp") {
126
126
  return `new ${func}(${JSON.stringify(source)}${flags ? `, ${JSON.stringify(flags)}` : ""})`;
127
127
  }
128
128
  //#endregion
129
+ //#region ../../internals/utils/src/reserved.ts
130
+ /**
131
+ * JavaScript and Java reserved words.
132
+ * @link https://github.com/jonschlinkert/reserved/blob/master/index.js
133
+ */
134
+ const reservedWords = new Set([
135
+ "abstract",
136
+ "arguments",
137
+ "boolean",
138
+ "break",
139
+ "byte",
140
+ "case",
141
+ "catch",
142
+ "char",
143
+ "class",
144
+ "const",
145
+ "continue",
146
+ "debugger",
147
+ "default",
148
+ "delete",
149
+ "do",
150
+ "double",
151
+ "else",
152
+ "enum",
153
+ "eval",
154
+ "export",
155
+ "extends",
156
+ "false",
157
+ "final",
158
+ "finally",
159
+ "float",
160
+ "for",
161
+ "function",
162
+ "goto",
163
+ "if",
164
+ "implements",
165
+ "import",
166
+ "in",
167
+ "instanceof",
168
+ "int",
169
+ "interface",
170
+ "let",
171
+ "long",
172
+ "native",
173
+ "new",
174
+ "null",
175
+ "package",
176
+ "private",
177
+ "protected",
178
+ "public",
179
+ "return",
180
+ "short",
181
+ "static",
182
+ "super",
183
+ "switch",
184
+ "synchronized",
185
+ "this",
186
+ "throw",
187
+ "throws",
188
+ "transient",
189
+ "true",
190
+ "try",
191
+ "typeof",
192
+ "var",
193
+ "void",
194
+ "volatile",
195
+ "while",
196
+ "with",
197
+ "yield",
198
+ "Array",
199
+ "Date",
200
+ "hasOwnProperty",
201
+ "Infinity",
202
+ "isFinite",
203
+ "isNaN",
204
+ "isPrototypeOf",
205
+ "length",
206
+ "Math",
207
+ "name",
208
+ "NaN",
209
+ "Number",
210
+ "Object",
211
+ "prototype",
212
+ "String",
213
+ "toString",
214
+ "undefined",
215
+ "valueOf"
216
+ ]);
217
+ /**
218
+ * Returns `true` when `name` is a syntactically valid JavaScript variable name.
219
+ *
220
+ * @example
221
+ * ```ts
222
+ * isValidVarName('status') // true
223
+ * isValidVarName('class') // false (reserved word)
224
+ * isValidVarName('42foo') // false (starts with digit)
225
+ * ```
226
+ */
227
+ function isValidVarName(name) {
228
+ if (!name || reservedWords.has(name)) return false;
229
+ return /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name);
230
+ }
231
+ /**
232
+ * Returns `name` when it's a syntactically valid JavaScript variable name,
233
+ * otherwise prefixes it with `_` so the result is a valid identifier.
234
+ *
235
+ * Useful for sanitizing OpenAPI schema names or operation IDs that start with
236
+ * a digit (e.g. `409`, `504AccountCancel`) before using them as exported
237
+ * variable, type, or function names.
238
+ *
239
+ * @example
240
+ * ```ts
241
+ * ensureValidVarName('409') // '_409'
242
+ * ensureValidVarName('504AccountCancel') // '_504AccountCancel'
243
+ * ensureValidVarName('Pet') // 'Pet'
244
+ * ensureValidVarName('class') // '_class'
245
+ * ```
246
+ */
247
+ function ensureValidVarName(name) {
248
+ if (!name || isValidVarName(name)) return name;
249
+ return `_${name}`;
250
+ }
251
+ //#endregion
129
252
  //#region src/components/Operations.tsx
130
253
  function Operations({ name, operations }) {
131
254
  const operationsJSON = operations.reduce((prev, acc) => {
@@ -261,11 +384,11 @@ function buildSchemaNames(node, { params, resolver }) {
261
384
  }
262
385
  responses["default"] = resolver.resolveResponseName(node);
263
386
  return {
264
- request: node.requestBody?.content?.[0]?.schema ? resolver.resolveDataName(node) : void 0,
387
+ request: node.requestBody?.content?.[0]?.schema ? resolver.resolveDataName(node) : null,
265
388
  parameters: {
266
- path: pathParam ? resolver.resolvePathParamsName(node, pathParam) : void 0,
267
- query: queryParam ? resolver.resolveQueryParamsName(node, queryParam) : void 0,
268
- header: headerParam ? resolver.resolveHeaderParamsName(node, headerParam) : void 0
389
+ path: pathParam ? resolver.resolvePathParamsName(node, pathParam) : null,
390
+ query: queryParam ? resolver.resolveQueryParamsName(node, queryParam) : null,
391
+ header: headerParam ? resolver.resolveHeaderParamsName(node, headerParam) : null
269
392
  },
270
393
  responses,
271
394
  errors
@@ -717,6 +840,12 @@ const printerZodMini = ast.definePrinter((options) => {
717
840
  //#region src/generators/zodGenerator.tsx
718
841
  const zodPrinterCache = /* @__PURE__ */ new WeakMap();
719
842
  const zodMiniPrinterCache = /* @__PURE__ */ new WeakMap();
843
+ /**
844
+ * Built-in generator for `@kubb/plugin-zod`. Emits one Zod schema per
845
+ * schema in the spec plus per-operation request/response/parameter schemas.
846
+ * When `mini: true`, schemas use the Zod Mini functional API instead of
847
+ * chainable methods.
848
+ */
720
849
  const zodGenerator = defineGenerator({
721
850
  name: "zod",
722
851
  renderer: jsxRendererSync,
@@ -735,7 +864,7 @@ const zodGenerator = defineGenerator({
735
864
  }, {
736
865
  root,
737
866
  output,
738
- group
867
+ group: group ?? void 0
739
868
  }).path
740
869
  }));
741
870
  const meta = {
@@ -746,10 +875,10 @@ const zodGenerator = defineGenerator({
746
875
  }, {
747
876
  root,
748
877
  output,
749
- group
878
+ group: group ?? void 0
750
879
  })
751
880
  };
752
- const inferTypeName = inferred ? resolver.resolveSchemaTypeName(node.name) : void 0;
881
+ const inferTypeName = inferred ? resolver.resolveSchemaTypeName(node.name) : null;
753
882
  const cyclicSchemas = new Set(ctx.meta.circularNames);
754
883
  const schemaPrinter = mini ? getCachedMiniPrinter() : getCachedStdPrinter();
755
884
  function getCachedStdPrinter() {
@@ -835,12 +964,12 @@ const zodGenerator = defineGenerator({
835
964
  }, {
836
965
  root,
837
966
  output,
838
- group
967
+ group: group ?? void 0
839
968
  }) };
840
969
  const cyclicSchemas = new Set(ctx.meta.circularNames);
841
970
  function renderSchemaEntry({ schema, name, keysToOmit }) {
842
971
  if (!schema) return null;
843
- const inferTypeName = inferred ? resolver.resolveTypeName(name) : void 0;
972
+ const inferTypeName = inferred ? resolver.resolveTypeName(name) : null;
844
973
  const imports = adapter.getImports(schema, (schemaName) => ({
845
974
  name: resolver.resolveSchemaName(schemaName),
846
975
  path: resolver.resolveFile({
@@ -849,7 +978,7 @@ const zodGenerator = defineGenerator({
849
978
  }, {
850
979
  root,
851
980
  output,
852
- group
981
+ group: group ?? void 0
853
982
  }).path
854
983
  }));
855
984
  const cachedStd = zodPrinterCache.get(resolver);
@@ -972,7 +1101,7 @@ const zodGenerator = defineGenerator({
972
1101
  }, {
973
1102
  root,
974
1103
  output,
975
- group
1104
+ group: group ?? void 0
976
1105
  }) };
977
1106
  const transformedOperations = nodes.map((node) => {
978
1107
  return {
@@ -997,7 +1126,7 @@ const zodGenerator = defineGenerator({
997
1126
  }, {
998
1127
  root,
999
1128
  output,
1000
- group
1129
+ group: group ?? void 0
1001
1130
  });
1002
1131
  return names.map((name) => /* @__PURE__ */ jsx(File.Import, {
1003
1132
  name: [name],
@@ -1036,31 +1165,37 @@ const zodGenerator = defineGenerator({
1036
1165
  //#endregion
1037
1166
  //#region src/resolvers/resolverZod.ts
1038
1167
  /**
1039
- * Naming convention resolver for Zod plugin.
1168
+ * Default resolver used by `@kubb/plugin-zod`. Decides the names and file
1169
+ * paths for every generated Zod schema. Schemas use camelCase with a
1170
+ * `Schema` suffix (`listPetsSchema`); their inferred types use PascalCase.
1040
1171
  *
1041
- * Provides default naming helpers using camelCase with a `Schema` suffix for schemas.
1172
+ * @example Resolve schema and type names
1173
+ * ```ts
1174
+ * import { resolverZod } from '@kubb/plugin-zod'
1042
1175
  *
1043
- * @example
1044
- * `resolverZod.default('list pets', 'function') // 'listPetsSchema'`
1176
+ * resolverZod.default('list pets', 'function') // 'listPetsSchema'
1177
+ * resolverZod.resolveSchemaTypeName('pet') // 'PetSchema'
1178
+ * ```
1045
1179
  */
1046
1180
  const resolverZod = defineResolver(() => {
1047
1181
  return {
1048
1182
  name: "default",
1049
1183
  pluginName: "plugin-zod",
1050
1184
  default(name, type) {
1051
- return camelCase(name, {
1185
+ const resolved = camelCase(name, {
1052
1186
  isFile: type === "file",
1053
1187
  suffix: type ? "schema" : void 0
1054
1188
  });
1189
+ return type === "file" ? resolved : ensureValidVarName(resolved);
1055
1190
  },
1056
1191
  resolveSchemaName(name) {
1057
- return camelCase(name, { suffix: "schema" });
1192
+ return ensureValidVarName(camelCase(name, { suffix: "schema" }));
1058
1193
  },
1059
1194
  resolveSchemaTypeName(name) {
1060
- return pascalCase(name, { suffix: "schema" });
1195
+ return ensureValidVarName(pascalCase(name, { suffix: "schema" }));
1061
1196
  },
1062
1197
  resolveTypeName(name) {
1063
- return pascalCase(name);
1198
+ return ensureValidVarName(pascalCase(name));
1064
1199
  },
1065
1200
  resolvePathName(name, type) {
1066
1201
  return this.default(name, type);
@@ -1094,19 +1229,32 @@ const resolverZod = defineResolver(() => {
1094
1229
  //#endregion
1095
1230
  //#region src/plugin.ts
1096
1231
  /**
1097
- * Canonical plugin name for `@kubb/plugin-zod`, used in driver lookups and warnings.
1232
+ * Canonical plugin name for `@kubb/plugin-zod`. Used for driver lookups and
1233
+ * cross-plugin dependency references.
1098
1234
  */
1099
1235
  const pluginZodName = "plugin-zod";
1100
1236
  /**
1101
- * Generates Zod validation schemas from an OpenAPI specification.
1102
- * Walks schemas and operations, delegates to generators, and writes barrel files
1103
- * based on the configured `barrelType`.
1237
+ * Generates Zod v4 schemas from an OpenAPI spec. Use them to validate API
1238
+ * responses at runtime, build form schemas, or feed back into router libraries
1239
+ * that consume Zod (tRPC, Hono, Elysia). Pair with `@kubb/plugin-client` and
1240
+ * set the client's `parser: 'zod'` to validate every response automatically.
1104
1241
  *
1105
- * @example Zod schema generator
1242
+ * @example
1106
1243
  * ```ts
1107
- * import pluginZod from '@kubb/plugin-zod'
1244
+ * import { defineConfig } from 'kubb'
1245
+ * import { pluginTs } from '@kubb/plugin-ts'
1246
+ * import { pluginZod } from '@kubb/plugin-zod'
1247
+ *
1108
1248
  * export default defineConfig({
1109
- * plugins: [pluginZod({ output: { path: 'zod' } })]
1249
+ * input: { path: './petStore.yaml' },
1250
+ * output: { path: './src/gen' },
1251
+ * plugins: [
1252
+ * pluginTs(),
1253
+ * pluginZod({
1254
+ * output: { path: './zod' },
1255
+ * typed: true,
1256
+ * }),
1257
+ * ],
1110
1258
  * })
1111
1259
  * ```
1112
1260
  */
@@ -1121,7 +1269,7 @@ const pluginZod = definePlugin((options) => {
1121
1269
  if (group.type === "path") return `${ctx.group.split("/")[1]}`;
1122
1270
  return `${camelCase(ctx.group)}Controller`;
1123
1271
  }
1124
- } : void 0;
1272
+ } : null;
1125
1273
  return {
1126
1274
  name: pluginZodName,
1127
1275
  options,