@kubb/plugin-vue-query 5.0.0-beta.4 → 5.0.0-beta.42

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.
Files changed (42) hide show
  1. package/README.md +39 -22
  2. package/dist/{components-qfOFRSoM.cjs → components-BwFPMwK7.cjs} +367 -381
  3. package/dist/components-BwFPMwK7.cjs.map +1 -0
  4. package/dist/{components-D1UhYFgY.js → components-Bxe1EuWf.js} +337 -381
  5. package/dist/components-Bxe1EuWf.js.map +1 -0
  6. package/dist/components.cjs +1 -1
  7. package/dist/components.d.ts +4 -68
  8. package/dist/components.js +1 -1
  9. package/dist/{generators-C4gs_P1i.cjs → generators-BSN6A0ED.cjs} +163 -206
  10. package/dist/generators-BSN6A0ED.cjs.map +1 -0
  11. package/dist/{generators-CbnIVBgY.js → generators-D9TUvYRN.js} +165 -208
  12. package/dist/generators-D9TUvYRN.js.map +1 -0
  13. package/dist/generators.cjs +1 -1
  14. package/dist/generators.d.ts +21 -6
  15. package/dist/generators.js +1 -1
  16. package/dist/index.cjs +133 -23
  17. package/dist/index.cjs.map +1 -1
  18. package/dist/index.d.ts +31 -4
  19. package/dist/index.js +134 -24
  20. package/dist/index.js.map +1 -1
  21. package/dist/types-HHnnlEhK.d.ts +270 -0
  22. package/extension.yaml +782 -327
  23. package/package.json +15 -17
  24. package/src/components/InfiniteQuery.tsx +16 -48
  25. package/src/components/InfiniteQueryOptions.tsx +43 -58
  26. package/src/components/Mutation.tsx +33 -42
  27. package/src/components/Query.tsx +16 -49
  28. package/src/components/QueryKey.tsx +9 -61
  29. package/src/components/QueryOptions.tsx +20 -76
  30. package/src/generators/infiniteQueryGenerator.tsx +57 -65
  31. package/src/generators/mutationGenerator.tsx +52 -63
  32. package/src/generators/queryGenerator.tsx +54 -63
  33. package/src/plugin.ts +46 -30
  34. package/src/resolvers/resolverVueQuery.ts +61 -4
  35. package/src/types.ts +129 -53
  36. package/src/utils.ts +44 -25
  37. package/dist/components-D1UhYFgY.js.map +0 -1
  38. package/dist/components-qfOFRSoM.cjs.map +0 -1
  39. package/dist/generators-C4gs_P1i.cjs.map +0 -1
  40. package/dist/generators-CbnIVBgY.js.map +0 -1
  41. package/dist/types-nVDTfuS1.d.ts +0 -194
  42. /package/dist/{chunk--u3MIqq1.js → chunk-C0LytTxp.js} +0 -0
package/extension.yaml CHANGED
@@ -2,18 +2,18 @@ $schema: https://kubb.dev/schemas/extension.json
2
2
  kind: plugin
3
3
  id: plugin-vue-query
4
4
  name: Vue Query
5
- description: Generate Vue Query composables from OpenAPI specifications.
5
+ description: Generate TanStack Query composables for Vue (useQuery, useMutation, useInfiniteQuery) from OpenAPI.
6
6
  category: framework
7
7
  type: official
8
- npmPackage: "@kubb/plugin-vue-query"
8
+ npmPackage: '@kubb/plugin-vue-query'
9
9
  docsPath: /plugins/plugin-vue-query
10
10
  repo: https://github.com/kubb-labs/plugins
11
11
  maintainers:
12
12
  - name: Stijn Van Hulle
13
13
  github: stijnvanhulle
14
14
  compatibility:
15
- kubb: ">=5.0.0"
16
- node: ">=22"
15
+ kubb: '>=5.0.0'
16
+ node: '>=22'
17
17
  tags:
18
18
  - vue-query
19
19
  - tanstack-query
@@ -37,159 +37,399 @@ icon:
37
37
  intro: |
38
38
  # @kubb/plugin-vue-query
39
39
 
