@kubb/plugin-client 5.0.0-beta.15 → 5.0.0-beta.25

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/extension.yaml CHANGED
@@ -2,7 +2,7 @@ $schema: https://kubb.dev/schemas/extension.json
2
2
  kind: plugin
3
3
  id: plugin-client
4
4
  name: Client
5
- description: Generate type-safe HTTP clients (Axios, Fetch) from OpenAPI specifications for making API requests.
5
+ description: Generate type-safe HTTP clients (axios or fetch) from OpenAPI one async function per operation, fully typed end to end.
6
6
  category: client
7
7
  type: official
8
8
  npmPackage: '@kubb/plugin-client'
@@ -35,159 +35,416 @@ icon:
35
35
  intro: |
36
36
  # @kubb/plugin-client
37
37
 
38
- Generate API client code for handling API requests.
38
+ Generate HTTP client functions for every operation in your OpenAPI spec. Each generated function has typed path params, query params, body, and response — call the API like any other typed function.
39
39
 
40
- By default, this plugin uses [Axios](https://axios-http.com/docs/intro), but you can add your own client. See [Use of Fetch](https://kubb.dev/plugins/plugin-client#importpath) for an example.
40
+ Ships with `axios` and `fetch` runtimes out of the box. Bring your own client (auth, retries, custom base URL) by pointing `importPath` at your module.
41
41
  options:
42
42
  - name: output
43
43
  type: Output
44
44
  required: false
45
45
  default: "{ path: 'clients', barrel: { type: 'named' } }"
46
- description: Specify the export location for the files and define the behavior of the output.
46
+ description: Where the generated client files are written and how they are exported.
47
47
  properties:
48
48
  - name: path
49
49
  type: string
50
50
  required: true
51
- description: Output directory or file for the generated code, relative to the global `output.path`.
51
+ description: |
52
+ Folder (or single file) where the plugin writes its generated code. The path is resolved against the global `output.path` set on `defineConfig`.
53
+
54
+ Use a folder to keep each generator's output isolated (`'types'`, `'clients'`, `'hooks'`). Use a single file when you want everything in one place, for example `'api.ts'`.
52
55
  tip: |
53
- if `output.path` is a file, `group` cannot be used.
56
+ When `output.path` points to a single file, the `group` option cannot be used because every operation ends up in the same file.
57
+ examples:
58
+ - name: kubb.config.ts
59
+ files:
60
+ - lang: typescript
61
+ twoslash: false
62
+ code: |
63
+ import { defineConfig } from 'kubb'
64
+ import { pluginTs } from '@kubb/plugin-ts'
65
+
66
+ export default defineConfig({
67
+ input: { path: './petStore.yaml' },
68
+ output: { path: './src/gen' },
69
+ plugins: [
70
+ pluginTs({
71
+ output: { path: './types' },
72
+ }),
73
+ ],
74
+ })
75
+ - name: Resulting tree
76
+ files:
77
+ - lang: text
78
+ twoslash: false
79
+ code: |
80
+ src/
81
+ └── gen/
82
+ └── types/
83
+ ├── Pet.ts
84
+ └── Store.ts
54
85
  default: "'clients'"
55
86
  - name: barrel
56
87
  type: "{ type: 'named' | 'all', nested?: boolean } | false"
57
88
  required: false
58
89
  default: "{ type: 'named' }"
59
- description: 'Configure barrel file export strategy. Use `type` to control named vs. wildcard exports; set `nested: true` to generate hierarchical barrels in subdirectories.'
90
+ description: |
91
+ Controls how the generated `index.ts` (barrel) file re-exports the plugin's output.
92
+
93
+ - `{ type: 'named' }` re-exports each symbol by name. Best for tree-shaking and explicit imports.
94
+ - `{ type: 'all' }` uses `export *`. Smaller barrel file, but exports everything.
95
+ - `{ nested: true }` creates a barrel in every subdirectory, so callers can import from any depth.
96
+ - `false` skips the barrel entirely. The plugin's files are also excluded from the root `index.ts`.
97
+ tip: |
98
+ Pick `'named'` when consumers care about which symbols they import (better tree-shaking, friendlier auto-import). Pick `'all'` when the file count is small and you want a one-line barrel.
60
99
  examples:
61
- - name: all
100
+ - name: "'named' (default)"
62
101
  files:
63
- - lang: typescript
102
+ - name: kubb.config.ts
103
+ lang: typescript
104
+ twoslash: false
64
105
  code: |
65
- export * from './gen/petService.ts'
106
+ import { defineConfig } from 'kubb'
107
+ import { pluginTs } from '@kubb/plugin-ts'
108
+
109
+ export default defineConfig({
110
+ input: { path: './petStore.yaml' },
111
+ output: { path: './src/gen' },
112
+ plugins: [
113
+ pluginTs({
114
+ output: { barrel: { type: 'named' } },
115
+ }),
116
+ ],
117
+ })
118
+ - name: src/gen/types/index.ts
119
+ lang: typescript
66
120
  twoslash: false
67
- - name: named
121
+ code: |
122
+ export { Pet, PetStatus } from './Pet'
123
+ export { Store } from './Store'
124
+ - name: "'all'"
68
125
  files:
69
- - lang: typescript
126
+ - name: kubb.config.ts
127
+ lang: typescript
128
+ twoslash: false
70
129
  code: |
71
- export { PetService } from './gen/petService.ts'
130
+ import { defineConfig } from 'kubb'
131
+ import { pluginTs } from '@kubb/plugin-ts'
132
+
133
+ export default defineConfig({
134
+ input: { path: './petStore.yaml' },
135
+ output: { path: './src/gen' },
136
+ plugins: [
137
+ pluginTs({
138
+ output: { barrel: { type: 'all' } },
139
+ }),
140
+ ],
141
+ })
142
+ - name: src/gen/types/index.ts
143
+ lang: typescript
72
144
  twoslash: false
145
+ code: |
146
+ export * from './Pet'
147
+ export * from './Store'
73
148
  - name: nested
74
149
  files:
75
150
  - name: kubb.config.ts
76
151
  lang: typescript
152
+ twoslash: false
77
153
  code: |
78
- output: {
79
- path: './gen',
80
- barrel: { type: 'named', nested: true },
81
- }
154
+ import { defineConfig } from 'kubb'
155
+ import { pluginTs } from '@kubb/plugin-ts'
156
+
157
+ export default defineConfig({
158
+ input: { path: './petStore.yaml' },
159
+ output: { path: './src/gen' },
160
+ plugins: [
161
+ pluginTs({
162
+ output: { barrel: { type: 'named', nested: true } },
163
+ }),
164
+ ],
165
+ })
166
+ - name: Generated tree
167
+ lang: text
82
168
  twoslash: false
169
+ code: |
170
+ src/gen/types/
171
+ ├── index.ts # re-exports ./petController and ./storeController
172
+ ├── petController/
173
+ │ ├── index.ts # re-exports Pet, Store, ...
174
+ │ └── Pet.ts
175
+ └── storeController/
176
+ ├── index.ts
177
+ └── Store.ts
83
178
  - name: 'false'
84
179
  files:
85
- - lang: typescript
86
- code: ''
180
+ - name: kubb.config.ts
181
+ lang: typescript
182
+ twoslash: false
183
+ code: |
184
+ import { defineConfig } from 'kubb'
185
+ import { pluginTs } from '@kubb/plugin-ts'
186
+
187
+ export default defineConfig({
188
+ input: { path: './petStore.yaml' },
189
+ output: { path: './src/gen' },
190
+ plugins: [
191
+ pluginTs({
192
+ output: { barrel: false },
193
+ }),
194
+ ],
195
+ })
196
+ - name: Result
197
+ lang: text
87
198
  twoslash: false
199
+ code: |
200
+ # No index.ts is generated for this plugin.
201
+ # Its files are also excluded from the root index.ts.
88
202
  - name: banner
89
203
  type: 'string | ((node: RootNode) => string)'
90
204
  required: false
91
- description: Add a banner comment at the top of every generated file. Accepts a static string or a function that receives the `RootNode` and returns a string.
205
+ description: |
206
+ Text prepended to every generated file. Useful for license headers, lint disables, or `@ts-nocheck` directives.
207
+
208
+ Pass a string for a static banner. Pass a function to compute the banner from each file's `RootNode` (the AST root containing path, schema, and operation context).
209
+ examples:
210
+ - name: Static banner
211
+ files:
212
+ - name: kubb.config.ts
213
+ lang: typescript
214
+ twoslash: false
215
+ code: |
216
+ import { defineConfig } from 'kubb'
217
+ import { pluginTs } from '@kubb/plugin-ts'
218
+
219
+ export default defineConfig({
220
+ input: { path: './petStore.yaml' },
221
+ output: { path: './src/gen' },
222
+ plugins: [
223
+ pluginTs({
224
+ output: {
225
+ banner: '/* eslint-disable */\n// @ts-nocheck',
226
+ },
227
+ }),
228
+ ],
229
+ })
230
+ - name: Generated file
231
+ lang: typescript
232
+ twoslash: false
233
+ code: |
234
+ /* eslint-disable */
235
+ // @ts-nocheck
236
+ export type Pet = {
237
+ id: number
238
+ name: string
239
+ }
240
+ - name: Dynamic banner
241
+ files:
242
+ - name: kubb.config.ts
243
+ lang: typescript
244
+ twoslash: false
245
+ code: |
246
+ import { defineConfig } from 'kubb'
247
+ import { pluginTs } from '@kubb/plugin-ts'
248
+
249
+ export default defineConfig({
250
+ input: { path: './petStore.yaml' },
251
+ output: { path: './src/gen' },
252
+ plugins: [
253
+ pluginTs({
254
+ output: {
255
+ banner: (node) => `// Source: ${node.path}\n// Generated at ${new Date().toISOString()}`,
256
+ },
257
+ }),
258
+ ],
259
+ })
92
260
  - name: footer
93
261
  type: 'string | ((node: RootNode) => string)'
94
262
  required: false
95
- description: Add a footer comment at the end of every generated file. Accepts a static string or a function that receives the `RootNode` and returns a string.
263
+ description: |
264
+ Text appended at the end of every generated file. The mirror of `banner` — use it for closing comments, re-enabling lint rules, or marker lines.
265
+
266
+ Pass a string for a static footer, or a function that receives the file's `RootNode` and returns the footer text.
267
+ examples:
268
+ - name: Re-enable lint after a banner disable
269
+ files:
270
+ - name: kubb.config.ts
271
+ lang: typescript
272
+ twoslash: false
273
+ code: |
274
+ import { defineConfig } from 'kubb'
275
+ import { pluginTs } from '@kubb/plugin-ts'
276
+
277
+ export default defineConfig({
278
+ input: { path: './petStore.yaml' },
279
+ output: { path: './src/gen' },
280
+ plugins: [
281
+ pluginTs({
282
+ output: {
283
+ banner: '/* eslint-disable */',
284
+ footer: '/* eslint-enable */',
285
+ },
286
+ }),
287
+ ],
288
+ })
96
289
  - name: override
97
290
  type: boolean
98
291
  required: false
99
292
  default: 'false'
100
- description: Whether Kubb overrides existing external files that can be generated if they already exist.
293
+ description: |
294
+ Allows the plugin to overwrite hand-written files that share a name with a generated file.
295
+
296
+ - `false` (default): Kubb skips a file if it already exists and is not marked as generated. This protects manual edits.
297
+ - `true`: Kubb overwrites any file at the target path, including hand-written ones.
298
+ warning: |
299
+ Enable this only when you are sure the target folder contains nothing you need to keep. Local edits are lost on the next generation.
300
+ examples:
301
+ - name: kubb.config.ts
302
+ files:
303
+ - lang: typescript
304
+ twoslash: false
305
+ code: |
306
+ import { defineConfig } from 'kubb'
307
+ import { pluginTs } from '@kubb/plugin-ts'
308
+
309
+ export default defineConfig({
310
+ input: { path: './petStore.yaml' },
311
+ output: { path: './src/gen' },
312
+ plugins: [
313
+ pluginTs({
314
+ output: { override: true },
315
+ }),
316
+ ],
317
+ })
101
318
  - name: contentType
102
319
  type: "'application/json' | (string & {})"
103
320
  required: false
104
321
  description: |
105
- Define which content type to use.
322
+ Selects which request/response media type the generator reads from the OpenAPI spec.
323
+
324
+ When omitted, Kubb picks the first JSON-compatible media type it finds (`application/json`, `application/vnd.api+json`, anything ending in `+json`). Set this when your spec defines multiple media types for the same operation and you want a non-default one.
325
+ examples:
326
+ - name: JSON API media type
327
+ files:
328
+ - lang: typescript
329
+ twoslash: false
330
+ code: |
331
+ import { defineConfig } from 'kubb'
332
+ import { pluginTs } from '@kubb/plugin-ts'
106
333
 
107
- By default, Kubb uses the first JSON-valid media type.
334
+ export default defineConfig({
335
+ input: { path: './petStore.yaml' },
336
+ output: { path: './src/gen' },
337
+ plugins: [
338
+ pluginTs({
339
+ contentType: 'application/vnd.api+json',
340
+ }),
341
+ ],
342
+ })
108
343
  - name: group
109
344
  type: Group
110
345
  required: false
111
346
  description: |
112
- Grouping combines files in a folder based on a specific `type`.
347
+ Splits generated files into subfolders based on the operation's tag, so each tag in your OpenAPI spec gets its own directory.
348
+
349
+ Without `group`, every file lands in the plugin's `output.path` folder. With `group`, files are bucketed under `{output.path}/{groupName}/`, where `groupName` is derived from the operation's first tag.
350
+ tip: |
351
+ Use `group` to mirror your API's domain structure (pet, store, user) in the generated code. Combine it with `output.barrel: { type: 'named', nested: true }` to get per-tag barrel files.
113
352
  examples:
114
353
  - name: kubb.config.ts
115
354
  files:
116
355
  - lang: typescript
117
- code: |
118
- group: {
119
- type: 'tag',
120
- name({ group }) {
121
- return `${group}Controller`
122
- }
123
- }
124
356
  twoslash: false
357
+ code: |
358
+ import { defineConfig } from 'kubb'
359
+ import { pluginTs } from '@kubb/plugin-ts'
360
+
361
+ export default defineConfig({
362
+ input: { path: './petStore.yaml' },
363
+ output: { path: './src/gen' },
364
+ plugins: [
365
+ pluginTs({
366
+ group: {
367
+ type: 'tag',
368
+ name: ({ group }) => `${group}Controller`,
369
+ },
370
+ }),
371
+ ],
372
+ })
125
373
  body: |
126
374
  With the configuration above, the generator emits:
127
375
 
128
376
  ```text
129
- .
130
- ├── src/
131
- └── petController/
132
- │ ├── addPet.ts
133
- │ │ └── getPet.ts
134
- │ └── storeController/
135
- │ ├── createStore.ts
136
- │ └── getStoreById.ts
137
- ├── petStore.yaml
138
- ├── kubb.config.ts
139
- └── package.json
377
+ src/gen/
378
+ ├── petController/
379
+ ├── AddPet.ts
380
+ └── GetPet.ts
381
+ └── storeController/
382
+ ├── CreateStore.ts
383
+ └── GetStoreById.ts
140
384
  ```
141
385
  properties:
142
386
  - name: type
143
387
  type: "'tag'"
144
388
  required: true
145
- description: Specify the property to group files by. Required when `group` is defined.
389
+ description: |
390
+ Property used to assign each operation to a group. Required whenever `group` is set.
391
+
392
+ Today only `'tag'` is supported: Kubb reads the first tag on the operation (`operation.getTags().at(0)?.name`) and uses it as the group key. Operations without a tag are placed in a default group.
146
393
  note: |
147
- `Required: true*` means this is required only when the `group` option is used. The `group` option itself is optional.
148
- body: |
149
- - `'tag'`: Uses the first tag from `operation.getTags().at(0)?.name`
394
+ `Required: true*` is conditional only required when the parent `group` option is used. `group` itself stays optional.
150
395
  - name: name
151
396
  type: '(context: GroupContext) => string'
152
397
  required: false
153
398
  default: (ctx) => `${ctx.group}Controller`
154
- description: Return the name of a group based on the group name. Used for the file and identifier generation.
399
+ description: Function that builds the folder/identifier name from a group key (the operation's first tag).
155
400
  - name: importPath
156
401
  type: string
157
402
  required: false
158
- description: Path to the client used for API calls. Supports both relative and absolute paths.
403
+ description: |
404
+ Path or module specifier of a custom client module. Generated code imports its HTTP runtime from here instead of `@kubb/plugin-client/clients/{client}`.
405
+
406
+ Use this when you need to inject auth headers, add interceptors, change the base URL at runtime, or wrap a different HTTP library (ky, ofetch, ...). Both relative paths (`./src/client.ts`) and bare specifiers (`@my-org/api-client`) work.
159
407
  details:
160
408
  - title: When to use `importPath`
161
409
  body: |
162
- Use `importPath` when you want to:
410
+ Reach for a custom client when you need to:
163
411
 
164
- - **Customize the HTTP client**: Provide your own client implementation with custom configurations (e.g., baseURL, headers, interceptors)
165
- - **Add authentication**: Include authentication tokens or other security mechanisms in your client
166
- - **Override default behavior**: Replace the default Kubb client with your own implementation
412
+ - Add an auth token to every request.
413
+ - Plug in interceptors, retries, or logging.
414
+ - Configure `baseURL` and headers from environment variables.
415
+ - Wrap a library other than `axios`/`fetch`.
167
416
  - title: Default behavior
168
417
  body: |
169
- When `importPath` is not specified:
418
+ Without `importPath`:
170
419
 
171
- - If `bundle: false` (default): Uses `@kubb/plugin-client/clients/${client}` where client is either `axios` or `fetch`.
172
- - If `bundle: true`: Bundles the client into `.kubb/fetch.ts`.
173
- - title: Import structure
174
- body: 'Generated code imports the client as a default import and the runtime types as named type imports:'
420
+ - `bundle: false` (default) generated code imports from `@kubb/plugin-client/clients/{axios|fetch}`.
421
+ - `bundle: true` Kubb writes `.kubb/fetch.ts` (or `.kubb/axios.ts`) and generated code imports from there.
422
+ - title: Required exports
423
+ body: |
424
+ The module pointed to by `importPath` must satisfy the same shape as the built-in client. At minimum:
425
+
426
+ - A default export of the `client` function.
427
+ - A `RequestConfig` type.
428
+ - A `ResponseErrorConfig` type.
429
+
430
+ When used together with a query plugin (`@kubb/plugin-react-query`, `@kubb/plugin-vue-query`), it must also export a `Client` type alias.
431
+ - title: How generated files import it
432
+ body: |
433
+ Generated code imports the client as a default import and the runtime types as named type imports:
175
434
  codeBlock:
176
435
  lang: typescript
177
- code: |-
178
- /**
179
- * Generated by Kubb (https://kubb.dev/).
180
- * Do not edit manually.
181
- */
436
+ code: |
182
437
  import client from '${client.importPath}'
183
438
  import type { RequestConfig, ResponseErrorConfig } from '${client.importPath}'
184
- // ... rest of generated file
439
+ // ... rest of the generated file
185
440
  important: |
186
- When using `importPath` with query plugins such as `@kubb/plugin-react-query` or `@kubb/plugin-vue-query`, the generated hooks also import a `Client` type alongside `RequestConfig` and `ResponseErrorConfig` from the custom module. Your custom client module **must** export all three typesif any is missing, TypeScript will report an unresolvable import error.
441
+ When used with query plugins (`@kubb/plugin-react-query`, `@kubb/plugin-vue-query`), generated hooks also import a `Client` type alias. Your module **must** export `Client`, `RequestConfig`, and `ResponseErrorConfig` — TypeScript will fail the import otherwise.
187
442
  codeBlock:
188
443
  lang: typescript
189
- title: client.ts
444
+ title: src/client.ts
190
445
  code: |
446
+ import axios from 'axios'
447
+
191
448
  export type RequestConfig<TData = unknown> = {
192
449
  url?: string
193
450
  method: 'GET' | 'PUT' | 'PATCH' | 'POST' | 'DELETE'
@@ -206,77 +463,109 @@ options:
206
463
 
207
464
  export type ResponseErrorConfig<TError = unknown> = TError
208
465
 
209
- // The Client type alias is required when using query plugins
466
+ // Required when used with @kubb/plugin-react-query or @kubb/plugin-vue-query
210
467
  export type Client = <TData, _TError = unknown, TVariables = unknown>(
211
- config: RequestConfig<TVariables>
468
+ config: RequestConfig<TVariables>,
212
469
  ) => Promise<ResponseConfig<TData>>
213
470
 
214
- export const client: Client = async (config) => { /* ... */ }
471
+ const client: Client = async (config) => {
472
+ const response = await axios.request<TData>({
473
+ ...config,
474
+ headers: {
475
+ Authorization: `Bearer ${process.env.API_TOKEN}`,
476
+ ...config.headers,
477
+ },
478
+ })
479
+
480
+ return response
481
+ }
482
+
215
483
  export default client
216
484
  examples:
217
- - name: kubb.config.ts
485
+ - name: Wire up a custom client
218
486
  files:
219
- - lang: typescript
487
+ - name: kubb.config.ts
488
+ lang: typescript
489
+ twoslash: false
220
490
  code: |
221
491
  import { defineConfig } from 'kubb'
222
492
  import { pluginClient } from '@kubb/plugin-client'
223
493
 
224
494
  export default defineConfig({
225
- // ...
495
+ input: { path: './petStore.yaml' },
496
+ output: { path: './src/gen' },
226
497
  plugins: [
227
498
  pluginClient({
228
- importPath: './src/client.ts', // Path to your custom client
499
+ importPath: './src/client.ts',
229
500
  }),
230
501
  ],
231
502
  })
232
- twoslash: false
233
503
  tip: |
234
- Learn more about defining a custom client [here](https://kubb.dev/plugins/plugin-client#importpath).
504
+ See the [custom client guide](https://kubb.dev/plugins/plugin-client#importpath) for a worked example.
235
505
  - name: operations
236
506
  type: boolean
237
507
  required: false
238
508
  default: 'false'
239
- description: Create an `operations.ts` file with all operations grouped by methods.
509
+ description: |
510
+ Emits an `operations.ts` file that re-exports every generated function grouped by HTTP method. Useful for building meta-tooling (route registries, API explorers) on top of the generated code.
240
511
  - name: dataReturnType
241
512
  type: "'data' | 'full'"
242
513
  required: false
243
514
  default: "'data'"
244
515
  description: |
245
- Return type used when calling the client.
516
+ Shape of the value returned from each generated client function.
246
517
 
247
- - `'data'` returns `ResponseConfig['data']`.
248
- - `'full'` returns the full `ResponseConfig`.
518
+ - `'data'` returns only the response body (`response.data`). Concise and matches what most apps need.
519
+ - `'full'` returns the full response config — body, status code, headers, and the original request. Use this when callers need to inspect headers or status.
249
520
  examples:
250
- - name: data
521
+ - name: "'data' (default)"
251
522
  files:
252
- - lang: typescript
523
+ - name: getPetById.ts
524
+ lang: typescript
525
+ twoslash: false
253
526
  code: |
254
527
  export async function getPetById<TData>(
255
528
  petId: GetPetByIdPathParams,
256
529
  ): Promise<ResponseConfig<TData>['data']> {
257
- ...
530
+ // ...
258
531
  }
532
+ - name: usage.ts
533
+ lang: typescript
259
534
  twoslash: false
260
- - name: full
535
+ code: |
536
+ const pet = await getPetById(1)
537
+ // ^? Pet
538
+ - name: "'full'"
261
539
  files:
262
- - lang: typescript
540
+ - name: getPetById.ts
541
+ lang: typescript
542
+ twoslash: false
263
543
  code: |
264
544
  export async function getPetById<TData>(
265
545
  petId: GetPetByIdPathParams,
266
546
  ): Promise<ResponseConfig<TData>> {
267
- ...
547
+ // ...
268
548
  }
549
+ - name: usage.ts
550
+ lang: typescript
269
551
  twoslash: false
552
+ code: |
553
+ const response = await getPetById(1)
554
+ // ^? ResponseConfig<Pet>
555
+ console.log(response.status, response.headers)
556
+ const pet = response.data
270
557
  - name: urlType
271
558
  type: "'export' | false"
272
559
  required: false
273
560
  default: 'false'
274
- description: Export URLs that are used by every operation.
275
- body: |
276
- - `'export'` will make them part of your barrel file.
277
- - `false` will not make them exportable.
561
+ description: |
562
+ Controls whether the URL builder helpers (`get<Operation>Url`) are exported alongside each client function.
563
+
564
+ - `'export'` expose them via the barrel. Useful when you call the API through a different transport (`navigator.sendBeacon`, server actions, etc.).
565
+ - `false` (default) — keep them private to the generated module.
278
566
  codeBlock:
279
567
  lang: typescript
568
+ title: Generated URL helper
280
569
  code: |
281
570
  export function getGetPetByIdUrl(petId: GetPetByIdPathParams['petId']) {
282
571
  return `/pet/${petId}` as const
@@ -285,16 +574,37 @@ options:
285
574
  type: "'object' | 'inline'"
286
575
  required: false
287
576
  default: "'inline'"
288
- description: Defines how parameters are passed to generated functions. Switch between object-style parameters and inline parameters.
577
+ description: |
578
+ How operation parameters (path, query, headers) are exposed in the generated function signature.
579
+
580
+ - `'inline'` (default) — each parameter is a separate positional argument. Compact for operations with one or two params.
581
+ - `'object'` — every parameter is wrapped in a single object argument. Easier to read for operations with many params and named at the call site.
289
582
  tip: |
290
- When `paramsType` is set to `'object'`, `pathParams` will also be set to `'object'`.
291
- body: |
292
- - `'object'` returns params and pathParams as an object.
293
- - `'inline'` returns params as comma-separated params.
583
+ Setting `paramsType: 'object'` implicitly sets `pathParamsType: 'object'` as well, so call sites are consistent.
294
584
  examples:
295
- - name: object
585
+ - name: "'inline' (default)"
296
586
  files:
297
- - lang: typescript
587
+ - name: Generated client
588
+ lang: typescript
589
+ twoslash: false
590
+ code: |
591
+ export async function deletePet(
592
+ petId: DeletePetPathParams['petId'],
593
+ headers?: DeletePetHeaderParams,
594
+ config: Partial<RequestConfig> = {},
595
+ ) {
596
+ // ...
597
+ }
598
+ - name: Caller
599
+ lang: typescript
600
+ twoslash: false
601
+ code: |
602
+ await deletePet(42)
603
+ - name: "'object'"
604
+ files:
605
+ - name: Generated client
606
+ lang: typescript
607
+ twoslash: false
298
608
  code: |
299
609
  export async function deletePet(
300
610
  {
@@ -306,131 +616,179 @@ options:
306
616
  },
307
617
  config: Partial<RequestConfig> = {},
308
618
  ) {
309
- ...
619
+ // ...
310
620
  }
621
+ - name: Caller
622
+ lang: typescript
311
623
  twoslash: false
312
- - name: inline
313
- files:
314
- - lang: typescript
315
624
  code: |
316
- export async function deletePet(
317
- petId: DeletePetPathParams['petId'],
318
- headers?: DeletePetHeaderParams,
319
- config: Partial<RequestConfig> = {}
320
- ){
321
- ...
322
- }
323
- twoslash: false
625
+ await deletePet({ petId: 42, headers: { 'X-Api-Key': 'secret' } })
324
626
  - name: paramsCasing
325
627
  type: "'camelcase'"
326
628
  required: false
327
- description: Transform parameter names to a specific casing format for path, query, and header parameters in generated client code.
629
+ description: |
630
+ Renames path, query, and header parameters in the generated client to the chosen casing. The HTTP request still uses the original names from the OpenAPI spec — Kubb writes the mapping for you.
631
+
632
+ - `'camelcase'` — turn `pet_id` and `X-Api-Key` into `petId` and `xApiKey` in your TypeScript code. The runtime URL still uses `/pet/{pet_id}` and the header is still sent as `X-Api-Key`.
328
633
  important: |
329
- When using `paramsCasing`, ensure that `@kubb/plugin-ts` also has the same `paramsCasing` setting. This option automatically maps transformed parameter names back to their original API names in HTTP requests.
330
- body: |
331
- - `'camelcase'` transforms parameter names to camelCase.
634
+ Set the same `paramsCasing` on every plugin that touches operation parameters (`@kubb/plugin-ts`, `@kubb/plugin-client`, `@kubb/plugin-react-query`, `@kubb/plugin-faker`, `@kubb/plugin-mcp`). Mismatched casing causes type errors between generated layers.
332
635
  examples:
333
- - name: With paramsCasing camelcase
636
+ - name: "With paramsCasing: 'camelcase'"
334
637
  files:
335
- - lang: typescript
638
+ - name: Generated client
639
+ lang: typescript
640
+ twoslash: false
336
641
  code: |
337
- // Function parameters use camelCase
642
+ // Function takes camelCase parameters
338
643
  export async function deletePet(
339
- petId: DeletePetPathParams['petId'], // ✓ camelCase
644
+ petId: DeletePetPathParams['petId'],
340
645
  headers?: DeletePetHeaderParams,
341
- config: Partial<RequestConfig> = {}
646
+ config: Partial<RequestConfig> = {},
342
647
  ) {
343
- // Automatically maps back to original name for the API
648
+ // ...mapped back to the original API name internally
344
649
  const pet_id = petId
345
650
 
346
651
  return fetch({
347
652
  method: 'DELETE',
348
- url: `/pet/${pet_id}`, // Uses original API parameter name
349
- ...
653
+ url: `/pet/${pet_id}`,
654
+ ...config,
350
655
  })
351
656
  }
657
+ - name: Caller
658
+ lang: typescript
352
659
  twoslash: false
660
+ code: |
661
+ await deletePet(42)
353
662
  - name: Without paramsCasing
354
663
  files:
355
- - lang: typescript
664
+ - name: Generated client
665
+ lang: typescript
666
+ twoslash: false
356
667
  code: |
357
- // Parameters use original API naming
668
+ // Function parameters mirror the OpenAPI spec
358
669
  export async function deletePet(
359
- pet_id: DeletePetPathParams['pet_id'], // Original naming
670
+ pet_id: DeletePetPathParams['pet_id'],
360
671
  headers?: DeletePetHeaderParams,
361
- config: Partial<RequestConfig> = {}
672
+ config: Partial<RequestConfig> = {},
362
673
  ) {
363
674
  return fetch({
364
675
  method: 'DELETE',
365
676
  url: `/pet/${pet_id}`,
366
- ...
677
+ ...config,
367
678
  })
368
679
  }
369
- twoslash: false
370
680
  tip: |
371
- The client automatically generates mapping code to convert camelCase parameter names back to the original API format. You write code with developer-friendly camelCase names, but HTTP requests use the exact parameter names from your OpenAPI specification.
681
+ Callers write friendly camelCase names. The generated client maps them back to whatever the API expects (snake_case path params, kebab-case headers, ...).
372
682
  - name: pathParamsType
373
683
  type: "'object' | 'inline'"
374
684
  required: false
375
685
  default: "'inline'"
376
- description: Defines how pathParams are passed to generated functions.
377
- body: |
378
- - `'object'` returns pathParams as an object.
379
- - `'inline'` returns pathParams as comma-separated params.
686
+ description: |
687
+ How URL path parameters appear in the generated function signature. Affects only path params; query/header params follow `paramsType`.
688
+
689
+ - `'inline'` (default) each path param is a positional argument: `getPetById(petId)`.
690
+ - `'object'` — path params are wrapped in a single object: `getPetById({ petId })`.
380
691
  examples:
381
- - name: object
692
+ - name: "'inline' (default)"
382
693
  files:
383
694
  - lang: typescript
695
+ twoslash: false
384
696
  code: |
385
697
  export async function getPetById(
386
- { petId }: GetPetByIdPathParams,
698
+ petId: GetPetByIdPathParams,
387
699
  ) {
388
- ...
700
+ // ...
389
701
  }
390
- twoslash: false
391
- - name: inline
702
+ - name: "'object'"
392
703
  files:
393
704
  - lang: typescript
705
+ twoslash: false
394
706
  code: |
395
707
  export async function getPetById(
396
- petId: GetPetByIdPathParams,
708
+ { petId }: GetPetByIdPathParams,
397
709
  ) {
398
- ...
710
+ // ...
399
711
  }
400
- twoslash: false
401
712
  - name: parser
402
713
  type: "'client' | 'zod'"
403
714
  required: false
404
715
  default: "'client'"
405
- description: Parser used before returning data.
406
- body: |
407
- - `'zod'` uses `@kubb/plugin-zod` to parse data.
408
- - `'client'` returns data without parsing.
716
+ description: |
717
+ Runtime validator applied to the response body before it is returned to the caller.
718
+
719
+ - `'client'` (default) no validation. The response is cast to the generated TypeScript type and returned as-is. Fastest path, trusts the API.
720
+ - `'zod'` — pipes the response through the Zod schema produced by `@kubb/plugin-zod`. Catches mismatches between spec and API at runtime, at the cost of a parse on every call.
721
+
722
+ Use `'zod'` when you want a defensive boundary against drift between your OpenAPI spec and the live API. Requires `@kubb/plugin-zod` in the plugins list.
723
+ examples:
724
+ - name: Validate responses with Zod
725
+ files:
726
+ - lang: typescript
727
+ twoslash: false
728
+ code: |
729
+ import { defineConfig } from 'kubb'
730
+ import { pluginClient } from '@kubb/plugin-client'
731
+ import { pluginTs } from '@kubb/plugin-ts'
732
+ import { pluginZod } from '@kubb/plugin-zod'
733
+
734
+ export default defineConfig({
735
+ input: { path: './petStore.yaml' },
736
+ output: { path: './src/gen' },
737
+ plugins: [
738
+ pluginTs(),
739
+ pluginZod(),
740
+ pluginClient({
741
+ parser: 'zod',
742
+ }),
743
+ ],
744
+ })
409
745
  - name: client
410
746
  type: "'axios' | 'fetch'"
411
747
  required: false
412
748
  default: "'axios'"
413
- description: Client used for HTTP calls.
414
- body: |
415
- - `'axios'` uses `@kubb/plugin-client/templates/axios` to fetch data.
416
- - `'fetch'` uses `@kubb/plugin-client/templates/fetch` to fetch data.
749
+ description: |
750
+ HTTP client used by the generated code.
751
+
752
+ - `'axios'` generated functions call into `@kubb/plugin-client/clients/axios`. Requires `axios` as a runtime dependency.
753
+ - `'fetch'` — generated functions call into `@kubb/plugin-client/clients/fetch`. Uses the global `fetch`, no extra runtime dependency.
754
+
755
+ To plug in your own client, use [`importPath`](#importpath) instead.
756
+ examples:
757
+ - name: Use fetch
758
+ files:
759
+ - lang: typescript
760
+ twoslash: false
761
+ code: |
762
+ import { defineConfig } from 'kubb'
763
+ import { pluginClient } from '@kubb/plugin-client'
764
+
765
+ export default defineConfig({
766
+ input: { path: './petStore.yaml' },
767
+ output: { path: './src/gen' },
768
+ plugins: [
769
+ pluginClient({
770
+ client: 'fetch',
771
+ }),
772
+ ],
773
+ })
417
774
  - name: clientType
418
775
  type: "'function' | 'class' | 'staticClass'"
419
776
  required: false
420
777
  default: "'function'"
421
778
  description: |
422
- Defines the client code generation style.
779
+ Shape of the generated client code.
423
780
 
424
- - `'function'` generates standalone functions for each operation.
425
- - `'class'` generates a class with instance methods for each operation.
426
- - `'staticClass'` generates a class with static methods for each operation. Use this style to call methods like `Pet.getPetById(...)` without instantiating the class.
781
+ - `'function'` (default) — one standalone async function per operation. Tree-shakes cleanly and works with every query plugin.
782
+ - `'class'` one class per group/tag with an instance method per operation. Use this to share configuration (auth, headers) through the constructor.
783
+ - `'staticClass'` one class per group/tag with static methods. Call as `Pet.getPetById(...)` without instantiating. Good for app-wide singleton clients.
427
784
  warning: |
428
- When using `clientType: 'class'` or `clientType: 'staticClass'`, these are not compatible with query plugins like `@kubb/plugin-react-query` or `@kubb/plugin-vue-query`. These plugins are designed to work with function-based clients. If you need to use both class-based or static-class clients and query hooks, configure separate `pluginClient` instances: one with `clientType: 'class'` or `clientType: 'staticClass'` for your needs, and another with `clientType: 'function'` (or omit it for the default) that the query plugins will reference.
785
+ Only `'function'` is compatible with query plugins (`@kubb/plugin-react-query`, `@kubb/plugin-vue-query`). To use both classes and query hooks, register two `pluginClient` instances one with `clientType: 'function'` for the query plugins to consume, and a second with `clientType: 'class'` or `'staticClass'` for your direct usage.
429
786
  examples:
430
- - name: staticClass
787
+ - name: "'staticClass'"
431
788
  files:
432
789
  - name: kubb.config.ts
433
790
  lang: typescript
791
+ twoslash: false
434
792
  code: |
435
793
  import { defineConfig } from 'kubb'
436
794
  import { pluginClient } from '@kubb/plugin-client'
@@ -448,30 +806,23 @@ options:
448
806
  }),
449
807
  ],
450
808
  })
451
- twoslash: false
452
- - name: Pet.ts
809
+ - name: Generated Pet.ts (excerpt)
453
810
  lang: typescript
811
+ twoslash: false
454
812
  code: |
455
813
  import fetch from '@kubb/plugin-client/clients/fetch'
456
- import type { GetPetByIdQueryResponse, GetPetByIdPathParams, GetPetById400, GetPetById404 } from '../../../models/ts/petController/GetPetById.js'
457
- import type { AddPetMutationRequest, AddPetMutationResponse, AddPet405 } from '../../../models/ts/petController/AddPet.js'
458
- import type { RequestConfig, ResponseErrorConfig } from '@kubb/plugin-client/clients/fetch'
814
+ import type { GetPetByIdPathParams, GetPetByIdQueryResponse } from '../../models/ts/petController/GetPetById'
815
+ import type { RequestConfig } from '@kubb/plugin-client/clients/fetch'
459
816
 
460
817
  export class Pet {
461
818
  static #client: typeof fetch = fetch
462
819
 
463
- /**
464
- * @description Returns a single pet
465
- * @summary Find pet by ID
466
- * {@link /pet/:petId}
467
- */
468
820
  static async getPetById(
469
821
  { petId }: { petId: GetPetByIdPathParams['petId'] },
470
- config: Partial<RequestConfig> & { client?: typeof fetch } = {}
822
+ config: Partial<RequestConfig> & { client?: typeof fetch } = {},
471
823
  ) {
472
- const request = this.#client || fetch
473
- const { client: _request = this.#client, ...requestConfig } = config
474
- const res = await request<GetPetByIdQueryResponse, ResponseErrorConfig<GetPetById400 | GetPetById404>, unknown>({
824
+ const { client: request = this.#client, ...requestConfig } = config
825
+ const res = await request<GetPetByIdQueryResponse>({
475
826
  method: 'GET',
476
827
  url: `/pet/${petId}`,
477
828
  ...requestConfig,
@@ -479,18 +830,18 @@ options:
479
830
  return res.data
480
831
  }
481
832
  }
482
- twoslash: false
483
833
  - name: usage.ts
484
834
  lang: typescript
835
+ twoslash: false
485
836
  code: |
486
837
  import { Pet } from './gen/clients/Pet'
487
838
 
488
839
  const pet = await Pet.getPetById({ petId: 1 })
489
- twoslash: false
490
- - name: class
840
+ - name: "'class'"
491
841
  files:
492
842
  - name: kubb.config.ts
493
843
  lang: typescript
844
+ twoslash: false
494
845
  code: |
495
846
  import { defineConfig } from 'kubb'
496
847
  import { pluginClient } from '@kubb/plugin-client'
@@ -508,13 +859,13 @@ options:
508
859
  }),
509
860
  ],
510
861
  })
511
- twoslash: false
512
- - name: Pet.ts
862
+ - name: Generated Pet.ts (excerpt)
513
863
  lang: typescript
864
+ twoslash: false
514
865
  code: |
515
866
  import fetch from '@kubb/plugin-client/clients/fetch'
516
- import type { GetPetByIdQueryResponse, GetPetByIdPathParams, GetPetById400, GetPetById404 } from '../../../models/ts/petController/GetPetById.js'
517
- import type { RequestConfig, ResponseErrorConfig } from '@kubb/plugin-client/clients/fetch'
867
+ import type { GetPetByIdPathParams, GetPetByIdQueryResponse } from '../../models/ts/petController/GetPetById'
868
+ import type { RequestConfig } from '@kubb/plugin-client/clients/fetch'
518
869
 
519
870
  export class Pet {
520
871
  #client: typeof fetch
@@ -525,10 +876,10 @@ options:
525
876
 
526
877
  async getPetById(
527
878
  { petId }: { petId: GetPetByIdPathParams['petId'] },
528
- config: Partial<RequestConfig> & { client?: typeof fetch } = {}
879
+ config: Partial<RequestConfig> & { client?: typeof fetch } = {},
529
880
  ) {
530
881
  const { client: request = this.#client, ...requestConfig } = config
531
- const res = await request<GetPetByIdQueryResponse, ResponseErrorConfig<GetPetById400 | GetPetById404>, unknown>({
882
+ const res = await request<GetPetByIdQueryResponse>({
532
883
  method: 'GET',
533
884
  url: `/pet/${petId}`,
534
885
  ...requestConfig,
@@ -536,29 +887,32 @@ options:
536
887
  return res.data
537
888
  }
538
889
  }
539
- twoslash: false
540
890
  - name: usage.ts
541
891
  lang: typescript
892
+ twoslash: false
542
893
  code: |
543
894
  import { Pet } from './gen/clients/Pet'
544
895
 
545
896
  const petClient = new Pet()
546
897
  const pet = await petClient.getPetById({ petId: 1 })
547
- twoslash: false
548
898
  - name: wrapper
549
899
  type: '{ className: string }'
550
900
  required: false
551
- description: Generate a wrapper class that composes all tag-based client classes into a single entry point.
901
+ description: |
902
+ Generates a single top-level class that composes the per-tag client classes into one entry point. Only meaningful when `clientType: 'class'` (or `'staticClass'`) and `group: { type: 'tag' }` are also set.
903
+
904
+ Use this when you want a single object to hand around your app (`api.pet.findById`, `api.user.login`) instead of importing each tag client separately.
552
905
  properties:
553
906
  - name: className
554
907
  type: string
555
908
  required: true
556
- description: Name of the generated wrapper class.
909
+ description: Name of the generated wrapper class — used as the export name and file name.
557
910
  examples:
558
- - name: wrapper.className
911
+ - name: A composed PetStoreClient
559
912
  files:
560
913
  - name: kubb.config.ts
561
914
  lang: typescript
915
+ twoslash: false
562
916
  code: |
563
917
  import { defineConfig } from 'kubb'
564
918
  import { pluginClient } from '@kubb/plugin-client'
@@ -577,14 +931,14 @@ options:
577
931
  }),
578
932
  ],
579
933
  })
580
- twoslash: false
581
- - name: PetStoreClient.ts
934
+ - name: Generated PetStoreClient.ts
582
935
  lang: typescript
936
+ twoslash: false
583
937
  code: |
584
- import type { Client, RequestConfig } from './.kubb/fetch.js'
585
- import { Pet } from './petController/Pet.js'
586
- import { Store } from './storeController/Store.js'
587
- import { User } from './userController/User.js'
938
+ import type { Client, RequestConfig } from './.kubb/fetch'
939
+ import { Pet } from './petController/Pet'
940
+ import { Store } from './storeController/Store'
941
+ import { User } from './userController/User'
588
942
 
589
943
  export class PetStoreClient {
590
944
  readonly pet: Pet
@@ -597,150 +951,312 @@ options:
597
951
  this.user = new User(config)
598
952
  }
599
953
  }
600
- twoslash: false
601
954
  - name: usage.ts
602
955
  lang: typescript
956
+ twoslash: false
603
957
  code: |
604
958
  import { PetStoreClient } from './gen/clients/PetStoreClient'
605
959
 
606
- const client = new PetStoreClient({ baseURL: 'https://petstore.swagger.io/v2' })
960
+ const api = new PetStoreClient({ baseURL: 'https://petstore.swagger.io/v2' })
607
961
 
608
- const pets = await client.pet.findPetsByTags({ tags: ['available'] })
609
- const user = await client.user.getUserByName({ username: 'john' })
610
- twoslash: false
962
+ const pets = await api.pet.findPetsByTags({ tags: ['available'] })
963
+ const user = await api.user.getUserByName({ username: 'john' })
611
964
  - name: bundle
612
965
  type: boolean
613
966
  required: false
614
967
  default: 'false'
615
- description: Controls whether the HTTP client runtime is copied into the generated `.kubb` directory.
616
- body: |
617
- - `true` adds a `.kubb/fetch.ts` file containing the selected client template (fetch or axios). Generated clients remain self-contained.
618
- - `false` keeps generated clients slim by importing the shared runtime from `@kubb/plugin-client/clients/{client}`.
619
- - Override this behavior by providing a custom `client.importPath`.
968
+ description: |
969
+ Copies the HTTP client runtime into the generated output, so the consuming app does not need `@kubb/plugin-client` installed at runtime.
970
+
971
+ - `false` (default) generated files import from `@kubb/plugin-client/clients/{client}`. Smaller diff, but the package must be a runtime dependency.
972
+ - `true` Kubb writes a `.kubb/fetch.ts` (or `.kubb/axios.ts`) file with the client implementation. Generated code imports from that local file and the project no longer pulls `@kubb/plugin-client` at runtime.
973
+ - Setting `client.importPath` overrides both behaviors and uses your custom client instead.
974
+ examples:
975
+ - name: Bundle the runtime
976
+ files:
977
+ - lang: typescript
978
+ twoslash: false
979
+ code: |
980
+ import { defineConfig } from 'kubb'
981
+ import { pluginClient } from '@kubb/plugin-client'
982
+
983
+ export default defineConfig({
984
+ input: { path: './petStore.yaml' },
985
+ output: { path: './src/gen' },
986
+ plugins: [
987
+ pluginClient({
988
+ client: 'fetch',
989
+ bundle: true,
990
+ }),
991
+ ],
992
+ })
620
993
  - name: baseURL
621
994
  type: string
622
995
  required: false
623
- description: Sets a custom base URL for all generated calls. When not set, the base URL is automatically taken from the OAS spec via the adapter (e.g. the `servers[0].url` field).
996
+ description: |
997
+ Base URL prepended to every request URL in the generated client. When omitted, the URL comes from the OpenAPI spec's `servers[0].url` (or whichever index the adapter is configured to read).
998
+
999
+ Set this when the generated client should point at a different environment (staging, production) than the one written in the spec.
1000
+ examples:
1001
+ - name: Override the spec's server URL
1002
+ files:
1003
+ - lang: typescript
1004
+ twoslash: false
1005
+ code: |
1006
+ import { defineConfig } from 'kubb'
1007
+ import { pluginClient } from '@kubb/plugin-client'
1008
+
1009
+ export default defineConfig({
1010
+ input: { path: './petStore.yaml' },
1011
+ output: { path: './src/gen' },
1012
+ plugins: [
1013
+ pluginClient({
1014
+ baseURL: 'https://petstore.swagger.io/v2',
1015
+ }),
1016
+ ],
1017
+ })
624
1018
  - name: include
625
1019
  type: Array<Include>
626
1020
  required: false
627
- description: Array containing include parameters to include tags, operations, methods, paths, or content types.
1021
+ description: |
1022
+ Restricts generation to operations that match at least one entry in the list. Anything not matched is skipped.
1023
+
1024
+ Each entry filters by one of:
1025
+
1026
+ - `tag` — the operation's first tag in the OpenAPI spec.
1027
+ - `operationId` — the operation's `operationId`.
1028
+ - `path` — the URL pattern (`'/pet/{petId}'`).
1029
+ - `method` — HTTP method (`'get'`, `'post'`, ...).
1030
+ - `contentType` — the media type of the request body.
1031
+
1032
+ `pattern` accepts either a string (exact match) or a `RegExp` for fuzzy matches.
628
1033
  codeBlock:
629
1034
  lang: typescript
630
- title: Include
1035
+ title: Type definition
631
1036
  code: |
632
1037
  export type Include = {
633
1038
  type: 'tag' | 'operationId' | 'path' | 'method' | 'contentType'
634
1039
  pattern: string | RegExp
635
1040
  }
1041
+ examples:
1042
+ - name: Only the pet tag
1043
+ files:
1044
+ - name: kubb.config.ts
1045
+ lang: typescript
1046
+ twoslash: false
1047
+ code: |
1048
+ import { defineConfig } from 'kubb'
1049
+ import { pluginTs } from '@kubb/plugin-ts'
1050
+
1051
+ export default defineConfig({
1052
+ input: { path: './petStore.yaml' },
1053
+ output: { path: './src/gen' },
1054
+ plugins: [
1055
+ pluginTs({
1056
+ include: [
1057
+ { type: 'tag', pattern: 'pet' },
1058
+ ],
1059
+ }),
1060
+ ],
1061
+ })
1062
+ - name: Only GET operations under /pet
1063
+ files:
1064
+ - name: kubb.config.ts
1065
+ lang: typescript
1066
+ twoslash: false
1067
+ code: |
1068
+ import { defineConfig } from 'kubb'
1069
+ import { pluginTs } from '@kubb/plugin-ts'
1070
+
1071
+ export default defineConfig({
1072
+ input: { path: './petStore.yaml' },
1073
+ output: { path: './src/gen' },
1074
+ plugins: [
1075
+ pluginTs({
1076
+ include: [
1077
+ { type: 'method', pattern: 'get' },
1078
+ { type: 'path', pattern: /^\/pet/ },
1079
+ ],
1080
+ }),
1081
+ ],
1082
+ })
636
1083
  - name: exclude
637
1084
  type: Array<Exclude>
638
1085
  required: false
639
- description: Array containing exclude parameters to exclude or skip tags, operations, methods, paths, or content types.
1086
+ description: |
1087
+ Skips any operation that matches at least one entry in the list. The opposite of `include`.
1088
+
1089
+ Each entry filters by one of:
1090
+
1091
+ - `tag` — the operation's first tag.
1092
+ - `operationId` — the operation's `operationId`.
1093
+ - `path` — the URL pattern (`'/pet/{petId}'`).
1094
+ - `method` — HTTP method (`'get'`, `'post'`, ...).
1095
+ - `contentType` — the media type of the request body.
1096
+
1097
+ `pattern` accepts a plain string or a `RegExp`. When both `include` and `exclude` are set, `exclude` wins.
640
1098
  codeBlock:
641
1099
  lang: typescript
642
- title: Exclude
1100
+ title: Type definition
643
1101
  code: |
644
1102
  export type Exclude = {
645
1103
  type: 'tag' | 'operationId' | 'path' | 'method' | 'contentType'
646
1104
  pattern: string | RegExp
647
1105
  }
1106
+ examples:
1107
+ - name: Skip everything under the store tag
1108
+ files:
1109
+ - name: kubb.config.ts
1110
+ lang: typescript
1111
+ twoslash: false
1112
+ code: |
1113
+ import { defineConfig } from 'kubb'
1114
+ import { pluginTs } from '@kubb/plugin-ts'
1115
+
1116
+ export default defineConfig({
1117
+ input: { path: './petStore.yaml' },
1118
+ output: { path: './src/gen' },
1119
+ plugins: [
1120
+ pluginTs({
1121
+ exclude: [
1122
+ { type: 'tag', pattern: 'store' },
1123
+ ],
1124
+ }),
1125
+ ],
1126
+ })
1127
+ - name: Skip a specific operation and all delete methods
1128
+ files:
1129
+ - name: kubb.config.ts
1130
+ lang: typescript
1131
+ twoslash: false
1132
+ code: |
1133
+ import { defineConfig } from 'kubb'
1134
+ import { pluginTs } from '@kubb/plugin-ts'
1135
+
1136
+ export default defineConfig({
1137
+ input: { path: './petStore.yaml' },
1138
+ output: { path: './src/gen' },
1139
+ plugins: [
1140
+ pluginTs({
1141
+ exclude: [
1142
+ { type: 'operationId', pattern: 'deletePet' },
1143
+ { type: 'method', pattern: 'delete' },
1144
+ ],
1145
+ }),
1146
+ ],
1147
+ })
648
1148
  - name: override
649
1149
  type: Array<Override>
650
1150
  required: false
651
- description: Array containing override parameters to override `options` based on tags, operations, methods, paths, or content types.
1151
+ description: |
1152
+ Applies a different set of plugin options to operations that match a pattern. Use this when most of your API should follow the global config, but a handful of endpoints need different treatment.
1153
+
1154
+ Each entry has the same `type` and `pattern` shape as `include`/`exclude`, plus an `options` object that overrides the plugin's options for matched operations.
1155
+
1156
+ Entries are evaluated top to bottom. The first matching entry's `options` is merged onto the plugin defaults; later entries do not stack.
652
1157
  codeBlock:
653
1158
  lang: typescript
654
- title: Override
1159
+ title: Type definition
655
1160
  code: |
656
1161
  export type Override = {
657
1162
  type: 'tag' | 'operationId' | 'path' | 'method' | 'contentType'
658
1163
  pattern: string | RegExp
659
1164
  options: PluginOptions
660
1165
  }
661
- - name: generators
662
- type: Array<Generator<PluginClient>>
663
- required: false
664
- experimental: true
665
- description: |
666
- Define additional generators next to the built-in generators.
667
-
668
- See [Generators](https://kubb.dev/docs/5.x/guides/creating-plugins) for more information on how to use generators.
669
- - name: transformers
670
- type: Visitor
671
- required: false
672
- description: |
673
- A single AST visitor applied to every node before code is printed. Each method you provide replaces the corresponding built-in one. When a method returns `null` or `undefined`, the preset transformer's result is used as the fallback — so you only need to supply the methods you want to change.
674
-
675
- Visitor methods receive the node and a context object. Return a modified node to replace it, or return `undefined`/`void` to leave it unchanged.
676
1166
  examples:
677
- - name: Strip descriptions before printing
1167
+ - name: Use a different enum style for the user tag
678
1168
  files:
679
- - lang: typescript
680
- code: |
681
- import { pluginTs } from '@kubb/plugin-ts'
682
-
683
- pluginTs({
684
- transformer: {
685
- schema(node) {
686
- return { ...node, description: undefined }
687
- },
688
- },
689
- })
1169
+ - name: kubb.config.ts
1170
+ lang: typescript
690
1171
  twoslash: false
691
- - name: Prefix every operationId
692
- files:
693
- - lang: typescript
694
1172
  code: |
1173
+ import { defineConfig } from 'kubb'
695
1174
  import { pluginTs } from '@kubb/plugin-ts'
696
1175
 
697
- pluginTs({
698
- transformer: {
699
- operation(node) {
700
- return { ...node, operationId: `api_${node.operationId}` }
701
- },
702
- },
1176
+ export default defineConfig({
1177
+ input: { path: './petStore.yaml' },
1178
+ output: { path: './src/gen' },
1179
+ plugins: [
1180
+ pluginTs({
1181
+ enumType: 'asConst',
1182
+ override: [
1183
+ {
1184
+ type: 'tag',
1185
+ pattern: 'user',
1186
+ options: { enumType: 'literal' },
1187
+ },
1188
+ ],
1189
+ }),
1190
+ ],
703
1191
  })
704
- twoslash: false
705
- tip: |
706
- Use `transformer` to rewrite node properties before printing. For output naming customization, use `resolver` instead.
1192
+ - name: generators
1193
+ type: Array<Generator<PluginClient>>
1194
+ required: false
1195
+ experimental: true
1196
+ description: |
1197
+ Adds custom generators that run alongside the plugin's built-in generators. Each generator can emit additional files or post-process existing ones using the plugin's AST and options.
1198
+
1199
+ Use this when you need output the plugin does not produce out of the box (a custom client wrapper, an extra index, a metadata file). For end-to-end guidance, see [Creating plugins](https://kubb.dev/docs/5.x/guides/creating-plugins).
1200
+ warning: |
1201
+ Generators are an experimental, low-level API. The signature may change between minor releases.
707
1202
  - name: resolver
708
1203
  type: Partial<ResolverClient> & ThisType<ResolverClient>
709
1204
  required: false
710
- description: Override individual resolver methods to customize generated names. Any method you omit falls back to the preset resolver. Use `this.default(...)` to call the preset's implementation.
1205
+ description: |
1206
+ Overrides naming and path resolution for the generated client. Only the methods you supply replace the defaults; everything else falls back to the built-in resolver.
1207
+
1208
+ Inside each method, `this` is bound to the full resolver, so you can call `this.default(name)` to delegate to the original implementation.
711
1209
  codeBlock:
712
1210
  lang: typescript
1211
+ title: Append "Client" to every name
713
1212
  code: |
1213
+ import { defineConfig } from 'kubb'
714
1214
  import { pluginClient } from '@kubb/plugin-client'
715
1215
 
716
- pluginClient({
717
- resolver: {
718
- resolveName(name) {
719
- return `${this.default(name)}Client`
720
- },
721
- },
1216
+ export default defineConfig({
1217
+ input: { path: './petStore.yaml' },
1218
+ output: { path: './src/gen' },
1219
+ plugins: [
1220
+ pluginClient({
1221
+ resolver: {
1222
+ resolveName(name) {
1223
+ return `${this.default(name)}Client`
1224
+ },
1225
+ },
1226
+ }),
1227
+ ],
722
1228
  })
723
1229
  - name: transformer
724
1230
  type: Visitor
725
1231
  required: false
726
1232
  experimental: true
727
- description: Apply an AST `Visitor` to transform operation nodes before they are printed.
1233
+ description: |
1234
+ AST visitor applied to operation nodes before code is printed. Use this to rewrite operation IDs, tags, or descriptions across the entire client.
728
1235
  codeBlock:
729
1236
  lang: typescript
1237
+ title: Prefix every operationId with "api_"
730
1238
  code: |
1239
+ import { defineConfig } from 'kubb'
731
1240
  import { pluginClient } from '@kubb/plugin-client'
732
1241
 
733
- pluginClient({
734
- transformer: {
735
- operation(node) {
736
- return { ...node, operationId: `api_${node.operationId}` }
737
- },
738
- },
1242
+ export default defineConfig({
1243
+ input: { path: './petStore.yaml' },
1244
+ output: { path: './src/gen' },
1245
+ plugins: [
1246
+ pluginClient({
1247
+ transformer: {
1248
+ operation(node) {
1249
+ return { ...node, operationId: `api_${node.operationId}` }
1250
+ },
1251
+ },
1252
+ }),
1253
+ ],
739
1254
  })
740
1255
  examples:
741
1256
  - name: kubb.config.ts
742
1257
  files:
743
1258
  - lang: typescript
1259
+ twoslash: false
744
1260
  code: |
745
1261
  import { defineConfig } from 'kubb'
746
1262
  import { pluginTs } from '@kubb/plugin-ts'
@@ -755,8 +1271,7 @@ examples:
755
1271
  output: {
756
1272
  path: './clients/axios',
757
1273
  barrel: { type: 'named' },
758
- banner: '/* eslint-disable no-alert, no-console */',
759
- footer: '',
1274
+ banner: '/* eslint-disable */',
760
1275
  },
761
1276
  group: {
762
1277
  type: 'tag',
@@ -776,4 +1291,3 @@ examples:
776
1291
  }),
777
1292
  ],
778
1293
  })
779
- twoslash: false