@kubb/plugin-react-query 5.0.0-beta.22 → 5.0.0-beta.27

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/dist/{components-BTwB9V-K.js → components-CDmg-RPi.js} +82 -63
  2. package/dist/components-CDmg-RPi.js.map +1 -0
  3. package/dist/{components-D4SQmw7N.cjs → components-MPBTffPl.cjs} +82 -63
  4. package/dist/components-MPBTffPl.cjs.map +1 -0
  5. package/dist/components.cjs +1 -1
  6. package/dist/components.d.ts +1 -1
  7. package/dist/components.js +1 -1
  8. package/dist/{generators-BZ_sX2lp.js → generators-C-cwJah8.js} +97 -57
  9. package/dist/generators-C-cwJah8.js.map +1 -0
  10. package/dist/{generators-C4bV7v9Z.cjs → generators-DozEZKwy.cjs} +97 -57
  11. package/dist/generators-DozEZKwy.cjs.map +1 -0
  12. package/dist/generators.cjs +1 -1
  13. package/dist/generators.d.ts +41 -1
  14. package/dist/generators.js +1 -1
  15. package/dist/index.cjs +51 -11
  16. package/dist/index.cjs.map +1 -1
  17. package/dist/index.d.ts +30 -1
  18. package/dist/index.js +51 -11
  19. package/dist/index.js.map +1 -1
  20. package/dist/{types-DG_OxOym.d.ts → types-DiZPLTXl.d.ts} +92 -55
  21. package/extension.yaml +904 -325
  22. package/package.json +7 -7
  23. package/src/components/InfiniteQuery.tsx +7 -6
  24. package/src/components/InfiniteQueryOptions.tsx +11 -10
  25. package/src/components/Mutation.tsx +7 -5
  26. package/src/components/MutationOptions.tsx +4 -3
  27. package/src/components/Query.tsx +6 -4
  28. package/src/components/QueryOptions.tsx +4 -3
  29. package/src/components/SuspenseInfiniteQuery.tsx +7 -6
  30. package/src/components/SuspenseInfiniteQueryOptions.tsx +11 -10
  31. package/src/components/SuspenseQuery.tsx +6 -4
  32. package/src/generators/customHookOptionsFileGenerator.tsx +7 -1
  33. package/src/generators/hookOptionsGenerator.tsx +14 -8
  34. package/src/generators/infiniteQueryGenerator.tsx +19 -10
  35. package/src/generators/mutationGenerator.tsx +17 -9
  36. package/src/generators/queryGenerator.tsx +17 -9
  37. package/src/generators/suspenseInfiniteQueryGenerator.tsx +19 -10
  38. package/src/generators/suspenseQueryGenerator.tsx +18 -9
  39. package/src/plugin.ts +34 -5
  40. package/src/resolvers/resolverReactQuery.ts +15 -4
  41. package/src/types.ts +89 -52
  42. package/src/utils.ts +8 -1
  43. package/dist/components-BTwB9V-K.js.map +0 -1
  44. package/dist/components-D4SQmw7N.cjs.map +0 -1
  45. package/dist/generators-BZ_sX2lp.js.map +0 -1
  46. package/dist/generators-C4bV7v9Z.cjs.map +0 -1
package/extension.yaml CHANGED
@@ -2,7 +2,7 @@ $schema: https://kubb.dev/schemas/extension.json
2
2
  kind: plugin
3
3
  id: plugin-react-query
4
4
  name: React Query
5
- description: Generate React Query hooks (useQuery, useMutation) from OpenAPI specifications.
5
+ description: Generate TanStack Query hooks for React (useQuery, useMutation, useSuspenseQuery, useInfiniteQuery) from OpenAPI.
6
6
  category: framework
7
7
  type: official
8
8
  npmPackage: '@kubb/plugin-react-query'
@@ -37,162 +37,424 @@ icon:
37
37
  intro: |
38
38
  # @kubb/plugin-react-query
39
39
 
