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