40
- Generate type-safe Vue Query composables from your OpenAPI schema for data fetching, caching, and synchronization.
40
+ Generate one [TanStack Query](https://tanstack.com/query) composable per OpenAPI operation, ready to use inside Vue's Composition API. Queries become `useFooQuery` (and optionally `useFooInfiniteQuery`); mutations become `useFooMutation`. Each composable is fully typed end to end.
41
+
42
+ Pairs with `@kubb/plugin-client` for the HTTP layer and `@kubb/plugin-ts` for types.
41
43
  options:
42
44
  - name: output
43
45
  type: Output
44
46
  required: false
45
- default: "{ path: 'hooks', barrelType: 'named' }"
46
- description: Specify the export location for the files and define the behavior of the output.
47
+ default: "{ path: 'hooks', barrel: { type: 'named' } }"
48
+ description: Where the generated composables are written and how they are exported.
47
49
  properties:
48
50
  - name: path
49
51
  type: string
50
52
  required: true
51
- description: Output directory or file for the generated code, relative to the global `output.path`.
53
+ description: |
54
+ Folder (or single file) where the plugin writes its generated code. The path is resolved against the global `output.path` set on `defineConfig`.
55
+
56
+ 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
57
  tip: |
53
- if `output.path` is a file, `group` cannot be used.
58
+ When `output.path` points to a single file, the `group` option cannot be used because every operation ends up in the same file.
59
+ examples:
60
+ - name: kubb.config.ts
61
+ files:
62
+ - lang: typescript
63
+ twoslash: false
64
+ code: |
65
+ import { defineConfig } from 'kubb'
66
+ import { pluginTs } from '@kubb/plugin-ts'
67
+
68
+ export default defineConfig({
69
+ input: { path: './petStore.yaml' },
70
+ output: { path: './src/gen' },
71
+ plugins: [
72
+ pluginTs({
73
+ output: { path: './types' },
74
+ }),
75
+ ],
76
+ })
77
+ - name: Resulting tree
78
+ files:
79
+ - lang: text
80
+ twoslash: false
81
+ code: |
82
+ src/
83
+ └── gen/
84
+ └── types/
85
+ ├── Pet.ts
86
+ └── Store.ts
54
87
  default: "'hooks'"
55
- - name: barrelType
56
- type: "'all' | 'named' | 'propagate' | false"
88
+ - name: barrel
89
+ type: "{ type: 'named' | 'all', nested?: boolean } | false"
57
90
  required: false
58
- default: "'named'"
59
- description: Specify what to export and optionally disable barrel-file generation.
91
+ default: "{ type: 'named' }"
92
+ description: |
93
+ Controls how the generated `index.ts` (barrel) file re-exports the plugin's output.
94
+
95
+ - `{ type: 'named' }` re-exports each symbol by name. Best for tree-shaking and explicit imports.
96
+ - `{ type: 'all' }` uses `export *`. Smaller barrel file, but exports everything.
97
+ - `{ nested: true }` creates a barrel in every subdirectory, so callers can import from any depth.
98
+ - `false` skips the barrel entirely. The plugin's files are also excluded from the root `index.ts`.
60
99
  tip: |
61
- Using `propagate` will prevent a plugin from creating a barrel file, but it will still propagate, allowing [`output.barrelType`](https://kubb.dev/docs/5.x/configuration#output-barreltype) to export the specific function or type.
100
+ 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.
62
101
  examples:
63
- - name: all
102
+ - name: "'named' (default)"
64
103
  files:
65
- - lang: typescript
104
+ - name: kubb.config.ts
105
+ lang: typescript
106
+ twoslash: false
66
107
  code: |
67
- export * from './gen/petService.ts'
108
+ import { defineConfig } from 'kubb'
109
+ import { pluginTs } from '@kubb/plugin-ts'
110
+
111
+ export default defineConfig({
112
+ input: { path: './petStore.yaml' },
113
+ output: { path: './src/gen' },
114
+ plugins: [
115
+ pluginTs({
116
+ output: { barrel: { type: 'named' } },
117
+ }),
118
+ ],
119
+ })
120
+ - name: src/gen/types/index.ts
121
+ lang: typescript
68
122
  twoslash: false
69
- - name: named
123
+ code: |
124
+ export { Pet, PetStatus } from './Pet'
125
+ export { Store } from './Store'
126
+ - name: "'all'"
70
127
  files:
71
- - lang: typescript
128
+ - name: kubb.config.ts
129
+ lang: typescript
130
+ twoslash: false
72
131
  code: |
73
- export { PetService } from './gen/petService.ts'
132
+ import { defineConfig } from 'kubb'
133
+ import { pluginTs } from '@kubb/plugin-ts'
134
+
135
+ export default defineConfig({
136
+ input: { path: './petStore.yaml' },
137
+ output: { path: './src/gen' },
138
+ plugins: [
139
+ pluginTs({
140
+ output: { barrel: { type: 'all' } },
141
+ }),
142
+ ],
143
+ })
144
+ - name: src/gen/types/index.ts
145
+ lang: typescript
74
146
  twoslash: false
75
- - name: propagate
147
+ code: |
148
+ export * from './Pet'
149
+ export * from './Store'
150
+ - name: nested
76
151
  files:
77
- - lang: typescript
78
- code: ""
152
+ - name: kubb.config.ts
153
+ lang: typescript
79
154
  twoslash: false
80
- - name: "false"
155
+ code: |
156
+ import { defineConfig } from 'kubb'
157
+ import { pluginTs } from '@kubb/plugin-ts'
158
+
159
+ export default defineConfig({
160
+ input: { path: './petStore.yaml' },
161
+ output: { path: './src/gen' },
162
+ plugins: [
163
+ pluginTs({
164
+ output: { barrel: { type: 'named', nested: true } },
165
+ }),
166
+ ],
167
+ })
168
+ - name: Generated tree
169
+ lang: text
170
+ twoslash: false
171
+ code: |
172
+ src/gen/types/
173
+ ├── index.ts # re-exports ./petController and ./storeController
174
+ ├── petController/
175
+ │ ├── index.ts # re-exports Pet, Store, ...
176
+ │ └── Pet.ts
177
+ └── storeController/
178
+ ├── index.ts
179
+ └── Store.ts
180
+ - name: 'false'
81
181
  files:
82
- - lang: typescript
83
- code: ""
182
+ - name: kubb.config.ts
183
+ lang: typescript
84
184
  twoslash: false
185
+ code: |
186
+ import { defineConfig } from 'kubb'
187
+ import { pluginTs } from '@kubb/plugin-ts'
188
+
189
+ export default defineConfig({
190
+ input: { path: './petStore.yaml' },
191
+ output: { path: './src/gen' },
192
+ plugins: [
193
+ pluginTs({
194
+ output: { barrel: false },
195
+ }),
196
+ ],
197
+ })
198
+ - name: Result
199
+ lang: text
200
+ twoslash: false
201
+ code: |
202
+ # No index.ts is generated for this plugin.
203
+ # Its files are also excluded from the root index.ts.
85
204
  - name: banner
86
- type: "string | ((node: RootNode) => string)"
205
+ type: 'string | ((node: RootNode) => string)'
87
206
  required: false
88
- 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.
207
+ description: |
208
+ Text prepended to every generated file. Useful for license headers, lint disables, or `@ts-nocheck` directives.
209
+
210
+ 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).
211
+ examples:
212
+ - name: Static banner
213
+ files:
214
+ - name: kubb.config.ts
215
+ lang: typescript
216
+ twoslash: false
217
+ code: |
218
+ import { defineConfig } from 'kubb'
219
+ import { pluginTs } from '@kubb/plugin-ts'
220
+
221
+ export default defineConfig({
222
+ input: { path: './petStore.yaml' },
223
+ output: { path: './src/gen' },
224
+ plugins: [
225
+ pluginTs({
226
+ output: {
227
+ banner: '/* eslint-disable */\n// @ts-nocheck',
228
+ },
229
+ }),
230
+ ],
231
+ })
232
+ - name: Generated file
233
+ lang: typescript
234
+ twoslash: false
235
+ code: |
236
+ /* eslint-disable */
237
+ // @ts-nocheck
238
+ export type Pet = {
239
+ id: number
240
+ name: string
241
+ }
242
+ - name: Dynamic banner
243
+ files:
244
+ - name: kubb.config.ts
245
+ lang: typescript
246
+ twoslash: false
247
+ code: |
248
+ import { defineConfig } from 'kubb'
249
+ import { pluginTs } from '@kubb/plugin-ts'
250
+
251
+ export default defineConfig({
252
+ input: { path: './petStore.yaml' },
253
+ output: { path: './src/gen' },
254
+ plugins: [
255
+ pluginTs({
256
+ output: {
257
+ banner: (node) => `// Source: ${node.path}\n// Generated at ${new Date().toISOString()}`,
258
+ },
259
+ }),
260
+ ],
261
+ })
89
262
  - name: footer
90
- type: "string | ((node: RootNode) => string)"
263
+ type: 'string | ((node: RootNode) => string)'
91
264
  required: false
92
- 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.
265
+ description: |
266
+ 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.
267
+
268
+ Pass a string for a static footer, or a function that receives the file's `RootNode` and returns the footer text.
269
+ examples:
270
+ - name: Re-enable lint after a banner disable
271
+ files:
272
+ - name: kubb.config.ts
273
+ lang: typescript
274
+ twoslash: false
275
+ code: |
276
+ import { defineConfig } from 'kubb'
277
+ import { pluginTs } from '@kubb/plugin-ts'
278
+
279
+ export default defineConfig({
280
+ input: { path: './petStore.yaml' },
281
+ output: { path: './src/gen' },
282
+ plugins: [
283
+ pluginTs({
284
+ output: {
285
+ banner: '/* eslint-disable */',
286
+ footer: '/* eslint-enable */',
287
+ },
288
+ }),
289
+ ],
290
+ })
93
291
  - name: override
94
292
  type: boolean
95
293
  required: false
96
- default: "false"
97
- description: Whether Kubb overrides existing external files that can be generated if they already exist.
98
- - name: contentType
99
- type: "'application/json' | (string & {})"
100
- required: false
101
- description: |
102
- Define which content type to use.
294
+ default: 'false'
295
+ description: |
296
+ Allows the plugin to overwrite hand-written files that share a name with a generated file.
103
297
 
104
- By default, Kubb uses the first JSON-valid media type.
298
+ - `false` (default): Kubb skips a file if it already exists and is not marked as generated. This protects manual edits.
299
+ - `true`: Kubb overwrites any file at the target path, including hand-written ones.
300
+ warning: |
301
+ Enable this only when you are sure the target folder contains nothing you need to keep. Local edits are lost on the next generation.
302
+ examples:
303
+ - name: kubb.config.ts
304
+ files:
305
+ - lang: typescript
306
+ twoslash: false
307
+ code: |
308
+ import { defineConfig } from 'kubb'
309
+ import { pluginTs } from '@kubb/plugin-ts'
310
+
311
+ export default defineConfig({
312
+ input: { path: './petStore.yaml' },
313
+ output: { path: './src/gen' },
314
+ plugins: [
315
+ pluginTs({
316
+ output: { override: true },
317
+ }),
318
+ ],
319
+ })
105
320
  - name: group
106
321
  type: Group
107
322
  required: false
108
323
  description: |
109
- Grouping combines files in a folder based on a specific `type`.
324
+ Splits generated files into subfolders based on the operation's tag, so each tag in your OpenAPI spec gets its own directory.
325
+
326
+ 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.
327
+ tip: |
328
+ 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.
110
329
  examples:
111
330
  - name: kubb.config.ts
112
331
  files:
113
332
  - lang: typescript
114
- code: |
115
- group: {
116
- type: 'tag',
117
- name({ group }) {
118
- return `${group}Controller`
119
- }
120
- }
121
333
  twoslash: false
334
+ code: |
335
+ import { defineConfig } from 'kubb'
336
+ import { pluginTs } from '@kubb/plugin-ts'
337
+
338
+ export default defineConfig({
339
+ input: { path: './petStore.yaml' },
340
+ output: { path: './src/gen' },
341
+ plugins: [
342
+ pluginTs({
343
+ group: {
344
+ type: 'tag',
345
+ name: ({ group }) => `${group}Controller`,
346
+ },
347
+ }),
348
+ ],
349
+ })
122
350
  body: |
123
351
  With the configuration above, the generator emits:
124
352
 
125
353
  ```text
126
- .
127
- ├── src/
128
- └── petController/
129
- │ ├── addPet.ts
130
- │ │ └── getPet.ts
131
- │ └── storeController/
132
- │ ├── createStore.ts
133
- │ └── getStoreById.ts
134
- ├── petStore.yaml
135
- ├── kubb.config.ts
136
- └── package.json
354
+ src/gen/
355
+ ├── petController/
356
+ ├── AddPet.ts
357
+ └── GetPet.ts
358
+ └── storeController/
359
+ ├── CreateStore.ts
360
+ └── GetStoreById.ts
137
361
  ```
138
362
  properties:
139
363
  - name: type
140
364
  type: "'tag'"
141
365
  required: true
142
- description: Specify the property to group files by. Required when `group` is defined.
366
+ description: |
367
+ Property used to assign each operation to a group. Required whenever `group` is set.
368
+
369
+ 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.
143
370
  note: |
144
- `Required: true*` means this is required only when the `group` option is used. The `group` option itself is optional.
145
- body: |
146
- - `'tag'`: Uses the first tag from `operation.getTags().at(0)?.name`
371
+ `Required: true*` is conditional only required when the parent `group` option is used. `group` itself stays optional.
147
372
  - name: name
148
- type: "(context: GroupContext) => string"
373
+ type: '(context: GroupContext) => string'
149
374
  required: false
150
375
  default: (ctx) => `${ctx.group}Controller`
151
- description: Return the name of a group based on the group name. This is used for file and identifier generation.
376
+ description: Function that builds the folder/identifier name from a group key (the operation's first tag).
152
377
  - name: client
153
378
  type: ClientImportPath & { clientType?, dataReturnType?, baseURL?, bundle?, paramsCasing? }
154
379
  required: false
155
- description: Client configuration for HTTP request generation.
380
+ description: |
381
+ HTTP client used inside every generated composable. Each composable calls into this client to perform the request.
382
+
383
+ Mirrors a subset of `pluginClient` options. Set these here when the Vue composables need different client behavior than the rest of your app.
156
384
  properties:
157
385
  - name: importPath
158
386
  type: string
159
387
  required: false
160
- description: Path to the client used for API calls. Supports both relative and absolute paths.
388
+ description: |
389
+ Path or module specifier of a custom client module. Generated code imports its HTTP runtime from here instead of `@kubb/plugin-client/clients/{client}`.
390
+
391
+ 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.
161
392
  details:
162
393
  - title: When to use `importPath`
163
394
  body: |
164
- Use `importPath` when you want to:
395
+ Reach for a custom client when you need to:
165
396
 
166
- - **Customize the HTTP client**: Provide your own client implementation with custom configurations (e.g., baseURL, headers, interceptors)
167
- - **Add authentication**: Include authentication tokens or other security mechanisms in your client
168
- - **Override default behavior**: Replace the default Kubb client with your own implementation
397
+ - Add an auth token to every request.
398
+ - Plug in interceptors, retries, or logging.
399
+ - Configure `baseURL` and headers from environment variables.
400
+ - Wrap a library other than `axios`/`fetch`.
169
401
  - title: Default behavior
170
402
  body: |
171
- When `importPath` is not specified:
403
+ Without `importPath`:
404
+
405
+ - `bundle: false` (default) — generated code imports from `@kubb/plugin-client/clients/{axios|fetch}`.
406
+ - `bundle: true` — Kubb writes `.kubb/client.ts` and generated code imports from there.
407
+ - title: Required exports
408
+ body: |
409
+ The module pointed to by `importPath` must satisfy the same shape as the built-in client. At minimum:
172
410
 
173
- - If `bundle: false` (default): Uses `@kubb/plugin-client/clients/${client}` where client is either `axios` or `fetch`.
174
- - If `bundle: true`: Bundles the client into `.kubb/fetch.ts`.
175
- - title: Import structure
176
- body: "Generated code imports the client as a default import and the runtime types as named type imports:"
411
+ - A default export of the `client` function.
412
+ - A `RequestConfig` type.
413
+ - A `ResponseErrorConfig` type.
414
+
415
+ When used together with a query plugin (`@kubb/plugin-react-query`, `@kubb/plugin-vue-query`), it must also export a `Client` type alias.
416
+ - title: How generated files import it
417
+ body: |
418
+ Generated code imports the client as a default import (bound to the local name `client`) and the runtime types as named type imports:
177
419
  codeBlock:
178
420
  lang: typescript
179
- code: |-
180
- /**
181
- * Generated by Kubb (https://kubb.dev/).
182
- * Do not edit manually.
183
- */
421
+ code: |
184
422
  import client from '${client.importPath}'
185
423
  import type { RequestConfig, ResponseErrorConfig } from '${client.importPath}'
186
- // ... rest of generated file
424
+ // ... rest of the generated file
187
425
  important: |
188
- 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.
426
+ 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.
189
427
  codeBlock:
190
428
  lang: typescript
191
- title: client.ts
429
+ title: src/client.ts
192
430
  code: |
431
+ import axios from 'axios'
432
+
193
433
  export type RequestConfig<TData = unknown> = {
194
434
  url?: string
195
435
  method: 'GET' | 'PUT' | 'PATCH' | 'POST' | 'DELETE'
@@ -208,96 +448,191 @@ options:
208
448
 
209
449
  export type ResponseErrorConfig<TError = unknown> = TError
210
450
 
211
- // The Client type alias is required when using query plugins
451
+ // Required when used with @kubb/plugin-react-query or @kubb/plugin-vue-query
212
452
  export type Client = <TData, _TError = unknown, TVariables = unknown>(
213
- config: RequestConfig<TVariables>
453
+ config: RequestConfig<TVariables>,
214
454
  ) => Promise<ResponseConfig<TData>>
215
455
 
216
- export const client: Client = async (config) => { /* ... */ }
456
+ const client: Client = async (config) => {
457
+ const response = await axios.request<TData>({
458
+ ...config,
459
+ headers: {
460
+ Authorization: `Bearer ${process.env.API_TOKEN}`,
461
+ ...config.headers,
462
+ },
463
+ })
464
+
465
+ return response
466
+ }
467
+
217
468
  export default client
218
469
  examples:
219
- - name: kubb.config.ts
470
+ - name: Wire up a custom client
220
471
  files:
221
- - lang: typescript
472
+ - name: kubb.config.ts
473
+ lang: typescript
474
+ twoslash: false
222
475
  code: |
223
476
  import { defineConfig } from 'kubb'
224
477
  import { pluginClient } from '@kubb/plugin-client'
225
478
 
226
479
  export default defineConfig({
227
- // ...
480
+ input: { path: './petStore.yaml' },
481
+ output: { path: './src/gen' },
228
482
  plugins: [
229
483
  pluginClient({
230
- importPath: './src/client.ts', // Path to your custom client
484
+ importPath: './src/client.ts',
231
485
  }),
232
486
  ],
233
487
  })
234
- twoslash: false
235
488
  tip: |
236
- Learn more about defining a custom client [here](https://kubb.dev/plugins/plugin-client#importpath).
489
+ See the [custom client guide](https://kubb.dev/plugins/plugin-client#importpath) for a worked example.
237
490
  - name: dataReturnType
238
491
  type: "'data' | 'full'"
239
492
  required: false
240
493
  default: "'data'"
241
494
  description: |
242
- Return type used when calling the client.
495
+ Shape of the value returned from each generated client function.
243
496
 
244
- - `'data'` returns `ResponseConfig['data']`.
245
- - `'full'` returns the full `ResponseConfig`.
497
+ - `'data'` returns only the response body (`response.data`). Concise and matches what most apps need.
498
+ - `'full'` returns the full response config — body, status code, headers, and the original request. Use this when callers need to inspect headers or status.
246
499
  examples:
247
- - name: data
500
+ - name: "'data' (default)"
248
501
  files:
249
- - lang: typescript
502
+ - name: getPetById.ts
503
+ lang: typescript
504
+ twoslash: false
250
505
  code: |
251
506
  export async function getPetById<TData>(
252
507
  petId: GetPetByIdPathParams,
253
508
  ): Promise<ResponseConfig<TData>['data']> {
254
- ...
509
+ // ...
255
510
  }
511
+ - name: usage.ts
512
+ lang: typescript
256
513
  twoslash: false
257
- - name: full
514
+ code: |
515
+ const pet = await getPetById(1)
516
+ // ^? Pet
517
+ - name: "'full'"
258
518
  files:
259
- - lang: typescript
519
+ - name: getPetById.ts
520
+ lang: typescript
521
+ twoslash: false
260
522
  code: |
261
523
  export async function getPetById<TData>(
262
524
  petId: GetPetByIdPathParams,
263
525
  ): Promise<ResponseConfig<TData>> {
264
- ...
526
+ // ...
265
527
  }
528
+ - name: usage.ts
529
+ lang: typescript
266
530
  twoslash: false
531
+ code: |
532
+ const response = await getPetById(1)
533
+ // ^? ResponseConfig<Pet>
534
+ console.log(response.status, response.headers)
535
+ const pet = response.data
267
536
  - name: baseURL
268
537
  type: string
269
538
  required: false
270
- 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).
539
+ description: |
540
+ 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).
541
+
542
+ Set this when the generated client should point at a different environment (staging, production) than the one written in the spec.
543
+ examples:
544
+ - name: Override the spec's server URL
545
+ files:
546
+ - lang: typescript
547
+ twoslash: false
548
+ code: |
549
+ import { defineConfig } from 'kubb'
550
+ import { pluginClient } from '@kubb/plugin-client'
551
+
552
+ export default defineConfig({
553
+ input: { path: './petStore.yaml' },
554
+ output: { path: './src/gen' },
555
+ plugins: [
556
+ pluginClient({
557
+ baseURL: 'https://petstore.swagger.io/v2',
558
+ }),
559
+ ],
560
+ })
271
561
  - name: clientType
272
562
  type: "'function' | 'class'"
273
563
  required: false
274
564
  default: "'function'"
275
- description: Specify whether to use function-based or class-based clients.
565
+ description: |
566
+ Style of the HTTP client that this plugin imports from `@kubb/plugin-client`.
567
+
568
+ - `'function'` — imports the function client (`getPetById(...)`). Required for query plugins.
569
+ - `'class'` — also generates a wrapper class on top, but only usable inside `@kubb/plugin-client`.
276
570
  warning: |
277
- This plugin is only compatible with `clientType: 'function'` (the default). If `clientType: 'class'` is detected, the plugin will automatically generate its own inline function-based client instead of importing from `@kubb/plugin-client`.
571
+ Query plugins (`@kubb/plugin-react-query`, `@kubb/plugin-vue-query`, `@kubb/plugin-svelte-query`, `@kubb/plugin-solid-query`) work only with `clientType: 'function'`. If you set `clientType: 'class'` here, the plugin falls back to generating its own inline function-based client instead of importing from `@kubb/plugin-client`.
278
572
  - name: bundle
279
573
  type: boolean
280
574
  required: false
281
- default: "false"
282
- description: Controls whether the HTTP client runtime is copied into the generated `.kubb` directory.
283
- body: |
284
- - `true` adds a `.kubb/fetch.ts` file containing the selected client template (fetch or axios). Generated clients remain self-contained.
285
- - `false` keeps generated clients slim by importing the shared runtime from `@kubb/plugin-client/clients/{client}`.
286
- - Override this behavior by providing a custom `client.importPath`.
575
+ default: 'false'
576
+ description: |
577
+ Copies the HTTP client runtime into the generated output, so the consuming app does not need `@kubb/plugin-client` installed at runtime.
578
+
579
+ - `false` (default) generated files import from `@kubb/plugin-client/clients/{client}`. Smaller diff, but the package must be a runtime dependency.
580
+ - `true` Kubb writes a `.kubb/client.ts` file with the client implementation. Generated code imports from that local file and the project no longer pulls `@kubb/plugin-client` at runtime.
581
+ - Setting `client.importPath` overrides both behaviors and uses your custom client instead.
582
+ examples:
583
+ - name: Bundle the runtime
584
+ files:
585
+ - lang: typescript
586
+ twoslash: false
587
+ code: |
588
+ import { defineConfig } from 'kubb'
589
+ import { pluginClient } from '@kubb/plugin-client'
590
+
591
+ export default defineConfig({
592
+ input: { path: './petStore.yaml' },
593
+ output: { path: './src/gen' },
594
+ plugins: [
595
+ pluginClient({
596
+ client: 'fetch',
597
+ bundle: true,
598
+ }),
599
+ ],
600
+ })
287
601
  - name: paramsType
288
602
  type: "'object' | 'inline'"
289
603
  required: false
290
604
  default: "'inline'"
291
- description: Defines how parameters are passed to generated functions. Switch between object-style parameters and inline parameters.
605
+ description: |
606
+ How operation parameters (path, query, headers) are exposed in the generated function signature.
607
+
608
+ - `'inline'` (default) — each parameter is a separate positional argument. Compact for operations with one or two params.
609
+ - `'object'` — every parameter is wrapped in a single object argument. Easier to read for operations with many params and named at the call site.
292
610
  tip: |
293
- When `paramsType` is set to `'object'`, `pathParams` will also be set to `'object'`.
294
- body: |
295
- - `'object'` returns params and pathParams as an object.
296
- - `'inline'` returns params as comma-separated params.
611
+ Setting `paramsType: 'object'` implicitly sets `pathParamsType: 'object'` as well, so call sites are consistent.
297
612
  examples:
298
- - name: object
613
+ - name: "'inline' (default)"
299
614
  files:
300
- - lang: typescript
615
+ - name: Generated client
616
+ lang: typescript
617
+ twoslash: false
618
+ code: |
619
+ export async function deletePet(
620
+ petId: DeletePetPathParams['petId'],
621
+ headers?: DeletePetHeaderParams,
622
+ config: Partial<RequestConfig> = {},
623
+ ) {
624
+ // ...
625
+ }
626
+ - name: Caller
627
+ lang: typescript
628
+ twoslash: false
629
+ code: |
630
+ await deletePet(42)
631
+ - name: "'object'"
632
+ files:
633
+ - name: Generated client
634
+ lang: typescript
635
+ twoslash: false
301
636
  code: |
302
637
  export async function deletePet(
303
638
  {
@@ -309,138 +644,149 @@ options:
309
644
  },
310
645
  config: Partial<RequestConfig> = {},
311
646
  ) {
312
- ...
647
+ // ...
313
648
  }
649
+ - name: Caller
650
+ lang: typescript
314
651
  twoslash: false
315
- - name: inline
316
- files:
317
- - lang: typescript
318
652
  code: |
319
- export async function deletePet(
320
- petId: DeletePetPathParams['petId'],
321
- headers?: DeletePetHeaderParams,
322
- config: Partial<RequestConfig> = {}
323
- ){
324
- ...
325
- }
326
- twoslash: false
653
+ await deletePet({ petId: 42, headers: { 'X-Api-Key': 'secret' } })
327
654
  - name: paramsCasing
328
655
  type: "'camelcase'"
329
656
  required: false
330
- description: Transform parameter names to a specific casing format for path, query, and header parameters in generated client code.
657
+ description: |
658
+ 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.
659
+
660
+ - `'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`.
331
661
  important: |
332
- 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.
333
- body: |
334
- - `'camelcase'` transforms parameter names to camelCase.
662
+ 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.
335
663
  examples:
336
- - name: With paramsCasing camelcase
664
+ - name: "With paramsCasing: 'camelcase'"
337
665
  files:
338
- - lang: typescript
666
+ - name: Generated client
667
+ lang: typescript
668
+ twoslash: false
339
669
  code: |
340
- // Function parameters use camelCase
670
+ // Function takes camelCase parameters
341
671
  export async function deletePet(
342
- petId: DeletePetPathParams['petId'], // ✓ camelCase
672
+ petId: DeletePetPathParams['petId'],
343
673
  headers?: DeletePetHeaderParams,
344
- config: Partial<RequestConfig> = {}
674
+ config: Partial<RequestConfig> = {},
345
675
  ) {
346
- // Automatically maps back to original name for the API
676
+ // ...mapped back to the original API name internally
347
677
  const pet_id = petId
348
678
 
349
- return fetch({
679
+ return client({
350
680
  method: 'DELETE',
351
- url: `/pet/${pet_id}`, // Uses original API parameter name
352
- ...
681
+ url: `/pet/${pet_id}`,
682
+ ...config,
353
683
  })
354
684
  }
685
+ - name: Caller
686
+ lang: typescript
355
687
  twoslash: false
688
+ code: |
689
+ await deletePet(42)
356
690
  - name: Without paramsCasing
357
691
  files:
358
- - lang: typescript
692
+ - name: Generated client
693
+ lang: typescript
694
+ twoslash: false
359
695
  code: |
360
- // Parameters use original API naming
696
+ // Function parameters mirror the OpenAPI spec
361
697
  export async function deletePet(
362
- pet_id: DeletePetPathParams['pet_id'], // Original naming
698
+ pet_id: DeletePetPathParams['pet_id'],
363
699
  headers?: DeletePetHeaderParams,
364
- config: Partial<RequestConfig> = {}
700
+ config: Partial<RequestConfig> = {},
365
701
  ) {
366
- return fetch({
702
+ return client({
367
703
  method: 'DELETE',
368
704
  url: `/pet/${pet_id}`,
369
- ...
705
+ ...config,
370
706
  })
371
707
  }
372
- twoslash: false
373
708
  tip: |
374
- 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.
709
+ Callers write friendly camelCase names. The generated client maps them back to whatever the API expects (snake_case path params, kebab-case headers, ...).
375
710
  - name: pathParamsType
376
711
  type: "'object' | 'inline'"
377
712
  required: false
378
713
  default: "'inline'"
379
- description: Defines how pathParams are passed to generated functions.
380
- body: |
381
- - `'object'` returns pathParams as an object.
382
- - `'inline'` returns pathParams as comma-separated params.
714
+ description: |
715
+ How URL path parameters appear in the generated function signature. Affects only path params; query/header params follow `paramsType`.
716
+
717
+ - `'inline'` (default) each path param is a positional argument: `getPetById(petId)`.
718
+ - `'object'` — path params are wrapped in a single object: `getPetById({ petId })`.
383
719
  examples:
384
- - name: object
720
+ - name: "'inline' (default)"
385
721
  files:
386
722
  - lang: typescript
723
+ twoslash: false
387
724
  code: |
388
725
  export async function getPetById(
389
- { petId }: GetPetByIdPathParams,
726
+ petId: GetPetByIdPathParams,
390
727
  ) {
391
- ...
728
+ // ...
392
729
  }
393
- twoslash: false
394
- - name: inline
730
+ - name: "'object'"
395
731
  files:
396
732
  - lang: typescript
733
+ twoslash: false
397
734
  code: |
398
735
  export async function getPetById(
399
- petId: GetPetByIdPathParams,
736
+ { petId }: GetPetByIdPathParams,
400
737
  ) {
401
- ...
738
+ // ...
402
739
  }
403
- twoslash: false
404
740
  - name: parser
405
- type: "'client' | 'zod'"
741
+ type: false | 'zod'
406
742
  required: false
407
- default: "'client'"
408
- description: Parser used before returning data.
409
- body: |
410
- - `'zod'` uses `@kubb/plugin-zod` to parse data.
411
- - `'client'` returns data without parsing.
743
+ default: 'false'
744
+ description: |
745
+ Runtime validator applied to the response body before it is returned to the caller.
746
+
747
+ - `false` (default) no validation. The client has no runtime parser; the response is cast to the generated TypeScript type and returned as-is. Fastest path, trusts the API.
748
+ - `'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.
749
+
750
+ 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.
751
+ examples:
752
+ - name: Validate responses with Zod
753
+ files:
754
+ - lang: typescript
755
+ twoslash: false
756
+ code: |
757
+ import { defineConfig } from 'kubb'
758
+ import { pluginClient } from '@kubb/plugin-client'
759
+ import { pluginTs } from '@kubb/plugin-ts'
760
+ import { pluginZod } from '@kubb/plugin-zod'
761
+
762
+ export default defineConfig({
763
+ input: { path: './petStore.yaml' },
764
+ output: { path: './src/gen' },
765
+ plugins: [
766
+ pluginTs(),
767
+ pluginZod(),
768
+ pluginClient({
769
+ parser: 'zod',
770
+ }),
771
+ ],
772
+ })
412
773
  - name: infinite
413
774
  type: Infinite | false
414
775
  required: false
415
- default: "false"
776
+ default: 'false'
416
777
  description: |
417
- Generate an `infiniteQuery` composable for paginated queries. Pass `false` to disable.
778
+ Enables `useInfiniteQuery` composables for cursor- or page-based pagination. Pass an object to configure how the cursor is read from the response; pass `false` (default) to skip.
418
779
  typeDefinition: |
419
780
  type Infinite = {
420
- /**
421
- * Specify the params key used for `pageParam`.
422
- * @default `'id'`
423
- */
781
+ /** Query-param key used as the page cursor. Defaults to `'id'`. */
424
782
  queryParam: string
425
- /**
426
- * Which field of the data will be used, set it to undefined when no cursor is known.
427
- * @deprecated Use `nextParam` and `previousParam` instead for more flexible pagination handling.
428
- */
429
- cursorParam?: string | undefined
430
- /**
431
- * Which field of the data will be used to get the cursor for the next page.
432
- * Supports dot notation (e.g. 'pagination.next.id') or array path (e.g. ['pagination', 'next', 'id']) to access nested fields.
433
- */
434
- nextParam?: string | string[] | undefined
435
- /**
436
- * Which field of the data will be used to get the cursor for the previous page.
437
- * Supports dot notation (e.g. 'pagination.prev.id') or array path (e.g. ['pagination', 'prev', 'id']) to access nested fields.
438
- */
439
- previousParam?: string | string[] | undefined
440
- /**
441
- * The initial value, the value of the first page.
442
- * @default `0`
443
- */
783
+ /** @deprecated Use `nextParam` / `previousParam` instead. */
784
+ cursorParam?: string
785
+ /** Path to the next-page cursor in the response. Dot or array form. */
786
+ nextParam?: string | string[]
787
+ /** Path to the previous-page cursor in the response. Dot or array form. */
788
+ previousParam?: string | string[]
789
+ /** Value of `pageParam` for the first page. Defaults to `0`. */
444
790
  initialPageParam: unknown
445
791
  } | false
446
792
  properties:
@@ -448,49 +794,40 @@ options:
448
794
  type: string
449
795
  required: false
450
796
  default: "'id'"
451
- description: Specify the params key used for `pageParam`.
797
+ description: Name of the query parameter that holds the page cursor.
452
798
  - name: initialPageParam
453
799
  type: unknown
454
800
  required: false
455
- default: "0"
456
- description: Specify the initial page param value.
801
+ default: '0'
802
+ description: Initial value for `pageParam` on the first fetch.
457
803
  - name: cursorParam
458
804
  type: string | undefined
459
805
  required: false
460
806
  deprecated:
461
- note: "`cursorParam` is deprecated. Use `nextParam` and `previousParam` instead for more flexible pagination handling."
462
- description: Which field of the data will be used, set it to undefined when no cursor is known.
807
+ note: '`cursorParam` is deprecated. Use `nextParam` and `previousParam` for richer pagination control.'
808
+ description: Path to the cursor field on the response. Leave undefined when the cursor is not known.
463
809
  - name: nextParam
464
810
  type: string | string[] | undefined
465
811
  required: false
466
812
  description: |
467
- Which field of the data will be used to get the cursor for the next page.
468
-
469
- Supports dot notation (e.g. `'pagination.next.id'`) or array path (e.g. `['pagination', 'next', 'id']`) to access nested fields.
813
+ Path to the next-page cursor on the response. Supports dot notation (`'pagination.next.id'`) or array form (`['pagination', 'next', 'id']`).
470
814
  - name: previousParam
471
815
  type: string | string[] | undefined
472
816
  required: false
473
817
  description: |
474
- Which field of the data will be used to get the cursor for the previous page.
475
-
476
- Supports dot notation (e.g. `'pagination.prev.id'`) or array path (e.g. `['pagination', 'prev', 'id']`) to access nested fields.
818
+ Path to the previous-page cursor on the response. Supports dot notation (`'pagination.prev.id'`) or array form.
477
819
  - name: queryKey
478
- type: "(props: { operation: Operation; schemas: OperationSchemas }) => unknown[]"
820
+ type: '(props: { operation: Operation; schemas: OperationSchemas }) => unknown[]'
479
821
  required: false
480
822
  description: |
481
- Customize the queryKey that will be used for the query.
823
+ Builds the `queryKey` for each generated composable. Use this to add a version namespace, swap to operation IDs, or shape keys to match an existing invalidation strategy.
482
824
 
483
- The function receives an object with:
484
- - `operation`: The OpenAPI operation object with methods like `getTags()`, `getOperationId()`, etc.
485
- - `schemas`: An object containing operation schemas including `pathParams`, `queryParams`, `request`, `response`, etc.
825
+ The callback receives the OpenAPI `operation` and a `schemas` object containing `pathParams`, `queryParams`, `request`, and `response`.
486
826
  warning: |
487
- When using a string you need to use `JSON.stringify`.
827
+ String values are inlined verbatim into generated code. Wrap any literal string in `JSON.stringify(...)`.
488
828
  details:
489
- - title: Using tags and path parameters
490
- body: |-
491
- Generate a queryKey with operation tags and path parameters:
492
-
493
- For a GET operation with tags `["user"]` and path parameter `username`, this generates:
829
+ - title: Keys from tags and path parameters
830
+ body: "Build a key from the operation's first tag plus its path parameters:"
494
831
  codeBlock:
495
832
  - lang: typescript
496
833
  code: |-
@@ -498,12 +835,13 @@ options:
498
835
  import { pluginVueQuery } from '@kubb/plugin-vue-query'
499
836
 
500
837
  export default defineConfig({
501
- // ...
838
+ input: { path: './petStore.yaml' },
839
+ output: { path: './src/gen' },
502
840
  plugins: [
503
841
  pluginVueQuery({
504
842
  queryKey: ({ operation, schemas }) => {
505
- const tags = operation.getTags().map(tag => JSON.stringify(tag.name))
506
- const pathParams = schemas.pathParams?.keys || []
843
+ const tags = operation.getTags().map((tag) => JSON.stringify(tag.name))
844
+ const pathParams = schemas.pathParams?.keys ?? []
507
845
  return [...tags, ...pathParams]
508
846
  },
509
847
  }),
@@ -511,13 +849,10 @@ options:
511
849
  })
512
850
  - lang: typescript
513
851
  code: |-
514
- export const getUserByNameQueryKey = ({ username }: { username: GetUserByNamePathParams["username"] }) =>
852
+ export const getUserByNameQueryKey = ({ username }: { username: GetUserByNamePathParams['username'] }) =>
515
853
  ['user', username] as const
516
- - title: Using the default transformer
517
- body: |-
518
- You can extend the default queryKey transformer:
519
-
520
- This prepends a version to the default queryKey:
854
+ - title: Extend the default transformer
855
+ body: 'Prepend a version prefix to the default query key:'
521
856
  codeBlock:
522
857
  - lang: typescript
523
858
  code: |-
@@ -526,7 +861,8 @@ options:
526
861
  import { QueryKey } from '@kubb/plugin-vue-query/components'
527
862
 
528
863
  export default defineConfig({
529
- // ...
864
+ input: { path: './petStore.yaml' },
865
+ output: { path: './src/gen' },
530
866
  plugins: [
531
867
  pluginVueQuery({
532
868
  queryKey: (props) => {
@@ -540,8 +876,7 @@ options:
540
876
  code: |-
541
877
  export const findPetsByTagsQueryKey = (params?: FindPetsByTagsQueryParams) =>
542
878
  ['v5', { url: '/pet/findByTags' }, ...(params ? [params] : [])] as const
543
- - title: Using operation ID
544
- body: "Create a simple queryKey using the operation ID:"
879
+ - title: Key from operationId
545
880
  codeBlock:
546
881
  lang: typescript
547
882
  code: |-
@@ -549,17 +884,15 @@ options:
549
884
  import { pluginVueQuery } from '@kubb/plugin-vue-query'
550
885
 
551
886
  export default defineConfig({
552
- // ...
887
+ input: { path: './petStore.yaml' },
888
+ output: { path: './src/gen' },
553
889
  plugins: [
554
890
  pluginVueQuery({
555
- queryKey: ({ operation }) => {
556
- return [JSON.stringify(operation.getOperationId())]
557
- },
891
+ queryKey: ({ operation }) => [JSON.stringify(operation.getOperationId())],
558
892
  }),
559
893
  ],
560
894
  })
561
- - title: Conditional keys based on parameters
562
- body: "Include query parameters when they exist:"
895
+ - title: Conditional keys based on params
563
896
  codeBlock:
564
897
  lang: typescript
565
898
  code: |-
@@ -567,18 +900,17 @@ options:
567
900
  import { pluginVueQuery } from '@kubb/plugin-vue-query'
568
901
 
569
902
  export default defineConfig({
570
- // ...
903
+ input: { path: './petStore.yaml' },
904
+ output: { path: './src/gen' },
571
905
  plugins: [
572
906
  pluginVueQuery({
573
907
  queryKey: ({ operation, schemas }) => {
574
- const keys = [JSON.stringify(operation.getOperationId())]
908
+ const keys: unknown[] = [JSON.stringify(operation.getOperationId())]
575
909
 
576
- // Add path parameter values (without quotes, so they reference the variables)
577
910
  if (schemas.pathParams?.keys) {
578
911
  keys.push(...schemas.pathParams.keys)
579
912
  }
580
913
 
581
- // Add query params conditionally (the string gets embedded as code)
582
914
  if (schemas.queryParams?.name) {
583
915
  keys.push('...(params ? [params] : [])')
584
916
  }
@@ -592,9 +924,7 @@ options:
592
924
  type: Query
593
925
  required: false
594
926
  description: |
595
- Override some `useQuery` behaviors.
596
-
597
- To disable the creation of hooks pass `false`, this will result in only creating `queryOptions`.
927
+ Configures the query composables. Pass `false` to skip composable generation and emit only `queryOptions(...)` helpers.
598
928
  typeDefinition: |
599
929
  type Query = {
600
930
  methods: Array<HttpMethod>
@@ -605,22 +935,39 @@ options:
605
935
  type: Array<HttpMethod>
606
936
  required: false
607
937
  default: "['get']"
608
- description: Define which HttpMethods can be used for queries.
938
+ description: |
939
+ HTTP methods treated as queries. Operations using one of these methods generate a `useQuery`-style hook (or `queryOptions` helper) instead of a mutation.
940
+
941
+ Defaults to `['get']`. Add other methods (for example `'head'`) only when your API uses them for cache-friendly reads.
942
+ examples:
943
+ - name: Allow HEAD as a query method
944
+ files:
945
+ - lang: typescript
946
+ twoslash: false
947
+ code: |
948
+ import { defineConfig } from 'kubb'
949
+ import { pluginReactQuery } from '@kubb/plugin-react-query'
950
+
951
+ export default defineConfig({
952
+ input: { path: './petStore.yaml' },
953
+ output: { path: './src/gen' },
954
+ plugins: [
955
+ pluginReactQuery({
956
+ query: { methods: ['get', 'head'] },
957
+ }),
958
+ ],
959
+ })
609
960
  - name: importPath
610
961
  type: string
611
962
  required: false
612
963
  default: "'@tanstack/vue-query'"
613
964
  description: |
614
- Path to the `useQuery` that will be used to do the `useQuery` functionality.
615
-
616
- It will be used as `import { useQuery } from '${hook.importPath}'`. It allows both relative and absolute paths. The path will be applied as is, so relative paths should be based on the file being generated.
965
+ Module specifier used in the `import { useQuery } from '...'` statement at the top of every generated composable file. Useful for routing through your own wrapper.
617
966
  - name: mutation
618
967
  type: Mutation
619
968
  required: false
620
969
  description: |
621
- Override some `useMutation` behaviors.
622
-
623
- To disable queries pass `false`.
970
+ Configures mutation composables. Set to `false` to skip mutation generation.
624
971
  typeDefinition: |
625
972
  type Mutation = {
626
973
  methods: Array<HttpMethod>
@@ -630,158 +977,267 @@ options:
630
977
  - name: methods
631
978
  type: Array<HttpMethod>
632
979
  required: false
633
- default: "['post', 'put', 'delete']"
634
- description: Define which HttpMethods can be used for mutations.
980
+ default: "['post', 'put', 'patch', 'delete']"
981
+ description: |
982
+ HTTP methods treated as mutations. Operations using one of these methods generate a `useMutation`-style hook instead of a query.
983
+
984
+ Defaults to `['post', 'put', 'patch', 'delete']`. Narrow the list if your API uses one of these methods for reads.
985
+ examples:
986
+ - name: Treat only POST and PUT as mutations
987
+ files:
988
+ - lang: typescript
989
+ twoslash: false
990
+ code: |
991
+ import { defineConfig } from 'kubb'
992
+ import { pluginReactQuery } from '@kubb/plugin-react-query'
993
+
994
+ export default defineConfig({
995
+ input: { path: './petStore.yaml' },
996
+ output: { path: './src/gen' },
997
+ plugins: [
998
+ pluginReactQuery({
999
+ mutation: { methods: ['post', 'put'] },
1000
+ }),
1001
+ ],
1002
+ })
635
1003
  - name: importPath
636
1004
  type: string
637
1005
  required: false
638
1006
  default: "'@tanstack/vue-query'"
639
1007
  description: |
640
- Path to the `useMutation` that will be used to do the `useMutation` functionality.
641
-
642
- It will be used as `import { useMutation } from '${hook.importPath}'`. It allows both relative and absolute paths. The path will be applied as is, so relative paths should be based on the file being generated.
1008
+ Module specifier used in the `import { useMutation } from '...'` statement at the top of every generated composable file.
643
1009
  - name: mutationKey
644
- type: "(props: { operation: Operation; schemas: OperationSchemas }) => unknown[]"
1010
+ type: '(props: { operation: Operation; schemas: OperationSchemas }) => unknown[]'
645
1011
  required: false
646
- description: Customize the mutationKey.
1012
+ description: |
1013
+ Builds the `mutationKey` for each mutation composable. Useful when you batch invalidations or read mutation state via `useMutationState`.
647
1014
  warning: |
648
- When using a string you need to use `JSON.stringify`.
1015
+ String values are inlined verbatim into generated code. Wrap any literal string in `JSON.stringify(...)`.
649
1016
  - name: include
650
1017
  type: Array<Include>
651
1018
  required: false
652
- description: Array containing include parameters to include tags, operations, methods, paths, or content types.
1019
+ description: |
1020
+ Restricts generation to operations that match at least one entry in the list. Anything not matched is skipped.
1021
+
1022
+ Each entry filters by one of:
1023
+
1024
+ - `tag` — the operation's first tag in the OpenAPI spec.
1025
+ - `operationId` — the operation's `operationId`.
1026
+ - `path` — the URL pattern (`'/pet/{petId}'`).
1027
+ - `method` — HTTP method (`'get'`, `'post'`, ...).
1028
+ - `contentType` — the media type of the request body.
1029
+
1030
+ `pattern` accepts either a string (exact match) or a `RegExp` for fuzzy matches.
653
1031
  codeBlock:
654
1032
  lang: typescript
655
- title: Include
1033
+ title: Type definition
656
1034
  code: |
657
1035
  export type Include = {
658
1036
  type: 'tag' | 'operationId' | 'path' | 'method' | 'contentType'
659
1037
  pattern: string | RegExp
660
1038
  }
1039
+ examples:
1040
+ - name: Only the pet tag
1041
+ files:
1042
+ - name: kubb.config.ts
1043
+ lang: typescript
1044
+ twoslash: false
1045
+ code: |
1046
+ import { defineConfig } from 'kubb'
1047
+ import { pluginTs } from '@kubb/plugin-ts'
1048
+
1049
+ export default defineConfig({
1050
+ input: { path: './petStore.yaml' },
1051
+ output: { path: './src/gen' },
1052
+ plugins: [
1053
+ pluginTs({
1054
+ include: [
1055
+ { type: 'tag', pattern: 'pet' },
1056
+ ],
1057
+ }),
1058
+ ],
1059
+ })
1060
+ - name: Only GET operations under /pet
1061
+ files:
1062
+ - name: kubb.config.ts
1063
+ lang: typescript
1064
+ twoslash: false
1065
+ code: |
1066
+ import { defineConfig } from 'kubb'
1067
+ import { pluginTs } from '@kubb/plugin-ts'
1068
+
1069
+ export default defineConfig({
1070
+ input: { path: './petStore.yaml' },
1071
+ output: { path: './src/gen' },
1072
+ plugins: [
1073
+ pluginTs({
1074
+ include: [
1075
+ { type: 'method', pattern: 'get' },
1076
+ { type: 'path', pattern: /^\/pet/ },
1077
+ ],
1078
+ }),
1079
+ ],
1080
+ })
661
1081
  - name: exclude
662
1082
  type: Array<Exclude>
663
1083
  required: false
664
- description: Array containing exclude parameters to exclude or skip tags, operations, methods, paths, or content types.
1084
+ description: |
1085
+ Skips any operation that matches at least one entry in the list. The opposite of `include`.
1086
+
1087
+ Each entry filters by one of:
1088
+
1089
+ - `tag` — the operation's first tag.
1090
+ - `operationId` — the operation's `operationId`.
1091
+ - `path` — the URL pattern (`'/pet/{petId}'`).
1092
+ - `method` — HTTP method (`'get'`, `'post'`, ...).
1093
+ - `contentType` — the media type of the request body.
1094
+
1095
+ `pattern` accepts a plain string or a `RegExp`. When both `include` and `exclude` are set, `exclude` wins.
665
1096
  codeBlock:
666
1097
  lang: typescript
667
- title: Exclude
1098
+ title: Type definition
668
1099
  code: |
669
1100
  export type Exclude = {
670
1101
  type: 'tag' | 'operationId' | 'path' | 'method' | 'contentType'
671
1102
  pattern: string | RegExp
672
1103
  }
1104
+ examples:
1105
+ - name: Skip everything under the store tag
1106
+ files:
1107
+ - name: kubb.config.ts
1108
+ lang: typescript
1109
+ twoslash: false
1110
+ code: |
1111
+ import { defineConfig } from 'kubb'
1112
+ import { pluginTs } from '@kubb/plugin-ts'
1113
+
1114
+ export default defineConfig({
1115
+ input: { path: './petStore.yaml' },
1116
+ output: { path: './src/gen' },
1117
+ plugins: [
1118
+ pluginTs({
1119
+ exclude: [
1120
+ { type: 'tag', pattern: 'store' },
1121
+ ],
1122
+ }),
1123
+ ],
1124
+ })
1125
+ - name: Skip a specific operation and all delete methods
1126
+ files:
1127
+ - name: kubb.config.ts
1128
+ lang: typescript
1129
+ twoslash: false
1130
+ code: |
1131
+ import { defineConfig } from 'kubb'
1132
+ import { pluginTs } from '@kubb/plugin-ts'
1133
+
1134
+ export default defineConfig({
1135
+ input: { path: './petStore.yaml' },
1136
+ output: { path: './src/gen' },
1137
+ plugins: [
1138
+ pluginTs({
1139
+ exclude: [
1140
+ { type: 'operationId', pattern: 'deletePet' },
1141
+ { type: 'method', pattern: 'delete' },
1142
+ ],
1143
+ }),
1144
+ ],
1145
+ })
673
1146
  - name: override
674
1147
  type: Array<Override>
675
1148
  required: false
676
- description: Array containing override parameters to override `options` based on tags, operations, methods, paths, or content types.
1149
+ description: |
1150
+ 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.
1151
+
1152
+ 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.
1153
+
1154
+ Entries are evaluated top to bottom. The first matching entry's `options` is merged onto the plugin defaults; later entries do not stack.
677
1155
  codeBlock:
678
1156
  lang: typescript
679
- title: Override
1157
+ title: Type definition
680
1158
  code: |
681
1159
  export type Override = {
682
1160
  type: 'tag' | 'operationId' | 'path' | 'method' | 'contentType'
683
1161
  pattern: string | RegExp
684
1162
  options: PluginOptions
685
1163
  }
686
- - name: generators
687
- type: Array<Generator<PluginVueQuery>>
688
- required: false
689
- experimental: true
690
- description: |
691
- Define additional generators next to the built-in generators.
692
-
693
- See [Generators](https://kubb.dev/docs/5.x/guides/creating-plugins) for more information on how to use generators.
694
- - name: transformers
695
- type: Visitor
696
- required: false
697
- description: |
698
- 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.
699
-
700
- Visitor methods receive the node and a context object. Return a modified node to replace it, or return `undefined`/`void` to leave it unchanged.
701
1164
  examples:
702
- - name: Strip descriptions before printing
1165
+ - name: Use a different enum style for the user tag
703
1166
  files:
704
- - lang: typescript
705
- code: |
706
- import { pluginTs } from '@kubb/plugin-ts'
707
-
708
- pluginTs({
709
- transformer: {
710
- schema(node) {
711
- return { ...node, description: undefined }
712
- },
713
- },
714
- })
1167
+ - name: kubb.config.ts
1168
+ lang: typescript
715
1169
  twoslash: false
716
- - name: Prefix every operationId
717
- files:
718
- - lang: typescript
719
1170
  code: |
1171
+ import { defineConfig } from 'kubb'
720
1172
  import { pluginTs } from '@kubb/plugin-ts'
721
1173
 
722
- pluginTs({
723
- transformer: {
724
- operation(node) {
725
- return { ...node, operationId: `api_${node.operationId}` }
726
- },
727
- },
1174
+ export default defineConfig({
1175
+ input: { path: './petStore.yaml' },
1176
+ output: { path: './src/gen' },
1177
+ plugins: [
1178
+ pluginTs({
1179
+ enumType: 'asConst',
1180
+ override: [
1181
+ {
1182
+ type: 'tag',
1183
+ pattern: 'user',
1184
+ options: { enumType: 'literal' },
1185
+ },
1186
+ ],
1187
+ }),
1188
+ ],
728
1189
  })
729
- twoslash: false
730
- tip: |
731
- Use `transformer` to rewrite node properties before printing. For output naming customization, use `resolver` instead.
732
- properties:
733
- - name: name
734
- type: "(name: string, type?: ResolveType) => string"
735
- required: false
736
- description: Customize the names based on the type that is provided by the plugin.
737
- codeBlock:
738
- lang: typescript
739
- code: |
740
- type ResolveType = 'file' | 'function' | 'type' | 'const'
1190
+ - name: generators
1191
+ type: Array<Generator<PluginVueQuery>>
1192
+ required: false
1193
+ experimental: true
1194
+ description: |
1195
+ 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.
1196
+
1197
+ 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).
1198
+ warning: |
1199
+ Generators are an experimental, low-level API. The signature may change between minor releases.
741
1200
  - name: resolver
742
1201
  type: Partial<ResolverVueQuery>
743
1202
  required: false
744
- description: Override individual resolver methods to customize naming conventions.
1203
+ description: |
1204
+ Overrides naming and path resolution for the generated composables. Supply only the methods you want to change; everything else falls back to the default resolver.
745
1205
  - name: transformer
746
1206
  type: ast.Visitor
747
1207
  required: false
748
- description: Single AST visitor applied to each node before printing.
1208
+ description: |
1209
+ AST visitor applied to operation nodes before code is printed. Use this to rewrite operation IDs, tags, or descriptions across the entire output.
1210
+ notes:
1211
+ - type: tip
1212
+ body: |
1213
+ Reference: [TanStack Query for Vue](https://tanstack.com/query/latest/docs/framework/vue/overview) for cache, retries, and devtools.
749
1214
  examples:
750
1215
  - name: kubb.config.ts
751
1216
  files:
752
1217
  - lang: typescript
1218
+ twoslash: false
753
1219
  code: |
754
1220
  import { defineConfig } from 'kubb'
755
1221
  import { pluginTs } from '@kubb/plugin-ts'
756
1222
  import { pluginVueQuery } from '@kubb/plugin-vue-query'
757
1223
 
758
1224
  export default defineConfig({
759
- input: {
760
- path: './petStore.yaml',
761
- },
762
- output: {
763
- path: './src/gen',
764
- },
1225
+ input: { path: './petStore.yaml' },
1226
+ output: { path: './src/gen' },
765
1227
  plugins: [
766
1228
  pluginTs(),
767
1229
  pluginVueQuery({
768
- output: {
769
- path: './hooks',
770
- },
1230
+ output: { path: './hooks' },
771
1231
  group: {
772
1232
  type: 'tag',
773
1233
  name: ({ group }) => `${group}Hooks`,
774
1234
  },
775
- client: {
776
- dataReturnType: 'full',
777
- },
778
- mutation: {
779
- methods: ['post', 'put', 'delete'],
780
- },
1235
+ client: { dataReturnType: 'full' },
1236
+ mutation: { methods: ['post', 'put', 'delete'] },
781
1237
  infinite: {
782
1238
  queryParam: 'next_page',
783
1239
  initialPageParam: 0,
784
- cursorParam: 'nextCursor',
1240
+ nextParam: 'pagination.next.cursor',
785
1241
  },
786
1242
  query: {
787
1243
  methods: ['get'],
@@ -790,4 +1246,3 @@ examples:
790
1246
  }),
791
1247
  ],
792
1248
  })
793
- twoslash: false