40
- Generate type-safe React Query hooks from your OpenAPI schema for data fetching, caching, and synchronization.
40
+ Generate one [TanStack Query](https://tanstack.com/query) hook per OpenAPI operation. Queries become `useFooQuery`/`useFooSuspenseQuery`/`useFooInfiniteQuery`; mutations become `useFooMutation`. Each hook is fully typed: query keys, input variables, response data, and error shape all come from the spec.
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
47
  default: "{ path: 'hooks', barrel: { type: 'named' } }"
46
- description: Specify the export location for the files and define the behavior of the output.
48
+ description: Where the generated hooks 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
88
  - name: barrel
56
89
  type: "{ type: 'named' | 'all', nested?: boolean } | false"
57
90
  required: false
58
91
  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.'
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`.
99
+ tip: |
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.
60
101
  examples:
61
- - name: all
102
+ - name: "'named' (default)"
62
103
  files:
63
- - lang: typescript
104
+ - name: kubb.config.ts
105
+ lang: typescript
106
+ twoslash: false
64
107
  code: |
65
- 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
66
122
  twoslash: false
67
- - name: named
123
+ code: |
124
+ export { Pet, PetStatus } from './Pet'
125
+ export { Store } from './Store'
126
+ - name: "'all'"
68
127
  files:
69
- - lang: typescript
128
+ - name: kubb.config.ts
129
+ lang: typescript
130
+ twoslash: false
70
131
  code: |
71
- 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
72
146
  twoslash: false
147
+ code: |
148
+ export * from './Pet'
149
+ export * from './Store'
73
150
  - name: nested
74
151
  files:
75
152
  - name: kubb.config.ts
76
153
  lang: typescript
154
+ twoslash: false
77
155
  code: |
78
- output: {
79
- path: './gen',
80
- barrel: { type: 'named', nested: true },
81
- }
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
82
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
83
180
  - name: 'false'
84
181
  files:
85
- - lang: typescript
86
- code: ''
182
+ - name: kubb.config.ts
183
+ lang: typescript
87
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.
88
204
  - name: banner
89
205
  type: 'string | ((node: RootNode) => string)'
90
206
  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.
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
+ })
92
262
  - name: footer
93
263
  type: 'string | ((node: RootNode) => string)'
94
264
  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.
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
+ })
96
291
  - name: override
97
292
  type: boolean
98
293
  required: false
99
294
  default: 'false'
100
- description: Whether Kubb overrides existing external files that can be generated if they already exist.
295
+ description: |
296
+ Allows the plugin to overwrite hand-written files that share a name with a generated file.
297
+
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
+ })
101
320
  - name: contentType
102
321
  type: "'application/json' | (string & {})"
103
322
  required: false
104
323
  description: |
105
- Define which content type to use.
324
+ Selects which request/response media type the generator reads from the OpenAPI spec.
106
325
 
107
- By default, Kubb uses the first JSON-valid media type.
326
+ 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.
327
+ examples:
328
+ - name: JSON API media type
329
+ files:
330
+ - lang: typescript
331
+ twoslash: false
332
+ code: |
333
+ import { defineConfig } from 'kubb'
334
+ import { pluginTs } from '@kubb/plugin-ts'
335
+
336
+ export default defineConfig({
337
+ input: { path: './petStore.yaml' },
338
+ output: { path: './src/gen' },
339
+ plugins: [
340
+ pluginTs({
341
+ contentType: 'application/vnd.api+json',
342
+ }),
343
+ ],
344
+ })
108
345
  - name: group
109
346
  type: Group
110
347
  required: false
111
348
  description: |
112
- Grouping combines files in a folder based on a specific `type`.
349
+ Splits generated files into subfolders based on the operation's tag, so each tag in your OpenAPI spec gets its own directory.
350
+
351
+ 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.
352
+ tip: |
353
+ 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
354
  examples:
114
355
  - name: kubb.config.ts
115
356
  files:
116
357
  - lang: typescript
117
- code: |
118
- group: {
119
- type: 'tag',
120
- name({ group }) {
121
- return `${group}Controller`
122
- }
123
- }
124
358
  twoslash: false
359
+ code: |
360
+ import { defineConfig } from 'kubb'
361
+ import { pluginTs } from '@kubb/plugin-ts'
362
+
363
+ export default defineConfig({
364
+ input: { path: './petStore.yaml' },
365
+ output: { path: './src/gen' },
366
+ plugins: [
367
+ pluginTs({
368
+ group: {
369
+ type: 'tag',
370
+ name: ({ group }) => `${group}Controller`,
371
+ },
372
+ }),
373
+ ],
374
+ })
125
375
  body: |
126
376
  With the configuration above, the generator emits:
127
377
 
128
378
  ```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
379
+ src/gen/
380
+ ├── petController/
381
+ ├── AddPet.ts
382
+ └── GetPet.ts
383
+ └── storeController/
384
+ ├── CreateStore.ts
385
+ └── GetStoreById.ts
140
386
  ```
141
387
  properties:
142
388
  - name: type
143
389
  type: "'tag'"
144
390
  required: true
145
- description: Specify the property to group files by. Required when `group` is defined.
391
+ description: |
392
+ Property used to assign each operation to a group. Required whenever `group` is set.
393
+
394
+ 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
395
  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`
396
+ `Required: true*` is conditional only required when the parent `group` option is used. `group` itself stays optional.
150
397
  - name: name
151
398
  type: '(context: GroupContext) => string'
152
399
  required: false
153
400
  default: (ctx) => `${ctx.group}Controller`
154
- description: Return the name of a group based on the group name. This is used for file and identifier generation.
401
+ description: Function that builds the folder/identifier name from a group key (the operation's first tag).
155
402
  - name: client
156
403
  type: ClientImportPath & { clientType?, dataReturnType?, baseURL?, bundle? }
157
404
  required: false
158
- description: Client configuration for HTTP request generation.
405
+ description: |
406
+ HTTP client used inside every generated hook. Each generated hook calls into this client to perform the actual request.
407
+
408
+ Mirrors a subset of `pluginClient` options. Set these here when the React Query hooks need different client behavior than the rest of your app (for example, a different base URL or full response objects).
159
409
  properties:
160
410
  - name: importPath
161
411
  type: string
162
412
  required: false
163
- description: Path to the client used for API calls. Supports both relative and absolute paths.
413
+ description: |
414
+ Path or module specifier of a custom client module. Generated code imports its HTTP runtime from here instead of `@kubb/plugin-client/clients/{client}`.
415
+
416
+ 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.
164
417
  details:
165
418
  - title: When to use `importPath`
166
419
  body: |
167
- Use `importPath` when you want to:
420
+ Reach for a custom client when you need to:
168
421
 
169
- - **Customize the HTTP client**: Provide your own client implementation with custom configurations (e.g., baseURL, headers, interceptors)
170
- - **Add authentication**: Include authentication tokens or other security mechanisms in your client
171
- - **Override default behavior**: Replace the default Kubb client with your own implementation
422
+ - Add an auth token to every request.
423
+ - Plug in interceptors, retries, or logging.
424
+ - Configure `baseURL` and headers from environment variables.
425
+ - Wrap a library other than `axios`/`fetch`.
172
426
  - title: Default behavior
173
427
  body: |
174
- When `importPath` is not specified:
428
+ Without `importPath`:
175
429
 
176
- - If `bundle: false` (default): Uses `@kubb/plugin-client/clients/${client}` where client is either `axios` or `fetch`.
177
- - If `bundle: true`: Bundles the client into `.kubb/fetch.ts`.
178
- - title: Import structure
179
- body: 'Generated code imports the client as a default import and the runtime types as named type imports:'
430
+ - `bundle: false` (default) generated code imports from `@kubb/plugin-client/clients/{axios|fetch}`.
431
+ - `bundle: true` Kubb writes `.kubb/fetch.ts` (or `.kubb/axios.ts`) and generated code imports from there.
432
+ - title: Required exports
433
+ body: |
434
+ The module pointed to by `importPath` must satisfy the same shape as the built-in client. At minimum:
435
+
436
+ - A default export of the `client` function.
437
+ - A `RequestConfig` type.
438
+ - A `ResponseErrorConfig` type.
439
+
440
+ When used together with a query plugin (`@kubb/plugin-react-query`, `@kubb/plugin-vue-query`), it must also export a `Client` type alias.
441
+ - title: How generated files import it
442
+ body: |
443
+ Generated code imports the client as a default import and the runtime types as named type imports:
180
444
  codeBlock:
181
445
  lang: typescript
182
- code: |-
183
- /**
184
- * Generated by Kubb (https://kubb.dev/).
185
- * Do not edit manually.
186
- */
446
+ code: |
187
447
  import client from '${client.importPath}'
188
448
  import type { RequestConfig, ResponseErrorConfig } from '${client.importPath}'
189
- // ... rest of generated file
449
+ // ... rest of the generated file
190
450
  important: |
191
- 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.
451
+ 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.
192
452
  codeBlock:
193
453
  lang: typescript
194
- title: client.ts
454
+ title: src/client.ts
195
455
  code: |
456
+ import axios from 'axios'
457
+
196
458
  export type RequestConfig<TData = unknown> = {
197
459
  url?: string
198
460
  method: 'GET' | 'PUT' | 'PATCH' | 'POST' | 'DELETE'
@@ -211,96 +473,191 @@ options:
211
473
 
212
474
  export type ResponseErrorConfig<TError = unknown> = TError
213
475
 
214
- // The Client type alias is required when using query plugins
476
+ // Required when used with @kubb/plugin-react-query or @kubb/plugin-vue-query
215
477
  export type Client = <TData, _TError = unknown, TVariables = unknown>(
216
- config: RequestConfig<TVariables>
478
+ config: RequestConfig<TVariables>,
217
479
  ) => Promise<ResponseConfig<TData>>
218
480
 
219
- export const client: Client = async (config) => { /* ... */ }
481
+ const client: Client = async (config) => {
482
+ const response = await axios.request<TData>({
483
+ ...config,
484
+ headers: {
485
+ Authorization: `Bearer ${process.env.API_TOKEN}`,
486
+ ...config.headers,
487
+ },
488
+ })
489
+
490
+ return response
491
+ }
492
+
220
493
  export default client
221
494
  examples:
222
- - name: kubb.config.ts
495
+ - name: Wire up a custom client
223
496
  files:
224
- - lang: typescript
497
+ - name: kubb.config.ts
498
+ lang: typescript
499
+ twoslash: false
225
500
  code: |
226
501
  import { defineConfig } from 'kubb'
227
502
  import { pluginClient } from '@kubb/plugin-client'
228
503
 
229
504
  export default defineConfig({
230
- // ...
505
+ input: { path: './petStore.yaml' },
506
+ output: { path: './src/gen' },
231
507
  plugins: [
232
508
  pluginClient({
233
- importPath: './src/client.ts', // Path to your custom client
509
+ importPath: './src/client.ts',
234
510
  }),
235
511
  ],
236
512
  })
237
- twoslash: false
238
513
  tip: |
239
- Learn more about defining a custom client [here](https://kubb.dev/plugins/plugin-client#importpath).
514
+ See the [custom client guide](https://kubb.dev/plugins/plugin-client#importpath) for a worked example.
240
515
  - name: dataReturnType
241
516
  type: "'data' | 'full'"
242
517
  required: false
243
518
  default: "'data'"
244
519
  description: |
245
- Return type used when calling the client.
520
+ Shape of the value returned from each generated client function.
246
521
 
247
- - `'data'` returns `ResponseConfig['data']`.
248
- - `'full'` returns the full `ResponseConfig`.
522
+ - `'data'` returns only the response body (`response.data`). Concise and matches what most apps need.
523
+ - `'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
524
  examples:
250
- - name: data
525
+ - name: "'data' (default)"
251
526
  files:
252
- - lang: typescript
527
+ - name: getPetById.ts
528
+ lang: typescript
529
+ twoslash: false
253
530
  code: |
254
531
  export async function getPetById<TData>(
255
532
  petId: GetPetByIdPathParams,
256
533
  ): Promise<ResponseConfig<TData>['data']> {
257
- ...
534
+ // ...
258
535
  }
536
+ - name: usage.ts
537
+ lang: typescript
259
538
  twoslash: false
260
- - name: full
539
+ code: |
540
+ const pet = await getPetById(1)
541
+ // ^? Pet
542
+ - name: "'full'"
261
543
  files:
262
- - lang: typescript
544
+ - name: getPetById.ts
545
+ lang: typescript
546
+ twoslash: false
263
547
  code: |
264
548
  export async function getPetById<TData>(
265
549
  petId: GetPetByIdPathParams,
266
550
  ): Promise<ResponseConfig<TData>> {
267
- ...
551
+ // ...
268
552
  }
553
+ - name: usage.ts
554
+ lang: typescript
269
555
  twoslash: false
556
+ code: |
557
+ const response = await getPetById(1)
558
+ // ^? ResponseConfig<Pet>
559
+ console.log(response.status, response.headers)
560
+ const pet = response.data
270
561
  - name: baseURL
271
562
  type: string
272
563
  required: false
273
- 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).
564
+ description: |
565
+ 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).
566
+
567
+ Set this when the generated client should point at a different environment (staging, production) than the one written in the spec.
568
+ examples:
569
+ - name: Override the spec's server URL
570
+ files:
571
+ - lang: typescript
572
+ twoslash: false
573
+ code: |
574
+ import { defineConfig } from 'kubb'
575
+ import { pluginClient } from '@kubb/plugin-client'
576
+
577
+ export default defineConfig({
578
+ input: { path: './petStore.yaml' },
579
+ output: { path: './src/gen' },
580
+ plugins: [
581
+ pluginClient({
582
+ baseURL: 'https://petstore.swagger.io/v2',
583
+ }),
584
+ ],
585
+ })
274
586
  - name: clientType
275
587
  type: "'function' | 'class'"
276
588
  required: false
277
589
  default: "'function'"
278
- description: Specify whether to use function-based or class-based clients.
590
+ description: |
591
+ Style of the HTTP client that this plugin imports from `@kubb/plugin-client`.
592
+
593
+ - `'function'` — imports the function client (`getPetById(...)`). Required for query plugins.
594
+ - `'class'` — also generates a wrapper class on top, but only usable inside `@kubb/plugin-client`.
279
595
  warning: |
280
- 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`.
596
+ 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`.
281
597
  - name: bundle
282
598
  type: boolean
283
599
  required: false
284
600
  default: 'false'
285
- description: Controls whether the HTTP client runtime is copied into the generated `.kubb` directory.
286
- body: |
287
- - `true` adds a `.kubb/fetch.ts` file containing the selected client template (fetch or axios). Generated clients remain self-contained.
288
- - `false` keeps generated clients slim by importing the shared runtime from `@kubb/plugin-client/clients/{client}`.
289
- - Override this behavior by providing a custom `client.importPath`.
601
+ description: |
602
+ Copies the HTTP client runtime into the generated output, so the consuming app does not need `@kubb/plugin-client` installed at runtime.
603
+
604
+ - `false` (default) generated files import from `@kubb/plugin-client/clients/{client}`. Smaller diff, but the package must be a runtime dependency.
605
+ - `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.
606
+ - Setting `client.importPath` overrides both behaviors and uses your custom client instead.
607
+ examples:
608
+ - name: Bundle the runtime
609
+ files:
610
+ - lang: typescript
611
+ twoslash: false
612
+ code: |
613
+ import { defineConfig } from 'kubb'
614
+ import { pluginClient } from '@kubb/plugin-client'
615
+
616
+ export default defineConfig({
617
+ input: { path: './petStore.yaml' },
618
+ output: { path: './src/gen' },
619
+ plugins: [
620
+ pluginClient({
621
+ client: 'fetch',
622
+ bundle: true,
623
+ }),
624
+ ],
625
+ })
290
626
  - name: paramsType
291
627
  type: "'object' | 'inline'"
292
628
  required: false
293
629
  default: "'inline'"
294
- description: Defines how parameters are passed to generated functions. Switch between object-style parameters and inline parameters.
630
+ description: |
631
+ How operation parameters (path, query, headers) are exposed in the generated function signature.
632
+
633
+ - `'inline'` (default) — each parameter is a separate positional argument. Compact for operations with one or two params.
634
+ - `'object'` — every parameter is wrapped in a single object argument. Easier to read for operations with many params and named at the call site.
295
635
  tip: |
296
- When `paramsType` is set to `'object'`, `pathParams` will also be set to `'object'`.
297
- body: |
298
- - `'object'` returns params and pathParams as an object.
299
- - `'inline'` returns params as comma-separated params.
636
+ Setting `paramsType: 'object'` implicitly sets `pathParamsType: 'object'` as well, so call sites are consistent.
300
637
  examples:
301
- - name: object
638
+ - name: "'inline' (default)"
302
639
  files:
303
- - lang: typescript
640
+ - name: Generated client
641
+ lang: typescript
642
+ twoslash: false
643
+ code: |
644
+ export async function deletePet(
645
+ petId: DeletePetPathParams['petId'],
646
+ headers?: DeletePetHeaderParams,
647
+ config: Partial<RequestConfig> = {},
648
+ ) {
649
+ // ...
650
+ }
651
+ - name: Caller
652
+ lang: typescript
653
+ twoslash: false
654
+ code: |
655
+ await deletePet(42)
656
+ - name: "'object'"
657
+ files:
658
+ - name: Generated client
659
+ lang: typescript
660
+ twoslash: false
304
661
  code: |
305
662
  export async function deletePet(
306
663
  {
@@ -312,141 +669,152 @@ options:
312
669
  },
313
670
  config: Partial<RequestConfig> = {},
314
671
  ) {
315
- ...
672
+ // ...
316
673
  }
674
+ - name: Caller
675
+ lang: typescript
317
676
  twoslash: false
318
- - name: inline
319
- files:
320
- - lang: typescript
321
677
  code: |
322
- export async function deletePet(
323
- petId: DeletePetPathParams['petId'],
324
- headers?: DeletePetHeaderParams,
325
- config: Partial<RequestConfig> = {}
326
- ){
327
- ...
328
- }
329
- twoslash: false
678
+ await deletePet({ petId: 42, headers: { 'X-Api-Key': 'secret' } })
330
679
  - name: paramsCasing
331
680
  type: "'camelcase'"
332
681
  required: false
333
- description: Transform parameter names to a specific casing format for path, query, and header parameters in generated client code.
682
+ description: |
683
+ 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.
684
+
685
+ - `'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`.
334
686
  important: |
335
- 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.
336
- body: |
337
- - `'camelcase'` transforms parameter names to camelCase.
687
+ 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.
338
688
  examples:
339
- - name: With paramsCasing camelcase
689
+ - name: "With paramsCasing: 'camelcase'"
340
690
  files:
341
- - lang: typescript
691
+ - name: Generated client
692
+ lang: typescript
693
+ twoslash: false
342
694
  code: |
343
- // Function parameters use camelCase
695
+ // Function takes camelCase parameters
344
696
  export async function deletePet(
345
- petId: DeletePetPathParams['petId'], // ✓ camelCase
697
+ petId: DeletePetPathParams['petId'],
346
698
  headers?: DeletePetHeaderParams,
347
- config: Partial<RequestConfig> = {}
699
+ config: Partial<RequestConfig> = {},
348
700
  ) {
349
- // Automatically maps back to original name for the API
701
+ // ...mapped back to the original API name internally
350
702
  const pet_id = petId
351
703
 
352
704
  return fetch({
353
705
  method: 'DELETE',
354
- url: `/pet/${pet_id}`, // Uses original API parameter name
355
- ...
706
+ url: `/pet/${pet_id}`,
707
+ ...config,
356
708
  })
357
709
  }
710
+ - name: Caller
711
+ lang: typescript
358
712
  twoslash: false
713
+ code: |
714
+ await deletePet(42)
359
715
  - name: Without paramsCasing
360
716
  files:
361
- - lang: typescript
717
+ - name: Generated client
718
+ lang: typescript
719
+ twoslash: false
362
720
  code: |
363
- // Parameters use original API naming
721
+ // Function parameters mirror the OpenAPI spec
364
722
  export async function deletePet(
365
- pet_id: DeletePetPathParams['pet_id'], // Original naming
723
+ pet_id: DeletePetPathParams['pet_id'],
366
724
  headers?: DeletePetHeaderParams,
367
- config: Partial<RequestConfig> = {}
725
+ config: Partial<RequestConfig> = {},
368
726
  ) {
369
727
  return fetch({
370
728
  method: 'DELETE',
371
729
  url: `/pet/${pet_id}`,
372
- ...
730
+ ...config,
373
731
  })
374
732
  }
375
- twoslash: false
376
733
  tip: |
377
- 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.
734
+ Callers write friendly camelCase names. The generated client maps them back to whatever the API expects (snake_case path params, kebab-case headers, ...).
378
735
  - name: pathParamsType
379
736
  type: "'object' | 'inline'"
380
737
  required: false
381
738
  default: "'inline'"
382
- description: Defines how pathParams are passed to generated functions.
383
- body: |
384
- - `'object'` returns pathParams as an object.
385
- - `'inline'` returns pathParams as comma-separated params.
739
+ description: |
740
+ How URL path parameters appear in the generated function signature. Affects only path params; query/header params follow `paramsType`.
741
+
742
+ - `'inline'` (default) each path param is a positional argument: `getPetById(petId)`.
743
+ - `'object'` — path params are wrapped in a single object: `getPetById({ petId })`.
386
744
  examples:
387
- - name: object
745
+ - name: "'inline' (default)"
388
746
  files:
389
747
  - lang: typescript
748
+ twoslash: false
390
749
  code: |
391
750
  export async function getPetById(
392
- { petId }: GetPetByIdPathParams,
751
+ petId: GetPetByIdPathParams,
393
752
  ) {
394
- ...
753
+ // ...
395
754
  }
396
- twoslash: false
397
- - name: inline
755
+ - name: "'object'"
398
756
  files:
399
757
  - lang: typescript
758
+ twoslash: false
400
759
  code: |
401
760
  export async function getPetById(
402
- petId: GetPetByIdPathParams,
761
+ { petId }: GetPetByIdPathParams,
403
762
  ) {
404
- ...
763
+ // ...
405
764
  }
406
- twoslash: false
407
765
  - name: parser
408
766
  type: "'client' | 'zod'"
409
767
  required: false
410
768
  default: "'client'"
411
- description: Parser used before returning data.
412
- body: |
413
- - `'zod'` uses `@kubb/plugin-zod` to parse data.
414
- - `'client'` returns data without parsing.
769
+ description: |
770
+ Runtime validator applied to the response body before it is returned to the caller.
771
+
772
+ - `'client'` (default) no validation. The response is cast to the generated TypeScript type and returned as-is. Fastest path, trusts the API.
773
+ - `'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.
774
+
775
+ 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.
776
+ examples:
777
+ - name: Validate responses with Zod
778
+ files:
779
+ - lang: typescript
780
+ twoslash: false
781
+ code: |
782
+ import { defineConfig } from 'kubb'
783
+ import { pluginClient } from '@kubb/plugin-client'
784
+ import { pluginTs } from '@kubb/plugin-ts'
785
+ import { pluginZod } from '@kubb/plugin-zod'
786
+
787
+ export default defineConfig({
788
+ input: { path: './petStore.yaml' },
789
+ output: { path: './src/gen' },
790
+ plugins: [
791
+ pluginTs(),
792
+ pluginZod(),
793
+ pluginClient({
794
+ parser: 'zod',
795
+ }),
796
+ ],
797
+ })
415
798
  - name: infinite
416
799
  type: Infinite | false
417
800
  required: false
418
801
  default: 'false'
419
802
  description: |
420
- Generate an `infiniteQuery` hook for paginated queries. Pass `false` to disable.
803
+ Enables `useInfiniteQuery` hooks for cursor- or page-based pagination. Pass an object to configure how the cursor is read from the response; pass `false` (default) to skip infinite query generation.
421
804
  codeBlock:
422
805
  lang: typescript
423
- title: Infinite
806
+ title: Infinite type
424
807
  code: |
425
808
  type Infinite = {
426
- /**
427
- * Specify the params key used for `pageParam`.
428
- * @default `'id'`
429
- */
809
+ /** Query-param key used as the page cursor. Defaults to `'id'`. */
430
810
  queryParam: string
431
- /**
432
- * Which field of the data will be used, set it to undefined when no cursor is known.
433
- * @deprecated Use `nextParam` and `previousParam` instead for more flexible pagination handling.
434
- */
435
- cursorParam?: string | undefined
436
- /**
437
- * Which field of the data will be used to get the cursor for the next page.
438
- * Supports dot notation (e.g. 'pagination.next.id') or array path (e.g. ['pagination', 'next', 'id']) to access nested fields.
439
- */
440
- nextParam?: string | string[] | undefined
441
- /**
442
- * Which field of the data will be used to get the cursor for the previous page.
443
- * Supports dot notation (e.g. 'pagination.prev.id') or array path (e.g. ['pagination', 'prev', 'id']) to access nested fields.
444
- */
445
- previousParam?: string | string[] | undefined
446
- /**
447
- * The initial value, the value of the first page.
448
- * @default `0`
449
- */
811
+ /** @deprecated Use `nextParam` / `previousParam` instead. */
812
+ cursorParam?: string
813
+ /** Path to the next-page cursor in the response. Dot or array form. */
814
+ nextParam?: string | string[]
815
+ /** Path to the previous-page cursor in the response. Dot or array form. */
816
+ previousParam?: string | string[]
817
+ /** Value of `pageParam` for the first page. Defaults to `0`. */
450
818
  initialPageParam: unknown
451
819
  } | false
452
820
  properties:
@@ -454,42 +822,59 @@ options:
454
822
  type: string
455
823
  required: false
456
824
  default: "'id'"
457
- description: Specify the params key used for `pageParam`.
825
+ description: Name of the query parameter that holds the page cursor (Kubb passes `pageParam` into this query key).
458
826
  - name: initialPageParam
459
827
  type: unknown
460
828
  required: false
461
829
  default: '0'
462
- description: Specify the initial page param value.
830
+ description: Initial value for `pageParam` on the first fetch.
463
831
  - name: cursorParam
464
832
  type: string | undefined
465
833
  required: false
466
834
  deprecated:
467
- note: '`cursorParam` is deprecated. Use `nextParam` and `previousParam` instead for more flexible pagination handling.'
468
- description: Which field of the data will be used, set it to undefined when no cursor is known.
835
+ note: '`cursorParam` is deprecated. Use `nextParam` and `previousParam` for richer pagination control.'
836
+ description: Path to the cursor field on the response. Leave undefined when the cursor is not known.
469
837
  - name: nextParam
470
838
  type: string | string[] | undefined
471
839
  required: false
472
840
  description: |
473
- Which field of the data will be used to get the cursor for the next page.
474
-
475
- Supports dot notation (e.g. `'pagination.next.id'`) or array path (e.g. `['pagination', 'next', 'id']`) to access nested fields.
841
+ Path to the next-page cursor on the response. Supports dot notation (`'pagination.next.id'`) or array form (`['pagination', 'next', 'id']`).
476
842
  - name: previousParam
477
843
  type: string | string[] | undefined
478
844
  required: false
479
845
  description: |
480
- Which field of the data will be used to get the cursor for the previous page.
846
+ Path to the previous-page cursor on the response. Supports dot notation (`'pagination.prev.id'`) or array form (`['pagination', 'prev', 'id']`).
847
+ examples:
848
+ - name: Cursor pagination
849
+ files:
850
+ - lang: typescript
851
+ twoslash: false
852
+ code: |
853
+ import { defineConfig } from 'kubb'
854
+ import { pluginReactQuery } from '@kubb/plugin-react-query'
481
855
 
482
- Supports dot notation (e.g. `'pagination.prev.id'`) or array path (e.g. `['pagination', 'prev', 'id']`) to access nested fields.
856
+ export default defineConfig({
857
+ input: { path: './petStore.yaml' },
858
+ output: { path: './src/gen' },
859
+ plugins: [
860
+ pluginReactQuery({
861
+ infinite: {
862
+ queryParam: 'cursor',
863
+ initialPageParam: null,
864
+ nextParam: 'pagination.next.cursor',
865
+ previousParam: 'pagination.prev.cursor',
866
+ },
867
+ }),
868
+ ],
869
+ })
483
870
  - name: query
484
871
  type: Query
485
872
  required: false
486
873
  description: |
487
- Override some `useQuery` behaviors.
488
-
489
- To disable the creation of hooks pass `false`, this will result in only creating `queryOptions`.
874
+ Configures the query hooks. Pass `false` to skip generating hooks entirely and only emit `queryOptions(...)` helpers — useful when you want to call `useQuery` yourself in app code.
490
875
  codeBlock:
491
876
  lang: typescript
492
- title: Query
877
+ title: Query type
493
878
  code: |
494
879
  type Query = {
495
880
  methods: Array<HttpMethod>
@@ -500,32 +885,49 @@ options:
500
885
  type: Array<HttpMethod>
501
886
  required: false
502
887
  default: "['get']"
503
- description: Define which HttpMethods can be used for queries.
888
+ description: |
889
+ HTTP methods treated as queries. Operations using one of these methods generate a `useQuery`-style hook (or `queryOptions` helper) instead of a mutation.
890
+
891
+ Defaults to `['get']`. Add other methods (for example `'head'`) only when your API uses them for cache-friendly reads.
892
+ examples:
893
+ - name: Allow HEAD as a query method
894
+ files:
895
+ - lang: typescript
896
+ twoslash: false
897
+ code: |
898
+ import { defineConfig } from 'kubb'
899
+ import { pluginReactQuery } from '@kubb/plugin-react-query'
900
+
901
+ export default defineConfig({
902
+ input: { path: './petStore.yaml' },
903
+ output: { path: './src/gen' },
904
+ plugins: [
905
+ pluginReactQuery({
906
+ query: { methods: ['get', 'head'] },
907
+ }),
908
+ ],
909
+ })
504
910
  - name: importPath
505
911
  type: string
506
912
  required: false
507
913
  default: "'@tanstack/react-query'"
508
914
  description: |
509
- Path to the `useQuery` that will be used to do the `useQuery` functionality.
510
- It will be used as `import { useQuery } from '${hook.importPath}'`.
511
- It allows both relative and absolute path. The path will be applied as is, so a relative path should be based on the file being generated.
915
+ Module specifier used in the `import { useQuery } from '...'` statement at the top of every generated hook file. Use this to point at your own re-export of TanStack Query (for example a wrapper that injects a default `queryClient`).
512
916
  - name: queryKey
513
917
  type: '(props: { operation: Operation; schemas: OperationSchemas }) => unknown[]'
514
918
  required: false
515
919
  description: |
516
- Customize the queryKey that will be used for the query.
920
+ Builds the `queryKey` for each generated hook. Use this to add a version namespace, swap to operation IDs, or shape keys to match an existing `queryClient.invalidateQueries` strategy.
921
+
922
+ The callback receives:
517
923
 
518
- The function receives an object with:
519
- - `operation`: The OpenAPI operation object with methods like `getTags()`, `getOperationId()`, etc.
520
- - `schemas`: An object containing operation schemas including `pathParams`, `queryParams`, `request`, `response`, etc.
924
+ - `operation` the OpenAPI operation (`getTags()`, `getOperationId()`, ...).
925
+ - `schemas` operation schemas including `pathParams`, `queryParams`, `request`, `response`.
521
926
  warning: |
522
- When using a string you need to use `JSON.stringify`.
927
+ String values are inlined verbatim into generated code. Wrap any string you want emitted as a literal in `JSON.stringify(...)`.
523
928
  details:
524
- - title: Using tags and path parameters
525
- body: |-
526
- Generate a queryKey with operation tags and path parameters:
527
-
528
- For a GET operation with tags `["user"]` and path parameter `username`, this generates:
929
+ - title: Keys from tags and path parameters
930
+ body: "Build a key from the operation's first tag plus its path parameters. For a `GET /user/{username}` operation with the `user` tag, this generates:"
529
931
  codeBlock:
530
932
  - lang: typescript
531
933
  code: |-
@@ -533,12 +935,13 @@ options:
533
935
  import { pluginReactQuery } from '@kubb/plugin-react-query'
534
936
 
535
937
  export default defineConfig({
536
- // ...
938
+ input: { path: './petStore.yaml' },
939
+ output: { path: './src/gen' },
537
940
  plugins: [
538
941
  pluginReactQuery({
539
942
  queryKey: ({ operation, schemas }) => {
540
- const tags = operation.getTags().map(tag => JSON.stringify(tag.name))
541
- const pathParams = schemas.pathParams?.keys || []
943
+ const tags = operation.getTags().map((tag) => JSON.stringify(tag.name))
944
+ const pathParams = schemas.pathParams?.keys ?? []
542
945
  return [...tags, ...pathParams]
543
946
  },
544
947
  }),
@@ -546,21 +949,20 @@ options:
546
949
  })
547
950
  - lang: typescript
548
951
  code: |-
549
- export const getUserByNameQueryKey = ({ username }: { username: GetUserByNamePathParams["username"] }) =>
952
+ export const getUserByNameQueryKey = ({ username }: { username: GetUserByNamePathParams['username'] }) =>
550
953
  ['user', username] as const
551
- - title: Using the default transformer
552
- body: |-
553
- You can extend the default queryKey transformer:
554
-
555
- This prepends a version to the default queryKey:
954
+ - title: Extend the default transformer
955
+ body: 'Prepend a version prefix to the default query key:'
556
956
  codeBlock:
557
957
  - lang: typescript
558
958
  code: |-
959
+ import { defineConfig } from 'kubb'
559
960
  import { pluginReactQuery } from '@kubb/plugin-react-query'
560
961
  import { QueryKey } from '@kubb/plugin-react-query/components'
561
962
 
562
963
  export default defineConfig({
563
- // ...
964
+ input: { path: './petStore.yaml' },
965
+ output: { path: './src/gen' },
564
966
  plugins: [
565
967
  pluginReactQuery({
566
968
  queryKey: (props) => {
@@ -574,43 +976,43 @@ options:
574
976
  code: |-
575
977
  export const findPetsByTagsQueryKey = (params?: FindPetsByTagsQueryParams) =>
576
978
  ['v5', { url: '/pet/findByTags' }, ...(params ? [params] : [])] as const
577
- - title: Using operation ID
578
- body: 'Create a simple queryKey using the operation ID:'
979
+ - title: Key from operationId
980
+ body: Use the operationId as the only key. Smallest possible key.
579
981
  codeBlock:
580
982
  lang: typescript
581
983
  code: |-
984
+ import { defineConfig } from 'kubb'
582
985
  import { pluginReactQuery } from '@kubb/plugin-react-query'
583
986
 
584
987
  export default defineConfig({
585
- // ...
988
+ input: { path: './petStore.yaml' },
989
+ output: { path: './src/gen' },
586
990
  plugins: [
587
991
  pluginReactQuery({
588
- queryKey: ({ operation }) => {
589
- return [JSON.stringify(operation.getOperationId())]
590
- },
992
+ queryKey: ({ operation }) => [JSON.stringify(operation.getOperationId())],
591
993
  }),
592
994
  ],
593
995
  })
594
- - title: Conditional keys based on parameters
595
- body: 'Include query parameters when they exist:'
996
+ - title: Conditional keys based on params
997
+ body: 'Include query params in the key only when they are present:'
596
998
  codeBlock:
597
999
  lang: typescript
598
1000
  code: |-
1001
+ import { defineConfig } from 'kubb'
599
1002
  import { pluginReactQuery } from '@kubb/plugin-react-query'
600
1003
 
601
1004
  export default defineConfig({
602
- // ...
1005
+ input: { path: './petStore.yaml' },
1006
+ output: { path: './src/gen' },
603
1007
  plugins: [
604
1008
  pluginReactQuery({
605
1009
  queryKey: ({ operation, schemas }) => {
606
- const keys = [JSON.stringify(operation.getOperationId())]
1010
+ const keys: unknown[] = [JSON.stringify(operation.getOperationId())]
607
1011
 
608
- // Add path parameter values (without quotes, so they reference the variables)
609
1012
  if (schemas.pathParams?.keys) {
610
1013
  keys.push(...schemas.pathParams.keys)
611
1014
  }
612
1015
 
613
- // Add query params conditionally (the string gets embedded as code)
614
1016
  if (schemas.queryParams?.name) {
615
1017
  keys.push('...(params ? [params] : [])')
616
1018
  }
@@ -623,17 +1025,18 @@ options:
623
1025
  - name: suspense
624
1026
  type: object | false
625
1027
  required: false
626
- description: When set, a `suspenseQuery` hook will be added. This will only work for v5 and react.
1028
+ description: |
1029
+ Adds `useSuspenseQuery` hooks alongside the regular `useQuery` ones. Pass an empty object (`{}`) to enable; omit or set to `false` to skip.
1030
+
1031
+ Suspense queries throw promises while loading and require a `<Suspense>` boundary in the React tree. TanStack Query v5+ only.
627
1032
  - name: mutation
628
1033
  type: Mutation
629
1034
  required: false
630
1035
  description: |
631
- Override some `useMutation` behaviors.
632
-
633
- To disable queries pass `false`.
1036
+ Configures mutation hooks. Set to `false` to skip mutation generation entirely.
634
1037
  codeBlock:
635
1038
  lang: typescript
636
- title: Mutation
1039
+ title: Mutation type
637
1040
  code: |
638
1041
  type Mutation = {
639
1042
  methods: Array<HttpMethod>
@@ -644,31 +1047,51 @@ options:
644
1047
  type: Array<HttpMethod>
645
1048
  required: false
646
1049
  default: "['post', 'put', 'delete']"
647
- description: Define which HttpMethods can be used for mutations.
1050
+ description: |
1051
+ HTTP methods treated as mutations. Operations using one of these methods generate a `useMutation`-style hook instead of a query.
1052
+
1053
+ Defaults to `['post', 'put', 'delete']`. Add `'patch'` if your API uses it for partial updates.
1054
+ examples:
1055
+ - name: Include PATCH as a mutation
1056
+ files:
1057
+ - lang: typescript
1058
+ twoslash: false
1059
+ code: |
1060
+ import { defineConfig } from 'kubb'
1061
+ import { pluginReactQuery } from '@kubb/plugin-react-query'
1062
+
1063
+ export default defineConfig({
1064
+ input: { path: './petStore.yaml' },
1065
+ output: { path: './src/gen' },
1066
+ plugins: [
1067
+ pluginReactQuery({
1068
+ mutation: { methods: ['post', 'put', 'patch', 'delete'] },
1069
+ }),
1070
+ ],
1071
+ })
648
1072
  - name: importPath
649
1073
  type: string
650
1074
  required: false
651
1075
  default: "'@tanstack/react-query'"
652
1076
  description: |
653
- Path to the `useMutation` that will be used to do the `useMutation` functionality.
654
- It will be used as `import { useMutation } from '${hook.importPath}'`.
655
- It allows both relative and absolute path. The path will be applied as is, so a relative path should be based on the file being generated.
1077
+ Module specifier used in the `import { useMutation } from '...'` statement at the top of every generated hook file. Useful for routing through your own wrapper.
656
1078
  - name: mutationKey
657
1079
  type: '(props: { operation: Operation; schemas: OperationSchemas }) => unknown[]'
658
1080
  required: false
659
- description: Customize the mutationKey.
1081
+ description: |
1082
+ Builds the `mutationKey` for each mutation hook. Useful when you batch invalidations or read mutation state via `useMutationState`.
660
1083
  warning: |
661
- When using a string you need to use `JSON.stringify`.
1084
+ String values are inlined verbatim into generated code. Wrap literal strings in `JSON.stringify(...)`.
662
1085
  - name: customOptions
663
1086
  type: CustomOptions
664
1087
  required: false
665
1088
  description: |
666
- When set, a custom hook will be used to customize the options of the generated hooks.
1089
+ Wires every generated hook through a user-supplied function that returns extra options (`onSuccess`, `onError`, `select`, ...). The plugin also emits a `HookOptions` type so your wrapper stays in sync with the generated hooks.
667
1090
 
668
- It will also generate a `HookOptions` type that can be used to type the custom options of each hook for type-safety.
1091
+ Use this to centralize cache invalidation, error toasts, or analytics in one place instead of repeating them at every call site.
669
1092
  codeBlock:
670
1093
  lang: typescript
671
- title: CustomOptions
1094
+ title: CustomOptions type
672
1095
  code: |
673
1096
  type CustomOptions = {
674
1097
  importPath: string
@@ -679,140 +1102,284 @@ options:
679
1102
  type: string
680
1103
  required: true
681
1104
  description: |
682
- Path to the hook that will be used to customize the hook options.
683
- It will be used as `import ${customOptions.name} from '${customOptions.importPath}'`.
684
- It allows both relative and absolute paths. However, the path will be applied as is, so relative paths should be based on the file being generated.
1105
+ Module specifier of your custom-options hook. Imported as `import ${name} from '${importPath}'`. Use a relative path from the generated file or a bare specifier.
685
1106
  - name: name
686
1107
  type: string
687
1108
  required: false
688
1109
  default: "'useCustomHookOptions'"
689
1110
  description: |
690
- Name of the exported hook that will be used to customize the hook options.
691
- It will be used as `import ${customOptions.name} from '${customOptions.importPath}'`.
692
- If not provided, it defaults to `useCustomHookOptions`.
1111
+ Exported function name of your custom-options hook. Imported as `import ${name} from '${importPath}'`.
693
1112
  details:
694
- - title: Add custom hook options to invalidate queries
1113
+ - title: Centralised cache invalidation
695
1114
  codeBlock:
696
1115
  lang: typescript
697
- title: useCustomHookOptions.ts
1116
+ title: src/useCustomHookOptions.ts
698
1117
  code: |-
1118
+ import { useQueryClient, type QueryClient } from '@tanstack/react-query'
1119
+ import type { HookOptions } from '../gen/hookOptions'
1120
+ import { getUserByNameQueryKey } from '../gen/hooks/userController/useGetUserByNameHook'
1121
+
699
1122
  function getCustomHookOptions({ queryClient }: { queryClient: QueryClient }): Partial<HookOptions> {
700
1123
  return {
701
1124
  useUpdatePetHook: {
702
1125
  onSuccess: () => {
703
- // Invalidate queries using a constant
704
1126
  void queryClient.invalidateQueries({ queryKey: ['pet'] })
705
1127
  },
706
1128
  },
707
1129
  useDeletePetHook: {
708
- onSuccess: (_data, variables, _onMutateResult, _context) => {
709
- // Invalidate queries using the provided variables
1130
+ onSuccess: (_data, variables) => {
710
1131
  void queryClient.invalidateQueries({ queryKey: ['pet', variables.pet_id] })
711
1132
  },
712
1133
  },
713
1134
  useUpdateUserHook: {
714
- onSuccess: (_data, variables, _onMutateResult, _context) => {
715
- // Invalidate queries using the provided query key generator function
716
- void queryClient.invalidateQueries({ queryKey: getUserByNameQueryKey({ username: variables.username }) })
1135
+ onSuccess: (_data, variables) => {
1136
+ void queryClient.invalidateQueries({
1137
+ queryKey: getUserByNameQueryKey({ username: variables.username }),
1138
+ })
717
1139
  },
718
1140
  },
719
- // Add more custom hook options here...
720
1141
  }
721
1142
  }
722
1143
 
723
- export function useCustomHookOptions<T extends keyof HookOptions>({ hookName, operationId }: { hookName: T; operationId: string }): HookOptions[T] {
1144
+ export function useCustomHookOptions<T extends keyof HookOptions>({
1145
+ hookName,
1146
+ }: {
1147
+ hookName: T
1148
+ operationId: string
1149
+ }): HookOptions[T] {
724
1150
  const queryClient = useQueryClient()
725
1151
  const customOptions = getCustomHookOptions({ queryClient })
726
1152
  return customOptions[hookName] ?? {}
727
1153
  }
728
- - title: Add custom hook options to implement custom error handling
1154
+ - title: App-wide error reporting
729
1155
  codeBlock:
730
1156
  lang: typescript
731
- title: useCustomHookOptions.ts
1157
+ title: src/useCustomHookOptions.ts
732
1158
  code: |-
733
- function getCustomHookOptions({queryClient}: { queryClient: QueryClient }): Partial<HookOptions> {
1159
+ import { toast } from 'sonner'
1160
+ import { useQueryClient, type QueryClient } from '@tanstack/react-query'
1161
+ import type { HookOptions } from '../gen/hookOptions'
1162
+
1163
+ function getCustomHookOptions({ queryClient }: { queryClient: QueryClient }): Partial<HookOptions> {
734
1164
  return {
735
1165
  useUpdatePetHook: {
736
- onError: (error, _variables, _onMutateResult, _context) => {
737
- // Log the error
738
- console.error(`Failed to update pet:`, error);
1166
+ onError: (error) => {
1167
+ console.error('Failed to update pet:', error)
739
1168
  },
740
1169
  },
741
1170
  useDeletePetHook: {
742
- onError: (_error, variables, _onMutateResult, _context) => {
743
- // Show a toast notification
744
- toast.error(`Failed to delete pet with id '${variables.pet_id}'`);
745
- },
746
- },
747
- useUpdateUserHook: {
748
- onError: (_error, variables, _onMutateResult, _context) => {
749
- // Post the error to a custom analytics service
750
- postEvent('user_updated_failed', { username: variables.username, message: error.message, date: Date.now() })
1171
+ onError: (_error, variables) => {
1172
+ toast.error(`Failed to delete pet with id '${variables.pet_id}'`)
751
1173
  },
752
1174
  },
753
- // Add more custom hook options here...
754
1175
  }
755
1176
  }
756
1177
 
757
- export function useCustomHookOptions<T extends keyof HookOptions>({ hookName, operationId }: { hookName: T; operationId: string }): HookOptions[T] {
1178
+ export function useCustomHookOptions<T extends keyof HookOptions>({
1179
+ hookName,
1180
+ }: {
1181
+ hookName: T
1182
+ operationId: string
1183
+ }): HookOptions[T] {
758
1184
  const queryClient = useQueryClient()
759
- const customOptions = getCustomHookOptions({queryClient})
1185
+ const customOptions = getCustomHookOptions({ queryClient })
760
1186
  return customOptions[hookName] ?? {}
761
1187
  }
762
1188
  - name: include
763
1189
  type: Array<Include>
764
1190
  required: false
765
- description: Array containing include parameters to include tags, operations, methods, paths, or content types.
1191
+ description: |
1192
+ Restricts generation to operations that match at least one entry in the list. Anything not matched is skipped.
1193
+
1194
+ Each entry filters by one of:
1195
+
1196
+ - `tag` — the operation's first tag in the OpenAPI spec.
1197
+ - `operationId` — the operation's `operationId`.
1198
+ - `path` — the URL pattern (`'/pet/{petId}'`).
1199
+ - `method` — HTTP method (`'get'`, `'post'`, ...).
1200
+ - `contentType` — the media type of the request body.
1201
+
1202
+ `pattern` accepts either a string (exact match) or a `RegExp` for fuzzy matches.
766
1203
  codeBlock:
767
1204
  lang: typescript
768
- title: Include
1205
+ title: Type definition
769
1206
  code: |
770
1207
  export type Include = {
771
1208
  type: 'tag' | 'operationId' | 'path' | 'method' | 'contentType'
772
1209
  pattern: string | RegExp
773
1210
  }
1211
+ examples:
1212
+ - name: Only the pet tag
1213
+ files:
1214
+ - name: kubb.config.ts
1215
+ lang: typescript
1216
+ twoslash: false
1217
+ code: |
1218
+ import { defineConfig } from 'kubb'
1219
+ import { pluginTs } from '@kubb/plugin-ts'
1220
+
1221
+ export default defineConfig({
1222
+ input: { path: './petStore.yaml' },
1223
+ output: { path: './src/gen' },
1224
+ plugins: [
1225
+ pluginTs({
1226
+ include: [
1227
+ { type: 'tag', pattern: 'pet' },
1228
+ ],
1229
+ }),
1230
+ ],
1231
+ })
1232
+ - name: Only GET operations under /pet
1233
+ files:
1234
+ - name: kubb.config.ts
1235
+ lang: typescript
1236
+ twoslash: false
1237
+ code: |
1238
+ import { defineConfig } from 'kubb'
1239
+ import { pluginTs } from '@kubb/plugin-ts'
1240
+
1241
+ export default defineConfig({
1242
+ input: { path: './petStore.yaml' },
1243
+ output: { path: './src/gen' },
1244
+ plugins: [
1245
+ pluginTs({
1246
+ include: [
1247
+ { type: 'method', pattern: 'get' },
1248
+ { type: 'path', pattern: /^\/pet/ },
1249
+ ],
1250
+ }),
1251
+ ],
1252
+ })
774
1253
  - name: exclude
775
1254
  type: Array<Exclude>
776
1255
  required: false
777
- description: Array containing exclude parameters to exclude or skip tags, operations, methods, paths, or content types.
1256
+ description: |
1257
+ Skips any operation that matches at least one entry in the list. The opposite of `include`.
1258
+
1259
+ Each entry filters by one of:
1260
+
1261
+ - `tag` — the operation's first tag.
1262
+ - `operationId` — the operation's `operationId`.
1263
+ - `path` — the URL pattern (`'/pet/{petId}'`).
1264
+ - `method` — HTTP method (`'get'`, `'post'`, ...).
1265
+ - `contentType` — the media type of the request body.
1266
+
1267
+ `pattern` accepts a plain string or a `RegExp`. When both `include` and `exclude` are set, `exclude` wins.
778
1268
  codeBlock:
779
1269
  lang: typescript
780
- title: Exclude
1270
+ title: Type definition
781
1271
  code: |
782
1272
  export type Exclude = {
783
1273
  type: 'tag' | 'operationId' | 'path' | 'method' | 'contentType'
784
1274
  pattern: string | RegExp
785
1275
  }
1276
+ examples:
1277
+ - name: Skip everything under the store tag
1278
+ files:
1279
+ - name: kubb.config.ts
1280
+ lang: typescript
1281
+ twoslash: false
1282
+ code: |
1283
+ import { defineConfig } from 'kubb'
1284
+ import { pluginTs } from '@kubb/plugin-ts'
1285
+
1286
+ export default defineConfig({
1287
+ input: { path: './petStore.yaml' },
1288
+ output: { path: './src/gen' },
1289
+ plugins: [
1290
+ pluginTs({
1291
+ exclude: [
1292
+ { type: 'tag', pattern: 'store' },
1293
+ ],
1294
+ }),
1295
+ ],
1296
+ })
1297
+ - name: Skip a specific operation and all delete methods
1298
+ files:
1299
+ - name: kubb.config.ts
1300
+ lang: typescript
1301
+ twoslash: false
1302
+ code: |
1303
+ import { defineConfig } from 'kubb'
1304
+ import { pluginTs } from '@kubb/plugin-ts'
1305
+
1306
+ export default defineConfig({
1307
+ input: { path: './petStore.yaml' },
1308
+ output: { path: './src/gen' },
1309
+ plugins: [
1310
+ pluginTs({
1311
+ exclude: [
1312
+ { type: 'operationId', pattern: 'deletePet' },
1313
+ { type: 'method', pattern: 'delete' },
1314
+ ],
1315
+ }),
1316
+ ],
1317
+ })
786
1318
  - name: override
787
1319
  type: Array<Override>
788
1320
  required: false
789
- description: Array containing override parameters to override `options` based on tags, operations, methods, paths, or content types.
1321
+ description: |
1322
+ 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.
1323
+
1324
+ 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.
1325
+
1326
+ Entries are evaluated top to bottom. The first matching entry's `options` is merged onto the plugin defaults; later entries do not stack.
790
1327
  codeBlock:
791
1328
  lang: typescript
792
- title: Override
1329
+ title: Type definition
793
1330
  code: |
794
1331
  export type Override = {
795
1332
  type: 'tag' | 'operationId' | 'path' | 'method' | 'contentType'
796
1333
  pattern: string | RegExp
797
1334
  options: PluginOptions
798
1335
  }
1336
+ examples:
1337
+ - name: Use a different enum style for the user tag
1338
+ files:
1339
+ - name: kubb.config.ts
1340
+ lang: typescript
1341
+ twoslash: false
1342
+ code: |
1343
+ import { defineConfig } from 'kubb'
1344
+ import { pluginTs } from '@kubb/plugin-ts'
1345
+
1346
+ export default defineConfig({
1347
+ input: { path: './petStore.yaml' },
1348
+ output: { path: './src/gen' },
1349
+ plugins: [
1350
+ pluginTs({
1351
+ enumType: 'asConst',
1352
+ override: [
1353
+ {
1354
+ type: 'tag',
1355
+ pattern: 'user',
1356
+ options: { enumType: 'literal' },
1357
+ },
1358
+ ],
1359
+ }),
1360
+ ],
1361
+ })
799
1362
  - name: generators
800
1363
  type: Array<Generator<PluginReactQuery>>
801
1364
  required: false
802
1365
  experimental: true
803
1366
  description: |
804
- Define additional generators next to the built-in generators.
1367
+ 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.
805
1368
 
806
- See [Generators](https://kubb.dev/docs/5.x/guides/creating-plugins) for more information on how to use generators.
1369
+ 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).
1370
+ warning: |
1371
+ Generators are an experimental, low-level API. The signature may change between minor releases.
807
1372
  - name: resolver
808
1373
  type: Partial<ResolverReactQuery> & ThisType<ResolverReactQuery>
809
1374
  required: false
810
1375
  description: |
811
- A single resolver that overrides the naming and path-resolution conventions. Each method you provide replaces the corresponding built-in one. When a method returns `null` or `undefined`, the resolver's result is used as the fallback, so you only need to supply the methods you want to change.
1376
+ Overrides how the plugin builds names and paths for generated files and symbols. Use this to add prefixes, suffixes, or to swap the casing strategy without forking the plugin.
1377
+
1378
+ Only override the methods you want to change. Anything you omit falls back to the plugin's default resolver. A method that returns `null` or `undefined` also falls back.
812
1379
 
813
- `this` inside each method is bound to the **full** resolver, so you can call other resolver methods (e.g. `this.default(name, 'function')`) without losing context.
1380
+ Inside each method, `this` is bound to the full resolver, so you can call `this.default(name, 'function')` to delegate to the built-in implementation.
814
1381
  body: |
815
- Each plugin ships a built-in resolver:
1382
+ Each plugin ships with a default resolver:
816
1383
 
817
1384
  | Plugin | Default resolver |
818
1385
  | --- | --- |
@@ -820,97 +1387,110 @@ options:
820
1387
  | `@kubb/plugin-zod` | `resolverZod` |
821
1388
  | `@kubb/plugin-cypress` | `resolverCypress` |
822
1389
  | `@kubb/plugin-mcp` | `resolverMcp` |
1390
+ | `@kubb/plugin-client` | `resolverClient` |
823
1391
  codeBlock:
824
1392
  lang: typescript
825
- title: Custom resolver (plugin-ts example)
1393
+ title: Add an Api prefix to every name
826
1394
  code: |
1395
+ import { defineConfig } from 'kubb'
827
1396
  import { pluginTs } from '@kubb/plugin-ts'
828
1397
 
829
- pluginTs({
830
- resolver: {
831
- resolveName(name) {
832
- // Prefix every operation-derived name; falls back for names where
833
- // this returns null/undefined.
834
- return `Api${this.default(name, 'function')}`
835
- },
836
- },
1398
+ export default defineConfig({
1399
+ input: { path: './petStore.yaml' },
1400
+ output: { path: './src/gen' },
1401
+ plugins: [
1402
+ pluginTs({
1403
+ resolver: {
1404
+ resolveName(name) {
1405
+ return `Api${this.default(name, 'function')}`
1406
+ },
1407
+ },
1408
+ }),
1409
+ ],
837
1410
  })
838
1411
  tip: |
839
- Use `resolver` for fine-grained control over naming conventions.
1412
+ Use `resolver` for naming and file-location tweaks. For changing the AST nodes themselves (e.g. stripping descriptions), use `transformer` instead.
840
1413
  - name: transformer
841
1414
  type: Visitor
842
1415
  required: false
843
1416
  description: |
844
- 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.
1417
+ Modifies AST nodes before they are printed to source code. Use this when you need to rewrite operation IDs, drop descriptions, or change schema metadata without forking the generator.
845
1418
 
846
- Visitor methods receive the node and a context object. Return a modified node to replace it, or return `undefined`/`void` to leave it unchanged.
1419
+ Each visitor method (e.g. `schema`, `operation`) receives the node and a context object. Return a new node to replace it, or return `undefined` to leave it untouched. Methods you omit keep the plugin's default behavior.
847
1420
  examples:
848
1421
  - name: Strip descriptions before printing
849
1422
  files:
850
- - lang: typescript
1423
+ - name: kubb.config.ts
1424
+ lang: typescript
1425
+ twoslash: false
851
1426
  code: |
1427
+ import { defineConfig } from 'kubb'
852
1428
  import { pluginTs } from '@kubb/plugin-ts'
853
1429
 
854
- pluginTs({
855
- transformer: {
856
- schema(node) {
857
- return { ...node, description: undefined }
858
- },
859
- },
1430
+ export default defineConfig({
1431
+ input: { path: './petStore.yaml' },
1432
+ output: { path: './src/gen' },
1433
+ plugins: [
1434
+ pluginTs({
1435
+ transformer: {
1436
+ schema(node) {
1437
+ return { ...node, description: undefined }
1438
+ },
1439
+ },
1440
+ }),
1441
+ ],
860
1442
  })
861
- twoslash: false
862
1443
  - name: Prefix every operationId
863
1444
  files:
864
- - lang: typescript
1445
+ - name: kubb.config.ts
1446
+ lang: typescript
1447
+ twoslash: false
865
1448
  code: |
1449
+ import { defineConfig } from 'kubb'
866
1450
  import { pluginTs } from '@kubb/plugin-ts'
867
1451
 
868
- pluginTs({
869
- transformer: {
870
- operation(node) {
871
- return { ...node, operationId: `api_${node.operationId}` }
872
- },
873
- },
1452
+ export default defineConfig({
1453
+ input: { path: './petStore.yaml' },
1454
+ output: { path: './src/gen' },
1455
+ plugins: [
1456
+ pluginTs({
1457
+ transformer: {
1458
+ operation(node) {
1459
+ return { ...node, operationId: `api_${node.operationId}` }
1460
+ },
1461
+ },
1462
+ }),
1463
+ ],
874
1464
  })
875
- twoslash: false
876
1465
  tip: |
877
- Use `transformer` to rewrite node properties before printing. For output naming customization, use `resolver` instead.
1466
+ Use `transformer` to rewrite node properties before printing. For changing the names of generated symbols and files, use `resolver` instead.
878
1467
  notes:
879
1468
  - type: tip
880
1469
  body: |
881
- See [Tanstack Query](https://tanstack.com/query) for more information about React Query.
1470
+ Reference: [TanStack Query](https://tanstack.com/query) for cache, retries, and devtools.
882
1471
  examples:
883
1472
  - name: kubb.config.ts
884
1473
  files:
885
1474
  - lang: typescript
1475
+ twoslash: false
886
1476
  code: |
887
1477
  import { defineConfig } from 'kubb'
888
1478
  import { pluginTs } from '@kubb/plugin-ts'
889
1479
  import { pluginReactQuery } from '@kubb/plugin-react-query'
890
1480
 
891
1481
  export default defineConfig({
892
- input: {
893
- path: './petStore.yaml',
894
- },
895
- output: {
896
- path: './src/gen',
897
- },
1482
+ input: { path: './petStore.yaml' },
1483
+ output: { path: './src/gen' },
898
1484
  plugins: [
899
1485
  pluginTs(),
900
1486
  pluginReactQuery({
901
- output: {
902
- path: './hooks',
903
- },
1487
+ output: { path: './hooks' },
904
1488
  group: {
905
1489
  type: 'tag',
906
1490
  name: ({ group }) => `${group}Hooks`,
907
1491
  },
908
- client: {
909
- dataReturnType: 'full',
910
- },
911
- mutation: {
912
- methods: ['post', 'put', 'delete'],
913
- },
1492
+ client: { dataReturnType: 'full' },
1493
+ mutation: { methods: ['post', 'put', 'delete'] },
914
1494
  infinite: {
915
1495
  queryParam: 'next_page',
916
1496
  initialPageParam: 0,
@@ -925,4 +1505,3 @@ examples:
925
1505
  }),
926
1506
  ],
927
1507
  })
928
- twoslash: false