@kubb/plugin-react-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.
- package/README.md +38 -91
- package/dist/{components-dAKJEn9b.cjs → components-DQAYLQW0.cjs} +409 -279
- package/dist/components-DQAYLQW0.cjs.map +1 -0
- package/dist/{components-DTGLu4UV.js → components-IArDg-DO.js} +379 -279
- package/dist/components-IArDg-DO.js.map +1 -0
- package/dist/components.cjs +1 -1
- package/dist/components.d.ts +5 -77
- package/dist/components.js +1 -1
- package/dist/{generators-C_fbcjpG.js → generators-B86BJkmW.js} +346 -419
- package/dist/generators-B86BJkmW.js.map +1 -0
- package/dist/{generators-CWEQsdO9.cjs → generators-BqGaMUH6.cjs} +344 -417
- package/dist/generators-BqGaMUH6.cjs.map +1 -0
- package/dist/generators.cjs +1 -1
- package/dist/generators.d.ts +49 -10
- package/dist/generators.js +1 -1
- package/dist/index.cjs +176 -26
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +32 -4
- package/dist/index.js +177 -27
- package/dist/index.js.map +1 -1
- package/dist/types-Dh4HNR9K.d.ts +400 -0
- package/extension.yaml +910 -364
- package/package.json +15 -17
- package/src/components/InfiniteQuery.tsx +24 -13
- package/src/components/InfiniteQueryOptions.tsx +37 -55
- package/src/components/Mutation.tsx +35 -15
- package/src/components/MutationOptions.tsx +14 -13
- package/src/components/Query.tsx +14 -10
- package/src/components/QueryOptions.tsx +17 -34
- package/src/components/SuspenseInfiniteQuery.tsx +19 -13
- package/src/components/SuspenseInfiniteQueryOptions.tsx +28 -52
- package/src/components/SuspenseQuery.tsx +9 -10
- package/src/generators/customHookOptionsFileGenerator.tsx +18 -14
- package/src/generators/hookOptionsGenerator.tsx +44 -51
- package/src/generators/infiniteQueryGenerator.tsx +57 -78
- package/src/generators/mutationGenerator.tsx +53 -64
- package/src/generators/queryGenerator.tsx +54 -63
- package/src/generators/suspenseInfiniteQueryGenerator.tsx +52 -65
- package/src/generators/suspenseQueryGenerator.tsx +56 -76
- package/src/plugin.ts +45 -31
- package/src/resolvers/resolverReactQuery.ts +102 -6
- package/src/types.ts +199 -61
- package/src/utils.ts +10 -33
- package/dist/components-DTGLu4UV.js.map +0 -1
- package/dist/components-dAKJEn9b.cjs.map +0 -1
- package/dist/generators-CWEQsdO9.cjs.map +0 -1
- package/dist/generators-C_fbcjpG.js.map +0 -1
- package/dist/types-DfaFRSBf.d.ts +0 -284
- /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-react-query
|
|
4
4
|
name: React Query
|
|
5
|
-
description: Generate
|
|
5
|
+
description: Generate TanStack Query hooks for React (useQuery, useMutation, useSuspenseQuery, useInfiniteQuery) from OpenAPI.
|
|
6
6
|
category: framework
|
|
7
7
|
type: official
|
|
8
|
-
npmPackage:
|
|
8
|
+
npmPackage: '@kubb/plugin-react-query'
|
|
9
9
|
docsPath: /plugins/plugin-react-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:
|
|
16
|
-
node:
|
|
15
|
+
kubb: '>=5.0.0'
|
|
16
|
+
node: '>=22'
|
|
17
17
|
tags:
|
|
18
18
|
- react-query
|
|
19
19
|
- tanstack-query
|
|
@@ -37,159 +37,399 @@ icon:
|
|
|
37
37
|
intro: |
|
|
38
38
|
# @kubb/plugin-react-query
|
|
39
39
|
|
|
40
|
-
Generate
|
|
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
|
-
default: "{ path: 'hooks',
|
|
46
|
-
description:
|
|
47
|
+
default: "{ path: 'hooks', barrel: { type: 'named' } }"
|
|
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:
|
|
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
|
-
|
|
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:
|
|
56
|
-
type: "
|
|
88
|
+
- name: barrel
|
|
89
|
+
type: "{ type: 'named' | 'all', nested?: boolean } | false"
|
|
57
90
|
required: false
|
|
58
|
-
default: "'named'"
|
|
59
|
-
description:
|
|
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
|
-
|
|
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:
|
|
102
|
+
- name: "'named' (default)"
|
|
64
103
|
files:
|
|
65
|
-
-
|
|
104
|
+
- name: kubb.config.ts
|
|
105
|
+
lang: typescript
|
|
106
|
+
twoslash: false
|
|
66
107
|
code: |
|
|
67
|
-
|
|
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
|
-
|
|
123
|
+
code: |
|
|
124
|
+
export { Pet, PetStatus } from './Pet'
|
|
125
|
+
export { Store } from './Store'
|
|
126
|
+
- name: "'all'"
|
|
70
127
|
files:
|
|
71
|
-
-
|
|
128
|
+
- name: kubb.config.ts
|
|
129
|
+
lang: typescript
|
|
130
|
+
twoslash: false
|
|
72
131
|
code: |
|
|
73
|
-
|
|
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
|
-
|
|
147
|
+
code: |
|
|
148
|
+
export * from './Pet'
|
|
149
|
+
export * from './Store'
|
|
150
|
+
- name: nested
|
|
76
151
|
files:
|
|
77
|
-
-
|
|
78
|
-
|
|
152
|
+
- name: kubb.config.ts
|
|
153
|
+
lang: typescript
|
|
79
154
|
twoslash: false
|
|
80
|
-
|
|
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
|
-
-
|
|
83
|
-
|
|
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:
|
|
205
|
+
type: 'string | ((node: RootNode) => string)'
|
|
87
206
|
required: false
|
|
88
|
-
description:
|
|
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:
|
|
263
|
+
type: 'string | ((node: RootNode) => string)'
|
|
91
264
|
required: false
|
|
92
|
-
description:
|
|
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:
|
|
97
|
-
description:
|
|
98
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
├──
|
|
128
|
-
│
|
|
129
|
-
│
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
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:
|
|
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*`
|
|
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:
|
|
373
|
+
type: '(context: GroupContext) => string'
|
|
149
374
|
required: false
|
|
150
375
|
default: (ctx) => `${ctx.group}Controller`
|
|
151
|
-
description:
|
|
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? }
|
|
154
379
|
required: false
|
|
155
|
-
description:
|
|
380
|
+
description: |
|
|
381
|
+
HTTP client used inside every generated hook. Each generated hook calls into this client to perform the actual request.
|
|
382
|
+
|
|
383
|
+
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).
|
|
156
384
|
properties:
|
|
157
385
|
- name: importPath
|
|
158
386
|
type: string
|
|
159
387
|
required: false
|
|
160
|
-
description:
|
|
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
|
-
|
|
395
|
+
Reach for a custom client when you need to:
|
|
165
396
|
|
|
166
|
-
-
|
|
167
|
-
-
|
|
168
|
-
-
|
|
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
|
-
|
|
403
|
+
Without `importPath`:
|
|
172
404
|
|
|
173
|
-
-
|
|
174
|
-
-
|
|
175
|
-
- title:
|
|
176
|
-
body:
|
|
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:
|
|
410
|
+
|
|
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
|
|
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
|
-
//
|
|
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
|
-
|
|
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:
|
|
470
|
+
- name: Wire up a custom client
|
|
220
471
|
files:
|
|
221
|
-
-
|
|
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',
|
|
484
|
+
importPath: './src/client.ts',
|
|
231
485
|
}),
|
|
232
486
|
],
|
|
233
487
|
})
|
|
234
|
-
twoslash: false
|
|
235
488
|
tip: |
|
|
236
|
-
|
|
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
|
-
|
|
495
|
+
Shape of the value returned from each generated client function.
|
|
243
496
|
|
|
244
|
-
- `'data'` returns `
|
|
245
|
-
- `'full'` returns the full
|
|
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
|
-
-
|
|
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
|
-
|
|
514
|
+
code: |
|
|
515
|
+
const pet = await getPetById(1)
|
|
516
|
+
// ^? Pet
|
|
517
|
+
- name: "'full'"
|
|
258
518
|
files:
|
|
259
|
-
-
|
|
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:
|
|
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:
|
|
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
|
-
|
|
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:
|
|
282
|
-
description:
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
- `false`
|
|
286
|
-
-
|
|
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:
|
|
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
|
-
|
|
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:
|
|
613
|
+
- name: "'inline' (default)"
|
|
299
614
|
files:
|
|
300
|
-
-
|
|
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,141 +644,152 @@ 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
|
-
|
|
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:
|
|
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
|
-
|
|
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
|
-
-
|
|
666
|
+
- name: Generated client
|
|
667
|
+
lang: typescript
|
|
668
|
+
twoslash: false
|
|
339
669
|
code: |
|
|
340
|
-
// Function
|
|
670
|
+
// Function takes camelCase parameters
|
|
341
671
|
export async function deletePet(
|
|
342
|
-
petId: DeletePetPathParams['petId'],
|
|
672
|
+
petId: DeletePetPathParams['petId'],
|
|
343
673
|
headers?: DeletePetHeaderParams,
|
|
344
|
-
config: Partial<RequestConfig> = {}
|
|
674
|
+
config: Partial<RequestConfig> = {},
|
|
345
675
|
) {
|
|
346
|
-
//
|
|
676
|
+
// ...mapped back to the original API name internally
|
|
347
677
|
const pet_id = petId
|
|
348
678
|
|
|
349
|
-
return
|
|
679
|
+
return client({
|
|
350
680
|
method: 'DELETE',
|
|
351
|
-
url: `/pet/${pet_id}`,
|
|
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
|
-
-
|
|
692
|
+
- name: Generated client
|
|
693
|
+
lang: typescript
|
|
694
|
+
twoslash: false
|
|
359
695
|
code: |
|
|
360
|
-
//
|
|
696
|
+
// Function parameters mirror the OpenAPI spec
|
|
361
697
|
export async function deletePet(
|
|
362
|
-
pet_id: DeletePetPathParams['pet_id'],
|
|
698
|
+
pet_id: DeletePetPathParams['pet_id'],
|
|
363
699
|
headers?: DeletePetHeaderParams,
|
|
364
|
-
config: Partial<RequestConfig> = {}
|
|
700
|
+
config: Partial<RequestConfig> = {},
|
|
365
701
|
) {
|
|
366
|
-
return
|
|
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
|
-
|
|
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:
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
- `'inline'`
|
|
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:
|
|
720
|
+
- name: "'inline' (default)"
|
|
385
721
|
files:
|
|
386
722
|
- lang: typescript
|
|
723
|
+
twoslash: false
|
|
387
724
|
code: |
|
|
388
725
|
export async function getPetById(
|
|
389
|
-
|
|
726
|
+
petId: GetPetByIdPathParams,
|
|
390
727
|
) {
|
|
391
|
-
...
|
|
728
|
+
// ...
|
|
392
729
|
}
|
|
393
|
-
|
|
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:
|
|
741
|
+
type: false | 'zod'
|
|
406
742
|
required: false
|
|
407
|
-
default:
|
|
408
|
-
description:
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
- `
|
|
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:
|
|
776
|
+
default: 'false'
|
|
416
777
|
description: |
|
|
417
|
-
|
|
778
|
+
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.
|
|
418
779
|
codeBlock:
|
|
419
780
|
lang: typescript
|
|
420
|
-
title: Infinite
|
|
781
|
+
title: Infinite type
|
|
421
782
|
code: |
|
|
422
783
|
type Infinite = {
|
|
423
|
-
/**
|
|
424
|
-
* Specify the params key used for `pageParam`.
|
|
425
|
-
* @default `'id'`
|
|
426
|
-
*/
|
|
784
|
+
/** Query-param key used as the page cursor. Defaults to `'id'`. */
|
|
427
785
|
queryParam: string
|
|
428
|
-
/**
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
* Supports dot notation (e.g. 'pagination.next.id') or array path (e.g. ['pagination', 'next', 'id']) to access nested fields.
|
|
436
|
-
*/
|
|
437
|
-
nextParam?: string | string[] | undefined
|
|
438
|
-
/**
|
|
439
|
-
* Which field of the data will be used to get the cursor for the previous page.
|
|
440
|
-
* Supports dot notation (e.g. 'pagination.prev.id') or array path (e.g. ['pagination', 'prev', 'id']) to access nested fields.
|
|
441
|
-
*/
|
|
442
|
-
previousParam?: string | string[] | undefined
|
|
443
|
-
/**
|
|
444
|
-
* The initial value, the value of the first page.
|
|
445
|
-
* @default `0`
|
|
446
|
-
*/
|
|
786
|
+
/** @deprecated Use `nextParam` / `previousParam` instead. */
|
|
787
|
+
cursorParam?: string
|
|
788
|
+
/** Path to the next-page cursor in the response. Dot or array form. */
|
|
789
|
+
nextParam?: string | string[]
|
|
790
|
+
/** Path to the previous-page cursor in the response. Dot or array form. */
|
|
791
|
+
previousParam?: string | string[]
|
|
792
|
+
/** Value of `pageParam` for the first page. Defaults to `0`. */
|
|
447
793
|
initialPageParam: unknown
|
|
448
794
|
} | false
|
|
449
795
|
properties:
|
|
@@ -451,42 +797,59 @@ options:
|
|
|
451
797
|
type: string
|
|
452
798
|
required: false
|
|
453
799
|
default: "'id'"
|
|
454
|
-
description:
|
|
800
|
+
description: Name of the query parameter that holds the page cursor (Kubb passes `pageParam` into this query key).
|
|
455
801
|
- name: initialPageParam
|
|
456
802
|
type: unknown
|
|
457
803
|
required: false
|
|
458
|
-
default:
|
|
459
|
-
description:
|
|
804
|
+
default: '0'
|
|
805
|
+
description: Initial value for `pageParam` on the first fetch.
|
|
460
806
|
- name: cursorParam
|
|
461
807
|
type: string | undefined
|
|
462
808
|
required: false
|
|
463
809
|
deprecated:
|
|
464
|
-
note:
|
|
465
|
-
description:
|
|
810
|
+
note: '`cursorParam` is deprecated. Use `nextParam` and `previousParam` for richer pagination control.'
|
|
811
|
+
description: Path to the cursor field on the response. Leave undefined when the cursor is not known.
|
|
466
812
|
- name: nextParam
|
|
467
813
|
type: string | string[] | undefined
|
|
468
814
|
required: false
|
|
469
815
|
description: |
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
Supports dot notation (e.g. `'pagination.next.id'`) or array path (e.g. `['pagination', 'next', 'id']`) to access nested fields.
|
|
816
|
+
Path to the next-page cursor on the response. Supports dot notation (`'pagination.next.id'`) or array form (`['pagination', 'next', 'id']`).
|
|
473
817
|
- name: previousParam
|
|
474
818
|
type: string | string[] | undefined
|
|
475
819
|
required: false
|
|
476
820
|
description: |
|
|
477
|
-
|
|
821
|
+
Path to the previous-page cursor on the response. Supports dot notation (`'pagination.prev.id'`) or array form (`['pagination', 'prev', 'id']`).
|
|
822
|
+
examples:
|
|
823
|
+
- name: Cursor pagination
|
|
824
|
+
files:
|
|
825
|
+
- lang: typescript
|
|
826
|
+
twoslash: false
|
|
827
|
+
code: |
|
|
828
|
+
import { defineConfig } from 'kubb'
|
|
829
|
+
import { pluginReactQuery } from '@kubb/plugin-react-query'
|
|
478
830
|
|
|
479
|
-
|
|
831
|
+
export default defineConfig({
|
|
832
|
+
input: { path: './petStore.yaml' },
|
|
833
|
+
output: { path: './src/gen' },
|
|
834
|
+
plugins: [
|
|
835
|
+
pluginReactQuery({
|
|
836
|
+
infinite: {
|
|
837
|
+
queryParam: 'cursor',
|
|
838
|
+
initialPageParam: null,
|
|
839
|
+
nextParam: 'pagination.next.cursor',
|
|
840
|
+
previousParam: 'pagination.prev.cursor',
|
|
841
|
+
},
|
|
842
|
+
}),
|
|
843
|
+
],
|
|
844
|
+
})
|
|
480
845
|
- name: query
|
|
481
846
|
type: Query
|
|
482
847
|
required: false
|
|
483
848
|
description: |
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
To disable the creation of hooks pass `false`, this will result in only creating `queryOptions`.
|
|
849
|
+
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.
|
|
487
850
|
codeBlock:
|
|
488
851
|
lang: typescript
|
|
489
|
-
title: Query
|
|
852
|
+
title: Query type
|
|
490
853
|
code: |
|
|
491
854
|
type Query = {
|
|
492
855
|
methods: Array<HttpMethod>
|
|
@@ -497,32 +860,49 @@ options:
|
|
|
497
860
|
type: Array<HttpMethod>
|
|
498
861
|
required: false
|
|
499
862
|
default: "['get']"
|
|
500
|
-
description:
|
|
863
|
+
description: |
|
|
864
|
+
HTTP methods treated as queries. Operations using one of these methods generate a `useQuery`-style hook (or `queryOptions` helper) instead of a mutation.
|
|
865
|
+
|
|
866
|
+
Defaults to `['get']`. Add other methods (for example `'head'`) only when your API uses them for cache-friendly reads.
|
|
867
|
+
examples:
|
|
868
|
+
- name: Allow HEAD as a query method
|
|
869
|
+
files:
|
|
870
|
+
- lang: typescript
|
|
871
|
+
twoslash: false
|
|
872
|
+
code: |
|
|
873
|
+
import { defineConfig } from 'kubb'
|
|
874
|
+
import { pluginReactQuery } from '@kubb/plugin-react-query'
|
|
875
|
+
|
|
876
|
+
export default defineConfig({
|
|
877
|
+
input: { path: './petStore.yaml' },
|
|
878
|
+
output: { path: './src/gen' },
|
|
879
|
+
plugins: [
|
|
880
|
+
pluginReactQuery({
|
|
881
|
+
query: { methods: ['get', 'head'] },
|
|
882
|
+
}),
|
|
883
|
+
],
|
|
884
|
+
})
|
|
501
885
|
- name: importPath
|
|
502
886
|
type: string
|
|
503
887
|
required: false
|
|
504
888
|
default: "'@tanstack/react-query'"
|
|
505
889
|
description: |
|
|
506
|
-
|
|
507
|
-
It will be used as `import { useQuery } from '${hook.importPath}'`.
|
|
508
|
-
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.
|
|
890
|
+
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`).
|
|
509
891
|
- name: queryKey
|
|
510
|
-
type:
|
|
892
|
+
type: '(props: { operation: Operation; schemas: OperationSchemas }) => unknown[]'
|
|
511
893
|
required: false
|
|
512
894
|
description: |
|
|
513
|
-
|
|
895
|
+
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.
|
|
896
|
+
|
|
897
|
+
The callback receives:
|
|
514
898
|
|
|
515
|
-
|
|
516
|
-
- `
|
|
517
|
-
- `schemas`: An object containing operation schemas including `pathParams`, `queryParams`, `request`, `response`, etc.
|
|
899
|
+
- `operation` — the OpenAPI operation (`getTags()`, `getOperationId()`, ...).
|
|
900
|
+
- `schemas` — operation schemas including `pathParams`, `queryParams`, `request`, `response`.
|
|
518
901
|
warning: |
|
|
519
|
-
|
|
902
|
+
String values are inlined verbatim into generated code. Wrap any string you want emitted as a literal in `JSON.stringify(...)`.
|
|
520
903
|
details:
|
|
521
|
-
- title:
|
|
522
|
-
body:
|
|
523
|
-
Generate a queryKey with operation tags and path parameters:
|
|
524
|
-
|
|
525
|
-
For a GET operation with tags `["user"]` and path parameter `username`, this generates:
|
|
904
|
+
- title: Keys from tags and path parameters
|
|
905
|
+
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:"
|
|
526
906
|
codeBlock:
|
|
527
907
|
- lang: typescript
|
|
528
908
|
code: |-
|
|
@@ -530,12 +910,13 @@ options:
|
|
|
530
910
|
import { pluginReactQuery } from '@kubb/plugin-react-query'
|
|
531
911
|
|
|
532
912
|
export default defineConfig({
|
|
533
|
-
|
|
913
|
+
input: { path: './petStore.yaml' },
|
|
914
|
+
output: { path: './src/gen' },
|
|
534
915
|
plugins: [
|
|
535
916
|
pluginReactQuery({
|
|
536
917
|
queryKey: ({ operation, schemas }) => {
|
|
537
|
-
const tags = operation.getTags().map(tag => JSON.stringify(tag.name))
|
|
538
|
-
const pathParams = schemas.pathParams?.keys
|
|
918
|
+
const tags = operation.getTags().map((tag) => JSON.stringify(tag.name))
|
|
919
|
+
const pathParams = schemas.pathParams?.keys ?? []
|
|
539
920
|
return [...tags, ...pathParams]
|
|
540
921
|
},
|
|
541
922
|
}),
|
|
@@ -543,21 +924,20 @@ options:
|
|
|
543
924
|
})
|
|
544
925
|
- lang: typescript
|
|
545
926
|
code: |-
|
|
546
|
-
export const getUserByNameQueryKey = ({ username }: { username: GetUserByNamePathParams[
|
|
927
|
+
export const getUserByNameQueryKey = ({ username }: { username: GetUserByNamePathParams['username'] }) =>
|
|
547
928
|
['user', username] as const
|
|
548
|
-
- title:
|
|
549
|
-
body:
|
|
550
|
-
You can extend the default queryKey transformer:
|
|
551
|
-
|
|
552
|
-
This prepends a version to the default queryKey:
|
|
929
|
+
- title: Extend the default transformer
|
|
930
|
+
body: 'Prepend a version prefix to the default query key:'
|
|
553
931
|
codeBlock:
|
|
554
932
|
- lang: typescript
|
|
555
933
|
code: |-
|
|
934
|
+
import { defineConfig } from 'kubb'
|
|
556
935
|
import { pluginReactQuery } from '@kubb/plugin-react-query'
|
|
557
936
|
import { QueryKey } from '@kubb/plugin-react-query/components'
|
|
558
937
|
|
|
559
938
|
export default defineConfig({
|
|
560
|
-
|
|
939
|
+
input: { path: './petStore.yaml' },
|
|
940
|
+
output: { path: './src/gen' },
|
|
561
941
|
plugins: [
|
|
562
942
|
pluginReactQuery({
|
|
563
943
|
queryKey: (props) => {
|
|
@@ -571,43 +951,43 @@ options:
|
|
|
571
951
|
code: |-
|
|
572
952
|
export const findPetsByTagsQueryKey = (params?: FindPetsByTagsQueryParams) =>
|
|
573
953
|
['v5', { url: '/pet/findByTags' }, ...(params ? [params] : [])] as const
|
|
574
|
-
- title:
|
|
575
|
-
body:
|
|
954
|
+
- title: Key from operationId
|
|
955
|
+
body: Use the operationId as the only key. Smallest possible key.
|
|
576
956
|
codeBlock:
|
|
577
957
|
lang: typescript
|
|
578
958
|
code: |-
|
|
959
|
+
import { defineConfig } from 'kubb'
|
|
579
960
|
import { pluginReactQuery } from '@kubb/plugin-react-query'
|
|
580
961
|
|
|
581
962
|
export default defineConfig({
|
|
582
|
-
|
|
963
|
+
input: { path: './petStore.yaml' },
|
|
964
|
+
output: { path: './src/gen' },
|
|
583
965
|
plugins: [
|
|
584
966
|
pluginReactQuery({
|
|
585
|
-
queryKey: ({ operation }) =>
|
|
586
|
-
return [JSON.stringify(operation.getOperationId())]
|
|
587
|
-
},
|
|
967
|
+
queryKey: ({ operation }) => [JSON.stringify(operation.getOperationId())],
|
|
588
968
|
}),
|
|
589
969
|
],
|
|
590
970
|
})
|
|
591
|
-
- title: Conditional keys based on
|
|
592
|
-
body:
|
|
971
|
+
- title: Conditional keys based on params
|
|
972
|
+
body: 'Include query params in the key only when they are present:'
|
|
593
973
|
codeBlock:
|
|
594
974
|
lang: typescript
|
|
595
975
|
code: |-
|
|
976
|
+
import { defineConfig } from 'kubb'
|
|
596
977
|
import { pluginReactQuery } from '@kubb/plugin-react-query'
|
|
597
978
|
|
|
598
979
|
export default defineConfig({
|
|
599
|
-
|
|
980
|
+
input: { path: './petStore.yaml' },
|
|
981
|
+
output: { path: './src/gen' },
|
|
600
982
|
plugins: [
|
|
601
983
|
pluginReactQuery({
|
|
602
984
|
queryKey: ({ operation, schemas }) => {
|
|
603
|
-
const keys = [JSON.stringify(operation.getOperationId())]
|
|
985
|
+
const keys: unknown[] = [JSON.stringify(operation.getOperationId())]
|
|
604
986
|
|
|
605
|
-
// Add path parameter values (without quotes, so they reference the variables)
|
|
606
987
|
if (schemas.pathParams?.keys) {
|
|
607
988
|
keys.push(...schemas.pathParams.keys)
|
|
608
989
|
}
|
|
609
990
|
|
|
610
|
-
// Add query params conditionally (the string gets embedded as code)
|
|
611
991
|
if (schemas.queryParams?.name) {
|
|
612
992
|
keys.push('...(params ? [params] : [])')
|
|
613
993
|
}
|
|
@@ -620,17 +1000,18 @@ options:
|
|
|
620
1000
|
- name: suspense
|
|
621
1001
|
type: object | false
|
|
622
1002
|
required: false
|
|
623
|
-
description:
|
|
1003
|
+
description: |
|
|
1004
|
+
Adds `useSuspenseQuery` hooks alongside the regular `useQuery` ones. Pass an empty object (`{}`) to enable; omit or set to `false` to skip.
|
|
1005
|
+
|
|
1006
|
+
Suspense queries throw promises while loading and require a `<Suspense>` boundary in the React tree. TanStack Query v5+ only.
|
|
624
1007
|
- name: mutation
|
|
625
1008
|
type: Mutation
|
|
626
1009
|
required: false
|
|
627
1010
|
description: |
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
To disable queries pass `false`.
|
|
1011
|
+
Configures mutation hooks. Set to `false` to skip mutation generation entirely.
|
|
631
1012
|
codeBlock:
|
|
632
1013
|
lang: typescript
|
|
633
|
-
title: Mutation
|
|
1014
|
+
title: Mutation type
|
|
634
1015
|
code: |
|
|
635
1016
|
type Mutation = {
|
|
636
1017
|
methods: Array<HttpMethod>
|
|
@@ -640,32 +1021,52 @@ options:
|
|
|
640
1021
|
- name: methods
|
|
641
1022
|
type: Array<HttpMethod>
|
|
642
1023
|
required: false
|
|
643
|
-
default: "['post', 'put', 'delete']"
|
|
644
|
-
description:
|
|
1024
|
+
default: "['post', 'put', 'patch', 'delete']"
|
|
1025
|
+
description: |
|
|
1026
|
+
HTTP methods treated as mutations. Operations using one of these methods generate a `useMutation`-style hook instead of a query.
|
|
1027
|
+
|
|
1028
|
+
Defaults to `['post', 'put', 'patch', 'delete']`. Narrow the list if your API uses one of these methods for reads.
|
|
1029
|
+
examples:
|
|
1030
|
+
- name: Treat only POST and PUT as mutations
|
|
1031
|
+
files:
|
|
1032
|
+
- lang: typescript
|
|
1033
|
+
twoslash: false
|
|
1034
|
+
code: |
|
|
1035
|
+
import { defineConfig } from 'kubb'
|
|
1036
|
+
import { pluginReactQuery } from '@kubb/plugin-react-query'
|
|
1037
|
+
|
|
1038
|
+
export default defineConfig({
|
|
1039
|
+
input: { path: './petStore.yaml' },
|
|
1040
|
+
output: { path: './src/gen' },
|
|
1041
|
+
plugins: [
|
|
1042
|
+
pluginReactQuery({
|
|
1043
|
+
mutation: { methods: ['post', 'put'] },
|
|
1044
|
+
}),
|
|
1045
|
+
],
|
|
1046
|
+
})
|
|
645
1047
|
- name: importPath
|
|
646
1048
|
type: string
|
|
647
1049
|
required: false
|
|
648
1050
|
default: "'@tanstack/react-query'"
|
|
649
1051
|
description: |
|
|
650
|
-
|
|
651
|
-
It will be used as `import { useMutation } from '${hook.importPath}'`.
|
|
652
|
-
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.
|
|
1052
|
+
Module specifier used in the `import { useMutation } from '...'` statement at the top of every generated hook file. Useful for routing through your own wrapper.
|
|
653
1053
|
- name: mutationKey
|
|
654
|
-
type:
|
|
1054
|
+
type: '(props: { operation: Operation; schemas: OperationSchemas }) => unknown[]'
|
|
655
1055
|
required: false
|
|
656
|
-
description:
|
|
1056
|
+
description: |
|
|
1057
|
+
Builds the `mutationKey` for each mutation hook. Useful when you batch invalidations or read mutation state via `useMutationState`.
|
|
657
1058
|
warning: |
|
|
658
|
-
|
|
1059
|
+
String values are inlined verbatim into generated code. Wrap literal strings in `JSON.stringify(...)`.
|
|
659
1060
|
- name: customOptions
|
|
660
1061
|
type: CustomOptions
|
|
661
1062
|
required: false
|
|
662
1063
|
description: |
|
|
663
|
-
|
|
1064
|
+
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.
|
|
664
1065
|
|
|
665
|
-
|
|
1066
|
+
Use this to centralize cache invalidation, error toasts, or analytics in one place instead of repeating them at every call site.
|
|
666
1067
|
codeBlock:
|
|
667
1068
|
lang: typescript
|
|
668
|
-
title: CustomOptions
|
|
1069
|
+
title: CustomOptions type
|
|
669
1070
|
code: |
|
|
670
1071
|
type CustomOptions = {
|
|
671
1072
|
importPath: string
|
|
@@ -676,251 +1077,397 @@ options:
|
|
|
676
1077
|
type: string
|
|
677
1078
|
required: true
|
|
678
1079
|
description: |
|
|
679
|
-
|
|
680
|
-
It will be used as `import ${customOptions.name} from '${customOptions.importPath}'`.
|
|
681
|
-
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.
|
|
1080
|
+
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.
|
|
682
1081
|
- name: name
|
|
683
1082
|
type: string
|
|
684
1083
|
required: false
|
|
685
1084
|
default: "'useCustomHookOptions'"
|
|
686
1085
|
description: |
|
|
687
|
-
|
|
688
|
-
It will be used as `import ${customOptions.name} from '${customOptions.importPath}'`.
|
|
689
|
-
If not provided, it defaults to `useCustomHookOptions`.
|
|
1086
|
+
Exported function name of your custom-options hook. Imported as `import ${name} from '${importPath}'`.
|
|
690
1087
|
details:
|
|
691
|
-
- title:
|
|
1088
|
+
- title: Centralised cache invalidation
|
|
692
1089
|
codeBlock:
|
|
693
1090
|
lang: typescript
|
|
694
|
-
title: useCustomHookOptions.ts
|
|
1091
|
+
title: src/useCustomHookOptions.ts
|
|
695
1092
|
code: |-
|
|
1093
|
+
import { useQueryClient, type QueryClient } from '@tanstack/react-query'
|
|
1094
|
+
import type { HookOptions } from '../gen/hookOptions'
|
|
1095
|
+
import { getUserByNameQueryKey } from '../gen/hooks/userController/useGetUserByNameHook'
|
|
1096
|
+
|
|
696
1097
|
function getCustomHookOptions({ queryClient }: { queryClient: QueryClient }): Partial<HookOptions> {
|
|
697
1098
|
return {
|
|
698
1099
|
useUpdatePetHook: {
|
|
699
1100
|
onSuccess: () => {
|
|
700
|
-
// Invalidate queries using a constant
|
|
701
1101
|
void queryClient.invalidateQueries({ queryKey: ['pet'] })
|
|
702
1102
|
},
|
|
703
1103
|
},
|
|
704
1104
|
useDeletePetHook: {
|
|
705
|
-
onSuccess: (_data, variables
|
|
706
|
-
// Invalidate queries using the provided variables
|
|
1105
|
+
onSuccess: (_data, variables) => {
|
|
707
1106
|
void queryClient.invalidateQueries({ queryKey: ['pet', variables.pet_id] })
|
|
708
1107
|
},
|
|
709
1108
|
},
|
|
710
1109
|
useUpdateUserHook: {
|
|
711
|
-
onSuccess: (_data, variables
|
|
712
|
-
|
|
713
|
-
|
|
1110
|
+
onSuccess: (_data, variables) => {
|
|
1111
|
+
void queryClient.invalidateQueries({
|
|
1112
|
+
queryKey: getUserByNameQueryKey({ username: variables.username }),
|
|
1113
|
+
})
|
|
714
1114
|
},
|
|
715
1115
|
},
|
|
716
|
-
// Add more custom hook options here...
|
|
717
1116
|
}
|
|
718
1117
|
}
|
|
719
1118
|
|
|
720
|
-
export function useCustomHookOptions<T extends keyof HookOptions>({
|
|
1119
|
+
export function useCustomHookOptions<T extends keyof HookOptions>({
|
|
1120
|
+
hookName,
|
|
1121
|
+
}: {
|
|
1122
|
+
hookName: T
|
|
1123
|
+
operationId: string
|
|
1124
|
+
}): HookOptions[T] {
|
|
721
1125
|
const queryClient = useQueryClient()
|
|
722
1126
|
const customOptions = getCustomHookOptions({ queryClient })
|
|
723
1127
|
return customOptions[hookName] ?? {}
|
|
724
1128
|
}
|
|
725
|
-
- title:
|
|
1129
|
+
- title: App-wide error reporting
|
|
726
1130
|
codeBlock:
|
|
727
1131
|
lang: typescript
|
|
728
|
-
title: useCustomHookOptions.ts
|
|
1132
|
+
title: src/useCustomHookOptions.ts
|
|
729
1133
|
code: |-
|
|
730
|
-
|
|
1134
|
+
import { toast } from 'sonner'
|
|
1135
|
+
import { useQueryClient, type QueryClient } from '@tanstack/react-query'
|
|
1136
|
+
import type { HookOptions } from '../gen/hookOptions'
|
|
1137
|
+
|
|
1138
|
+
function getCustomHookOptions({ queryClient }: { queryClient: QueryClient }): Partial<HookOptions> {
|
|
731
1139
|
return {
|
|
732
1140
|
useUpdatePetHook: {
|
|
733
|
-
onError: (error
|
|
734
|
-
|
|
735
|
-
console.error(`Failed to update pet:`, error);
|
|
1141
|
+
onError: (error) => {
|
|
1142
|
+
console.error('Failed to update pet:', error)
|
|
736
1143
|
},
|
|
737
1144
|
},
|
|
738
1145
|
useDeletePetHook: {
|
|
739
|
-
onError: (_error, variables
|
|
740
|
-
|
|
741
|
-
toast.error(`Failed to delete pet with id '${variables.pet_id}'`);
|
|
1146
|
+
onError: (_error, variables) => {
|
|
1147
|
+
toast.error(`Failed to delete pet with id '${variables.pet_id}'`)
|
|
742
1148
|
},
|
|
743
1149
|
},
|
|
744
|
-
useUpdateUserHook: {
|
|
745
|
-
onError: (_error, variables, _onMutateResult, _context) => {
|
|
746
|
-
// Post the error to a custom analytics service
|
|
747
|
-
postEvent('user_updated_failed', { username: variables.username, message: error.message, date: Date.now() })
|
|
748
|
-
},
|
|
749
|
-
},
|
|
750
|
-
// Add more custom hook options here...
|
|
751
1150
|
}
|
|
752
1151
|
}
|
|
753
1152
|
|
|
754
|
-
export function useCustomHookOptions<T extends keyof HookOptions>({
|
|
1153
|
+
export function useCustomHookOptions<T extends keyof HookOptions>({
|
|
1154
|
+
hookName,
|
|
1155
|
+
}: {
|
|
1156
|
+
hookName: T
|
|
1157
|
+
operationId: string
|
|
1158
|
+
}): HookOptions[T] {
|
|
755
1159
|
const queryClient = useQueryClient()
|
|
756
|
-
const customOptions = getCustomHookOptions({queryClient})
|
|
1160
|
+
const customOptions = getCustomHookOptions({ queryClient })
|
|
757
1161
|
return customOptions[hookName] ?? {}
|
|
758
1162
|
}
|
|
759
1163
|
- name: include
|
|
760
1164
|
type: Array<Include>
|
|
761
1165
|
required: false
|
|
762
|
-
description:
|
|
1166
|
+
description: |
|
|
1167
|
+
Restricts generation to operations that match at least one entry in the list. Anything not matched is skipped.
|
|
1168
|
+
|
|
1169
|
+
Each entry filters by one of:
|
|
1170
|
+
|
|
1171
|
+
- `tag` — the operation's first tag in the OpenAPI spec.
|
|
1172
|
+
- `operationId` — the operation's `operationId`.
|
|
1173
|
+
- `path` — the URL pattern (`'/pet/{petId}'`).
|
|
1174
|
+
- `method` — HTTP method (`'get'`, `'post'`, ...).
|
|
1175
|
+
- `contentType` — the media type of the request body.
|
|
1176
|
+
|
|
1177
|
+
`pattern` accepts either a string (exact match) or a `RegExp` for fuzzy matches.
|
|
763
1178
|
codeBlock:
|
|
764
1179
|
lang: typescript
|
|
765
|
-
title:
|
|
1180
|
+
title: Type definition
|
|
766
1181
|
code: |
|
|
767
1182
|
export type Include = {
|
|
768
1183
|
type: 'tag' | 'operationId' | 'path' | 'method' | 'contentType'
|
|
769
1184
|
pattern: string | RegExp
|
|
770
1185
|
}
|
|
1186
|
+
examples:
|
|
1187
|
+
- name: Only the pet tag
|
|
1188
|
+
files:
|
|
1189
|
+
- name: kubb.config.ts
|
|
1190
|
+
lang: typescript
|
|
1191
|
+
twoslash: false
|
|
1192
|
+
code: |
|
|
1193
|
+
import { defineConfig } from 'kubb'
|
|
1194
|
+
import { pluginTs } from '@kubb/plugin-ts'
|
|
1195
|
+
|
|
1196
|
+
export default defineConfig({
|
|
1197
|
+
input: { path: './petStore.yaml' },
|
|
1198
|
+
output: { path: './src/gen' },
|
|
1199
|
+
plugins: [
|
|
1200
|
+
pluginTs({
|
|
1201
|
+
include: [
|
|
1202
|
+
{ type: 'tag', pattern: 'pet' },
|
|
1203
|
+
],
|
|
1204
|
+
}),
|
|
1205
|
+
],
|
|
1206
|
+
})
|
|
1207
|
+
- name: Only GET operations under /pet
|
|
1208
|
+
files:
|
|
1209
|
+
- name: kubb.config.ts
|
|
1210
|
+
lang: typescript
|
|
1211
|
+
twoslash: false
|
|
1212
|
+
code: |
|
|
1213
|
+
import { defineConfig } from 'kubb'
|
|
1214
|
+
import { pluginTs } from '@kubb/plugin-ts'
|
|
1215
|
+
|
|
1216
|
+
export default defineConfig({
|
|
1217
|
+
input: { path: './petStore.yaml' },
|
|
1218
|
+
output: { path: './src/gen' },
|
|
1219
|
+
plugins: [
|
|
1220
|
+
pluginTs({
|
|
1221
|
+
include: [
|
|
1222
|
+
{ type: 'method', pattern: 'get' },
|
|
1223
|
+
{ type: 'path', pattern: /^\/pet/ },
|
|
1224
|
+
],
|
|
1225
|
+
}),
|
|
1226
|
+
],
|
|
1227
|
+
})
|
|
771
1228
|
- name: exclude
|
|
772
1229
|
type: Array<Exclude>
|
|
773
1230
|
required: false
|
|
774
|
-
description:
|
|
1231
|
+
description: |
|
|
1232
|
+
Skips any operation that matches at least one entry in the list. The opposite of `include`.
|
|
1233
|
+
|
|
1234
|
+
Each entry filters by one of:
|
|
1235
|
+
|
|
1236
|
+
- `tag` — the operation's first tag.
|
|
1237
|
+
- `operationId` — the operation's `operationId`.
|
|
1238
|
+
- `path` — the URL pattern (`'/pet/{petId}'`).
|
|
1239
|
+
- `method` — HTTP method (`'get'`, `'post'`, ...).
|
|
1240
|
+
- `contentType` — the media type of the request body.
|
|
1241
|
+
|
|
1242
|
+
`pattern` accepts a plain string or a `RegExp`. When both `include` and `exclude` are set, `exclude` wins.
|
|
775
1243
|
codeBlock:
|
|
776
1244
|
lang: typescript
|
|
777
|
-
title:
|
|
1245
|
+
title: Type definition
|
|
778
1246
|
code: |
|
|
779
1247
|
export type Exclude = {
|
|
780
1248
|
type: 'tag' | 'operationId' | 'path' | 'method' | 'contentType'
|
|
781
1249
|
pattern: string | RegExp
|
|
782
1250
|
}
|
|
1251
|
+
examples:
|
|
1252
|
+
- name: Skip everything under the store tag
|
|
1253
|
+
files:
|
|
1254
|
+
- name: kubb.config.ts
|
|
1255
|
+
lang: typescript
|
|
1256
|
+
twoslash: false
|
|
1257
|
+
code: |
|
|
1258
|
+
import { defineConfig } from 'kubb'
|
|
1259
|
+
import { pluginTs } from '@kubb/plugin-ts'
|
|
1260
|
+
|
|
1261
|
+
export default defineConfig({
|
|
1262
|
+
input: { path: './petStore.yaml' },
|
|
1263
|
+
output: { path: './src/gen' },
|
|
1264
|
+
plugins: [
|
|
1265
|
+
pluginTs({
|
|
1266
|
+
exclude: [
|
|
1267
|
+
{ type: 'tag', pattern: 'store' },
|
|
1268
|
+
],
|
|
1269
|
+
}),
|
|
1270
|
+
],
|
|
1271
|
+
})
|
|
1272
|
+
- name: Skip a specific operation and all delete methods
|
|
1273
|
+
files:
|
|
1274
|
+
- name: kubb.config.ts
|
|
1275
|
+
lang: typescript
|
|
1276
|
+
twoslash: false
|
|
1277
|
+
code: |
|
|
1278
|
+
import { defineConfig } from 'kubb'
|
|
1279
|
+
import { pluginTs } from '@kubb/plugin-ts'
|
|
1280
|
+
|
|
1281
|
+
export default defineConfig({
|
|
1282
|
+
input: { path: './petStore.yaml' },
|
|
1283
|
+
output: { path: './src/gen' },
|
|
1284
|
+
plugins: [
|
|
1285
|
+
pluginTs({
|
|
1286
|
+
exclude: [
|
|
1287
|
+
{ type: 'operationId', pattern: 'deletePet' },
|
|
1288
|
+
{ type: 'method', pattern: 'delete' },
|
|
1289
|
+
],
|
|
1290
|
+
}),
|
|
1291
|
+
],
|
|
1292
|
+
})
|
|
783
1293
|
- name: override
|
|
784
1294
|
type: Array<Override>
|
|
785
1295
|
required: false
|
|
786
|
-
description:
|
|
1296
|
+
description: |
|
|
1297
|
+
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.
|
|
1298
|
+
|
|
1299
|
+
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.
|
|
1300
|
+
|
|
1301
|
+
Entries are evaluated top to bottom. The first matching entry's `options` is merged onto the plugin defaults; later entries do not stack.
|
|
787
1302
|
codeBlock:
|
|
788
1303
|
lang: typescript
|
|
789
|
-
title:
|
|
1304
|
+
title: Type definition
|
|
790
1305
|
code: |
|
|
791
1306
|
export type Override = {
|
|
792
1307
|
type: 'tag' | 'operationId' | 'path' | 'method' | 'contentType'
|
|
793
1308
|
pattern: string | RegExp
|
|
794
1309
|
options: PluginOptions
|
|
795
1310
|
}
|
|
1311
|
+
examples:
|
|
1312
|
+
- name: Use a different enum style for the user tag
|
|
1313
|
+
files:
|
|
1314
|
+
- name: kubb.config.ts
|
|
1315
|
+
lang: typescript
|
|
1316
|
+
twoslash: false
|
|
1317
|
+
code: |
|
|
1318
|
+
import { defineConfig } from 'kubb'
|
|
1319
|
+
import { pluginTs } from '@kubb/plugin-ts'
|
|
1320
|
+
|
|
1321
|
+
export default defineConfig({
|
|
1322
|
+
input: { path: './petStore.yaml' },
|
|
1323
|
+
output: { path: './src/gen' },
|
|
1324
|
+
plugins: [
|
|
1325
|
+
pluginTs({
|
|
1326
|
+
enumType: 'asConst',
|
|
1327
|
+
override: [
|
|
1328
|
+
{
|
|
1329
|
+
type: 'tag',
|
|
1330
|
+
pattern: 'user',
|
|
1331
|
+
options: { enumType: 'literal' },
|
|
1332
|
+
},
|
|
1333
|
+
],
|
|
1334
|
+
}),
|
|
1335
|
+
],
|
|
1336
|
+
})
|
|
796
1337
|
- name: generators
|
|
797
1338
|
type: Array<Generator<PluginReactQuery>>
|
|
798
1339
|
required: false
|
|
799
1340
|
experimental: true
|
|
800
1341
|
description: |
|
|
801
|
-
|
|
1342
|
+
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.
|
|
802
1343
|
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
required: false
|
|
807
|
-
description: Customize the generated names based on the type provided by the plugin.
|
|
808
|
-
properties:
|
|
809
|
-
- name: name
|
|
810
|
-
type: "(name: string, type?: ResolveType) => string"
|
|
811
|
-
required: false
|
|
812
|
-
description: Customize the names based on the type that is provided by the plugin.
|
|
813
|
-
codeBlock:
|
|
814
|
-
lang: typescript
|
|
815
|
-
code: |
|
|
816
|
-
type ResolveType = 'file' | 'function' | 'type' | 'const'
|
|
1344
|
+
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).
|
|
1345
|
+
warning: |
|
|
1346
|
+
Generators are an experimental, low-level API. The signature may change between minor releases.
|
|
817
1347
|
- name: resolver
|
|
818
1348
|
type: Partial<ResolverReactQuery> & ThisType<ResolverReactQuery>
|
|
819
1349
|
required: false
|
|
820
1350
|
description: |
|
|
821
|
-
|
|
1351
|
+
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.
|
|
1352
|
+
|
|
1353
|
+
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.
|
|
822
1354
|
|
|
823
|
-
|
|
1355
|
+
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.
|
|
824
1356
|
body: |
|
|
825
|
-
Each plugin ships a
|
|
1357
|
+
Each plugin ships with a default resolver:
|
|
826
1358
|
|
|
827
1359
|
| Plugin | Default resolver |
|
|
828
1360
|
| --- | --- |
|
|
829
1361
|
| `@kubb/plugin-ts` | `resolverTs` |
|
|
830
1362
|
| `@kubb/plugin-zod` | `resolverZod` |
|
|
1363
|
+
| `@kubb/plugin-faker` | `resolverFaker` |
|
|
831
1364
|
| `@kubb/plugin-cypress` | `resolverCypress` |
|
|
1365
|
+
| `@kubb/plugin-msw` | `resolverMsw` |
|
|
832
1366
|
| `@kubb/plugin-mcp` | `resolverMcp` |
|
|
1367
|
+
| `@kubb/plugin-client` | `resolverClient` |
|
|
833
1368
|
codeBlock:
|
|
834
1369
|
lang: typescript
|
|
835
|
-
title:
|
|
1370
|
+
title: Add an Api prefix to every name
|
|
836
1371
|
code: |
|
|
1372
|
+
import { defineConfig } from 'kubb'
|
|
837
1373
|
import { pluginTs } from '@kubb/plugin-ts'
|
|
838
1374
|
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
1375
|
+
export default defineConfig({
|
|
1376
|
+
input: { path: './petStore.yaml' },
|
|
1377
|
+
output: { path: './src/gen' },
|
|
1378
|
+
plugins: [
|
|
1379
|
+
pluginTs({
|
|
1380
|
+
resolver: {
|
|
1381
|
+
resolveName(name) {
|
|
1382
|
+
return `Api${this.default(name, 'function')}`
|
|
1383
|
+
},
|
|
1384
|
+
},
|
|
1385
|
+
}),
|
|
1386
|
+
],
|
|
847
1387
|
})
|
|
848
1388
|
tip: |
|
|
849
|
-
Use `resolver` for
|
|
1389
|
+
Use `resolver` for naming and file-location tweaks. For changing the AST nodes themselves (e.g. stripping descriptions), use `transformer` instead.
|
|
850
1390
|
- name: transformer
|
|
851
1391
|
type: Visitor
|
|
852
1392
|
required: false
|
|
853
1393
|
description: |
|
|
854
|
-
|
|
1394
|
+
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.
|
|
855
1395
|
|
|
856
|
-
|
|
1396
|
+
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.
|
|
857
1397
|
examples:
|
|
858
1398
|
- name: Strip descriptions before printing
|
|
859
1399
|
files:
|
|
860
|
-
-
|
|
1400
|
+
- name: kubb.config.ts
|
|
1401
|
+
lang: typescript
|
|
1402
|
+
twoslash: false
|
|
861
1403
|
code: |
|
|
1404
|
+
import { defineConfig } from 'kubb'
|
|
862
1405
|
import { pluginTs } from '@kubb/plugin-ts'
|
|
863
1406
|
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
1407
|
+
export default defineConfig({
|
|
1408
|
+
input: { path: './petStore.yaml' },
|
|
1409
|
+
output: { path: './src/gen' },
|
|
1410
|
+
plugins: [
|
|
1411
|
+
pluginTs({
|
|
1412
|
+
transformer: {
|
|
1413
|
+
schema(node) {
|
|
1414
|
+
return { ...node, description: undefined }
|
|
1415
|
+
},
|
|
1416
|
+
},
|
|
1417
|
+
}),
|
|
1418
|
+
],
|
|
870
1419
|
})
|
|
871
|
-
twoslash: false
|
|
872
1420
|
- name: Prefix every operationId
|
|
873
1421
|
files:
|
|
874
|
-
-
|
|
1422
|
+
- name: kubb.config.ts
|
|
1423
|
+
lang: typescript
|
|
1424
|
+
twoslash: false
|
|
875
1425
|
code: |
|
|
1426
|
+
import { defineConfig } from 'kubb'
|
|
876
1427
|
import { pluginTs } from '@kubb/plugin-ts'
|
|
877
1428
|
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
1429
|
+
export default defineConfig({
|
|
1430
|
+
input: { path: './petStore.yaml' },
|
|
1431
|
+
output: { path: './src/gen' },
|
|
1432
|
+
plugins: [
|
|
1433
|
+
pluginTs({
|
|
1434
|
+
transformer: {
|
|
1435
|
+
operation(node) {
|
|
1436
|
+
return { ...node, operationId: `api_${node.operationId}` }
|
|
1437
|
+
},
|
|
1438
|
+
},
|
|
1439
|
+
}),
|
|
1440
|
+
],
|
|
884
1441
|
})
|
|
885
|
-
twoslash: false
|
|
886
1442
|
tip: |
|
|
887
|
-
Use `transformer` to rewrite node properties before printing. For
|
|
1443
|
+
Use `transformer` to rewrite node properties before printing. For changing the names of generated symbols and files, use `resolver` instead.
|
|
888
1444
|
notes:
|
|
889
1445
|
- type: tip
|
|
890
1446
|
body: |
|
|
891
|
-
|
|
1447
|
+
Reference: [TanStack Query](https://tanstack.com/query) for cache, retries, and devtools.
|
|
892
1448
|
examples:
|
|
893
1449
|
- name: kubb.config.ts
|
|
894
1450
|
files:
|
|
895
1451
|
- lang: typescript
|
|
1452
|
+
twoslash: false
|
|
896
1453
|
code: |
|
|
897
1454
|
import { defineConfig } from 'kubb'
|
|
898
1455
|
import { pluginTs } from '@kubb/plugin-ts'
|
|
899
1456
|
import { pluginReactQuery } from '@kubb/plugin-react-query'
|
|
900
1457
|
|
|
901
1458
|
export default defineConfig({
|
|
902
|
-
input: {
|
|
903
|
-
|
|
904
|
-
},
|
|
905
|
-
output: {
|
|
906
|
-
path: './src/gen',
|
|
907
|
-
},
|
|
1459
|
+
input: { path: './petStore.yaml' },
|
|
1460
|
+
output: { path: './src/gen' },
|
|
908
1461
|
plugins: [
|
|
909
1462
|
pluginTs(),
|
|
910
1463
|
pluginReactQuery({
|
|
911
|
-
output: {
|
|
912
|
-
path: './hooks',
|
|
913
|
-
},
|
|
1464
|
+
output: { path: './hooks' },
|
|
914
1465
|
group: {
|
|
915
1466
|
type: 'tag',
|
|
916
1467
|
name: ({ group }) => `${group}Hooks`,
|
|
917
1468
|
},
|
|
918
|
-
client: {
|
|
919
|
-
|
|
920
|
-
},
|
|
921
|
-
mutation: {
|
|
922
|
-
methods: ['post', 'put', 'delete'],
|
|
923
|
-
},
|
|
1469
|
+
client: { dataReturnType: 'full' },
|
|
1470
|
+
mutation: { methods: ['post', 'put', 'delete'] },
|
|
924
1471
|
infinite: {
|
|
925
1472
|
queryParam: 'next_page',
|
|
926
1473
|
initialPageParam: 0,
|
|
@@ -935,4 +1482,3 @@ examples:
|
|
|
935
1482
|
}),
|
|
936
1483
|
],
|
|
937
1484
|
})
|
|
938
|
-
twoslash: false
|