Options#
Pass these options to pluginFetch() to control what it generates and where the files go.
| Option | Type | Default | Description |
|---|---|---|---|
output | Output | { path: 'clients', barrel: { type: 'named' } } | Where the generated files are written and exported |
group | Group | — | Split output into per-tag or per-path folders |
baseURL | string | — | Base URL prepended to every request |
validator | false | 'zod' | { request?: 'zod'; response?: 'zod' } | false | Validate request and response bodies with Zod |
comments | 'full' | 'brief' | 'none' | 'full' | How much of each description reaches the JSDoc |
sdk | { mode?: 'tag' | 'flat'; name?: string } | — | Generate a class-based SDK instead of functions |
returnType | 'full' | 'data' | 'full' | Shape of the value a generated call resolves to |
include | Array<Include> | — | Keep only operations that match |
exclude | Array<Exclude> | [] | Skip operations that match |
override | Array<Override> | [] | Apply different options per pattern |
resolver | ResolverPatch<ResolverClient> | — | Customize generated names and file paths |
macros | Array<Macro> | — | Rewrite AST nodes before printing |
output#
Where the plugin writes its generated .ts files and how it exports them.
output.path#
Folder for the plugin's files, resolved against the global output.path on defineConfig and defaulting to 'clients'. To write everything to one file, set output.mode: 'file' and give path a file name with its extension, such as 'clients.ts'.
output.mode#
How the plugin consolidates its code into files, either 'file' or 'directory'.
'file'writes everything into a single file, sooutput.pathmust include the extension (see above).'directory'writes one file per operation underoutput.path.
Leave it unset and Kubb reads output.path: a name with an extension means one file, anything else a directory.
Important
group works with the inferred directory mode, no mode needed. Set mode: 'directory' yourself only to override the inference, such as a directory name that carries a dot (path: 'clients.v2'). An explicit mode: 'file' still forbids group and stops the build with KUBB_INVALID_PLUGIN_OPTIONS, since a single file has nothing to group.
output.barrel#
output.banner#
output.footer#
group#
group.name#
Function (context: { group: string }) => string that turns a group key into a folder name. It defaults to the camelCased tag for a 'tag' group or the first path segment for a 'path' group, and a group.name you pass always wins.
baseURL#
Base URL prepended to every request. When omitted, no host is prepended and each request uses the operation's relative path from the spec. A value containing a ${...} interpolation is emitted as a template literal in the generated client config, so baseURL: '${process.env.API_URL}' reads the environment variable at runtime.
validator#
Runtime validator applied to request and response bodies using schemas from @kubb/plugin-zod, defaulting to false.
falsedoes no validation and returns the response cast to the generated type.'zod'validates the success response body, and the error body when a non-2xx call does not throw.{ request?: 'zod', response?: 'zod' }opts in per direction, validating the request body before the call and the response body after.
Add @kubb/plugin-zod to the plugins list when either direction is 'zod'. With validation on the generated function throws a ParseError when a body fails its schema.
comments#
How much of each OpenAPI description reaches the JSDoc above each generated operation. Defaults to 'full', which emits every description in full, however many paragraphs the spec carries. 'brief' keeps the opening sentence and leaves every other tag such as @summary and the {@link} in place, cutting a description that runs on for 150 characters without a sentence ending at the last word before 120. 'none' emits no JSDoc, leaving the generated-by banner untouched. Descriptions are a third of the output on a large spec, so pick 'brief' or 'none' when file size matters more than editor hovers.
sdk#
Generates a class-based SDK instead of standalone functions, accepting { mode?: 'tag' | 'flat'; name?: string }. Each tag client is an instance class whose constructor takes a client config and builds its own client, so every environment is a separate instance. Leave sdk unset to keep the per-operation functions that the query plugins consume.
mode: 'tag' (the default) emits one class per tag, such as PetClient and StoreClient. Set sdk.name alongside it to also emit a composed root class that instantiates every tag client from one shared config, reached as new PetStore(config).pet.getPetById(...). mode: 'flat' emits a single class named by sdk.name with every operation as a direct method.
Construct a class with a client config, then call a method with the grouped options object ({ path, query, headers, body }). Each call resolves to { status, data, error, contentType, request, response }. Because throwOnError defaults to true, a resolved call means the request succeeded and data is set. Pass throwOnError: false to get the discriminated union instead, keyed on the top-level status:
const { status, data, error } = await pet.getPetById({ path: { petId: 1 }, throwOnError: false })
if (status === 200) {
console.log(data) // data is the success body, error is undefined
} else {
console.error(status, error) // status is the documented error code, error is its parsed body
}
returnType#
Shape of the value a generated call resolves to. 'full' (the default) keeps { status, data, error, contentType, request, response }. 'data' unwraps that down to the bare success body once throwOnError (on by default) rules out the error branch, and falls back to the full result for a call that sets throwOnError: false, since that path still needs error to tell success from failure.
pluginFetch({ returnType: 'data' })
const pet = await getPetById({ path: { petId: 1 } }) // Pet, not { status, data, ... }
This applies to the standalone functions and the class-based SDK. It does not apply to @kubb/plugin-react-query, @kubb/plugin-vue-query, or @kubb/plugin-swr, which call the client directly and expect the full result.
include#
exclude#
override#
resolver#
Changes how the plugin names generated files and symbols by accepting a partial patch. Override only the members you want, and anything you omit keeps resolverClient. See Override a resolver for the this context and how a patch layers over the default.
Tip
Inside a method this is the full resolver, so this.default.name(name) reuses the built-in casing.
type ResolverClientPatch = {
name?(name: string): string
file?: {
baseName?(params: { name: string; extname: string }): string
path?(params: { baseName: string; output: Output }): string
}
className?(name: string): string
groupName?(name: string): string // → 'PetClient'
propertyName?(name: string): string
}