@kubb/plugin-client 5.0.0-beta.3 → 5.0.0-beta.31
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 +24 -4
- package/dist/clients/axios.cjs +25 -3
- package/dist/clients/axios.cjs.map +1 -1
- package/dist/clients/axios.d.ts +9 -2
- package/dist/clients/axios.js +25 -3
- package/dist/clients/axios.js.map +1 -1
- package/dist/clients/fetch.cjs +76 -8
- package/dist/clients/fetch.cjs.map +1 -1
- package/dist/clients/fetch.d.ts +9 -2
- package/dist/clients/fetch.js +76 -8
- package/dist/clients/fetch.js.map +1 -1
- package/dist/index.cjs +627 -353
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +153 -86
- package/dist/index.js +628 -354
- package/dist/index.js.map +1 -1
- package/dist/templates/clients/axios.source.cjs +1 -1
- package/dist/templates/clients/axios.source.js +1 -1
- package/dist/templates/clients/fetch.source.cjs +1 -1
- package/dist/templates/clients/fetch.source.js +1 -1
- package/extension.yaml +1293 -0
- package/package.json +11 -17
- package/src/clients/axios.ts +41 -7
- package/src/clients/fetch.ts +106 -6
- package/src/components/ClassClient.tsx +19 -20
- package/src/components/Client.tsx +74 -53
- package/src/components/Operations.tsx +2 -1
- package/src/components/StaticClassClient.tsx +19 -20
- package/src/components/Url.tsx +8 -9
- package/src/components/WrapperClient.tsx +9 -5
- package/src/functionParams.ts +8 -8
- package/src/generators/classClientGenerator.tsx +51 -47
- package/src/generators/clientGenerator.tsx +37 -48
- package/src/generators/groupedClientGenerator.tsx +14 -8
- package/src/generators/operationsGenerator.tsx +14 -8
- package/src/generators/staticClassClientGenerator.tsx +45 -41
- package/src/plugin.ts +27 -26
- package/src/resolvers/resolverClient.ts +31 -8
- package/src/types.ts +93 -55
- package/src/utils.ts +35 -56
- package/templates/clients/axios.ts +0 -73
- package/templates/clients/fetch.ts +0 -96
- package/templates/config.ts +0 -43
|
@@ -1,27 +1,33 @@
|
|
|
1
|
-
import { defineGenerator } from '@kubb/core'
|
|
2
|
-
import { File,
|
|
1
|
+
import { ast, defineGenerator } from '@kubb/core'
|
|
2
|
+
import { File, jsxRendererSync } from '@kubb/renderer-jsx'
|
|
3
3
|
import { Operations } from '../components/Operations'
|
|
4
4
|
import type { PluginClient } from '../types'
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
* Generates an `operations.ts` file that re-exports every operation grouped
|
|
8
|
+
* by HTTP method. Enabled when `pluginClient({ operations: true })`. Useful
|
|
9
|
+
* for building meta-tooling on top of the generated client (route
|
|
10
|
+
* registries, API explorers).
|
|
11
|
+
*/
|
|
6
12
|
export const operationsGenerator = defineGenerator<PluginClient>({
|
|
7
13
|
name: 'client',
|
|
8
|
-
renderer:
|
|
14
|
+
renderer: jsxRendererSync,
|
|
9
15
|
operations(nodes, ctx) {
|
|
10
|
-
const { config, resolver,
|
|
16
|
+
const { config, resolver, root } = ctx
|
|
11
17
|
const { output, group } = ctx.options
|
|
12
18
|
|
|
13
19
|
const name = 'operations'
|
|
14
|
-
const file = resolver.resolveFile({ name, extname: '.ts' }, { root, output, group })
|
|
20
|
+
const file = resolver.resolveFile({ name, extname: '.ts' }, { root, output, group: group ?? undefined })
|
|
15
21
|
|
|
16
22
|
return (
|
|
17
23
|
<File
|
|
18
24
|
baseName={file.baseName}
|
|
19
25
|
path={file.path}
|
|
20
26
|
meta={file.meta}
|
|
21
|
-
banner={resolver.resolveBanner(
|
|
22
|
-
footer={resolver.resolveFooter(
|
|
27
|
+
banner={resolver.resolveBanner(ctx.meta, { output, config, file: { path: file.path, baseName: file.baseName } })}
|
|
28
|
+
footer={resolver.resolveFooter(ctx.meta, { output, config, file: { path: file.path, baseName: file.baseName } })}
|
|
23
29
|
>
|
|
24
|
-
<Operations name={name} nodes={nodes} />
|
|
30
|
+
<Operations name={name} nodes={nodes.filter(ast.isHttpOperationNode)} />
|
|
25
31
|
</File>
|
|
26
32
|
)
|
|
27
33
|
},
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import path from 'node:path'
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
4
|
-
import { defineGenerator } from '@kubb/core'
|
|
2
|
+
import { operationFileEntry, resolveOperationTypeNames } from '@internals/shared'
|
|
3
|
+
import { camelCase } from '@internals/utils'
|
|
4
|
+
import { ast, defineGenerator } from '@kubb/core'
|
|
5
5
|
import type { ResolverTs } from '@kubb/plugin-ts'
|
|
6
6
|
import { pluginTsName } from '@kubb/plugin-ts'
|
|
7
7
|
import type { ResolverZod } from '@kubb/plugin-zod'
|
|
8
8
|
import { pluginZodName } from '@kubb/plugin-zod'
|
|
9
|
-
import { File,
|
|
9
|
+
import { File, jsxRendererSync } from '@kubb/renderer-jsx'
|
|
10
10
|
import { StaticClassClient } from '../components/StaticClassClient'
|
|
11
11
|
import type { PluginClient } from '../types'
|
|
12
12
|
|
|
@@ -14,9 +14,9 @@ type OperationData = {
|
|
|
14
14
|
node: ast.OperationNode
|
|
15
15
|
name: string
|
|
16
16
|
tsResolver: ResolverTs
|
|
17
|
-
zodResolver: ResolverZod |
|
|
17
|
+
zodResolver: ResolverZod | null
|
|
18
18
|
typeFile: ast.FileNode
|
|
19
|
-
zodFile: ast.FileNode |
|
|
19
|
+
zodFile: ast.FileNode | null
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
type Controller = {
|
|
@@ -26,53 +26,53 @@ type Controller = {
|
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
function resolveTypeImportNames(node: ast.OperationNode, tsResolver: ResolverTs): Array<string> {
|
|
29
|
-
|
|
30
|
-
node.requestBody?.content?.[0]?.schema ? tsResolver.resolveDataName(node) : undefined,
|
|
31
|
-
tsResolver.resolveResponseName(node),
|
|
32
|
-
...node.parameters.filter((p) => p.in === 'path').map((p) => tsResolver.resolvePathParamsName(node, p)),
|
|
33
|
-
...node.parameters.filter((p) => p.in === 'query').map((p) => tsResolver.resolveQueryParamsName(node, p)),
|
|
34
|
-
...node.parameters.filter((p) => p.in === 'header').map((p) => tsResolver.resolveHeaderParamsName(node, p)),
|
|
35
|
-
...node.responses.map((res) => tsResolver.resolveResponseStatusName(node, res.statusCode)),
|
|
36
|
-
]
|
|
37
|
-
return names.filter((n): n is string => Boolean(n))
|
|
29
|
+
return resolveOperationTypeNames(node, tsResolver, { order: 'body-response-first' })
|
|
38
30
|
}
|
|
39
31
|
|
|
40
32
|
function resolveZodImportNames(node: ast.OperationNode, zodResolver: ResolverZod): Array<string> {
|
|
41
|
-
const names: Array<string | undefined> = [
|
|
33
|
+
const names: Array<string | null | undefined> = [
|
|
42
34
|
zodResolver.resolveResponseName?.(node),
|
|
43
|
-
node.requestBody?.content?.[0]?.schema ? zodResolver.resolveDataName?.(node) :
|
|
35
|
+
node.requestBody?.content?.[0]?.schema ? zodResolver.resolveDataName?.(node) : null,
|
|
44
36
|
]
|
|
45
37
|
return names.filter((n): n is string => Boolean(n))
|
|
46
38
|
}
|
|
47
39
|
|
|
40
|
+
/**
|
|
41
|
+
* Built-in `operations` generator for `@kubb/plugin-client` when
|
|
42
|
+
* `clientType: 'staticClass'`. Emits one class per tag, with a static method
|
|
43
|
+
* per operation so callers can use `Pet.getPetById(...)` without
|
|
44
|
+
* instantiating the class.
|
|
45
|
+
*/
|
|
48
46
|
export const staticClassClientGenerator = defineGenerator<PluginClient>({
|
|
49
47
|
name: 'staticClassClient',
|
|
50
|
-
renderer:
|
|
48
|
+
renderer: jsxRendererSync,
|
|
51
49
|
operations(nodes, ctx) {
|
|
52
|
-
const {
|
|
50
|
+
const { config, driver, resolver, root } = ctx
|
|
53
51
|
const { output, group, dataReturnType, paramsCasing, paramsType, pathParamsType, parser, importPath } = ctx.options
|
|
54
|
-
const baseURL = ctx.options.baseURL ??
|
|
52
|
+
const baseURL = ctx.options.baseURL ?? ctx.meta.baseURL
|
|
55
53
|
|
|
56
54
|
const pluginTs = driver.getPlugin(pluginTsName)
|
|
57
55
|
if (!pluginTs) return null
|
|
58
56
|
|
|
59
57
|
const tsResolver = driver.getResolver(pluginTsName)
|
|
60
58
|
const tsPluginOptions = pluginTs.options
|
|
61
|
-
const pluginZod = parser === 'zod' ? driver.getPlugin(pluginZodName) :
|
|
62
|
-
const zodResolver = pluginZod ? driver.getResolver(pluginZodName) :
|
|
59
|
+
const pluginZod = parser === 'zod' ? driver.getPlugin(pluginZodName) : null
|
|
60
|
+
const zodResolver = pluginZod ? driver.getResolver(pluginZodName) : null
|
|
63
61
|
|
|
64
62
|
function buildOperationData(node: ast.OperationNode): OperationData {
|
|
65
|
-
const typeFile = tsResolver.resolveFile(
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
63
|
+
const typeFile = tsResolver.resolveFile(operationFileEntry(node, node.operationId), {
|
|
64
|
+
root,
|
|
65
|
+
output: tsPluginOptions?.output ?? output,
|
|
66
|
+
group: tsPluginOptions?.group,
|
|
67
|
+
})
|
|
69
68
|
const zodFile =
|
|
70
69
|
zodResolver && pluginZod?.options
|
|
71
|
-
? zodResolver.resolveFile(
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
70
|
+
? zodResolver.resolveFile(operationFileEntry(node, node.operationId), {
|
|
71
|
+
root,
|
|
72
|
+
output: pluginZod.options?.output ?? output,
|
|
73
|
+
group: pluginZod.options?.group ?? undefined,
|
|
74
|
+
})
|
|
75
|
+
: null
|
|
76
76
|
|
|
77
77
|
return {
|
|
78
78
|
node: node,
|
|
@@ -85,12 +85,13 @@ export const staticClassClientGenerator = defineGenerator<PluginClient>({
|
|
|
85
85
|
}
|
|
86
86
|
|
|
87
87
|
const controllers = nodes.reduce((acc, operationNode) => {
|
|
88
|
+
if (!ast.isHttpOperationNode(operationNode)) return acc
|
|
88
89
|
const tag = operationNode.tags[0]
|
|
89
|
-
const groupName = tag ? (group?.name?.({ group: camelCase(tag) }) ??
|
|
90
|
+
const groupName = tag ? (group?.name?.({ group: camelCase(tag) }) ?? resolver.resolveGroupName(tag)) : resolver.resolveGroupName('Client')
|
|
90
91
|
|
|
91
92
|
if (!tag && !group) {
|
|
92
|
-
const name = 'ApiClient'
|
|
93
|
-
const file = resolver.resolveFile({ name, extname: '.ts' }, { root, output, group })
|
|
93
|
+
const name = resolver.resolveClassName('ApiClient')
|
|
94
|
+
const file = resolver.resolveFile({ name, extname: '.ts' }, { root, output, group: group ?? undefined })
|
|
94
95
|
const operationData = buildOperationData(operationNode)
|
|
95
96
|
const previous = acc.find((item) => item.file.path === file.path)
|
|
96
97
|
|
|
@@ -99,9 +100,12 @@ export const staticClassClientGenerator = defineGenerator<PluginClient>({
|
|
|
99
100
|
} else {
|
|
100
101
|
acc.push({ name, file, operations: [operationData] })
|
|
101
102
|
}
|
|
102
|
-
|
|
103
|
+
return acc
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (tag) {
|
|
103
107
|
const name = groupName
|
|
104
|
-
const file = resolver.resolveFile({ name, extname: '.ts', tag }, { root, output, group })
|
|
108
|
+
const file = resolver.resolveFile({ name, extname: '.ts', tag }, { root, output, group: group ?? undefined })
|
|
105
109
|
const operationData = buildOperationData(operationNode)
|
|
106
110
|
const previous = acc.find((item) => item.file.path === file.path)
|
|
107
111
|
|
|
@@ -160,7 +164,7 @@ export const staticClassClientGenerator = defineGenerator<PluginClient>({
|
|
|
160
164
|
const { typeImportsByFile, typeFilesByPath } = collectTypeImports(ops)
|
|
161
165
|
const { zodImportsByFile, zodFilesByPath } =
|
|
162
166
|
parser === 'zod' ? collectZodImports(ops) : { zodImportsByFile: new Map<string, Set<string>>(), zodFilesByPath: new Map<string, ast.FileNode>() }
|
|
163
|
-
const hasFormData = ops.some((op) => op.node.requestBody?.content?.
|
|
167
|
+
const hasFormData = ops.some((op) => op.node.requestBody?.content?.some((e) => e.contentType === 'multipart/form-data') ?? false)
|
|
164
168
|
|
|
165
169
|
return (
|
|
166
170
|
<File
|
|
@@ -168,18 +172,18 @@ export const staticClassClientGenerator = defineGenerator<PluginClient>({
|
|
|
168
172
|
baseName={file.baseName}
|
|
169
173
|
path={file.path}
|
|
170
174
|
meta={file.meta}
|
|
171
|
-
banner={resolver.resolveBanner(
|
|
172
|
-
footer={resolver.resolveFooter(
|
|
175
|
+
banner={resolver.resolveBanner(ctx.meta, { output, config, file: { path: file.path, baseName: file.baseName } })}
|
|
176
|
+
footer={resolver.resolveFooter(ctx.meta, { output, config, file: { path: file.path, baseName: file.baseName } })}
|
|
173
177
|
>
|
|
174
178
|
{importPath ? (
|
|
175
179
|
<>
|
|
176
|
-
<File.Import name={'
|
|
180
|
+
<File.Import name={'client'} path={importPath} />
|
|
177
181
|
<File.Import name={['mergeConfig']} path={importPath} />
|
|
178
182
|
<File.Import name={['Client', 'RequestConfig', 'ResponseErrorConfig']} path={importPath} isTypeOnly />
|
|
179
183
|
</>
|
|
180
184
|
) : (
|
|
181
185
|
<>
|
|
182
|
-
<File.Import name={['
|
|
186
|
+
<File.Import name={['client']} root={file.path} path={path.resolve(root, '.kubb/client.ts')} />
|
|
183
187
|
<File.Import name={['mergeConfig']} root={file.path} path={path.resolve(root, '.kubb/client.ts')} />
|
|
184
188
|
<File.Import
|
|
185
189
|
name={['Client', 'RequestConfig', 'ResponseErrorConfig']}
|
package/src/plugin.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import path from 'node:path'
|
|
2
|
-
import {
|
|
2
|
+
import { createGroupConfig } from '@internals/shared'
|
|
3
3
|
|
|
4
|
-
import { ast, definePlugin
|
|
4
|
+
import { ast, definePlugin } from '@kubb/core'
|
|
5
5
|
import { pluginTsName } from '@kubb/plugin-ts'
|
|
6
6
|
import { pluginZodName } from '@kubb/plugin-zod'
|
|
7
7
|
import { classClientGenerator } from './generators/classClientGenerator.tsx'
|
|
@@ -16,20 +16,33 @@ import { source as configSource } from './templates/config.source.ts'
|
|
|
16
16
|
import type { PluginClient } from './types.ts'
|
|
17
17
|
|
|
18
18
|
/**
|
|
19
|
-
* Canonical plugin name for `@kubb/plugin-client
|
|
19
|
+
* Canonical plugin name for `@kubb/plugin-client`. Used for driver lookups and
|
|
20
|
+
* cross-plugin dependency references.
|
|
20
21
|
*/
|
|
21
22
|
export const pluginClientName = 'plugin-client' satisfies PluginClient['name']
|
|
22
23
|
|
|
23
24
|
/**
|
|
24
|
-
* Generates
|
|
25
|
-
*
|
|
26
|
-
*
|
|
25
|
+
* Generates one HTTP client function per OpenAPI operation. Each function has
|
|
26
|
+
* typed path params, query params, body, and response, so callers use the API
|
|
27
|
+
* like any other typed function. Ships with `axios` and `fetch` runtimes; bring
|
|
28
|
+
* your own by setting `importPath`.
|
|
27
29
|
*
|
|
28
|
-
* @example
|
|
30
|
+
* @example
|
|
29
31
|
* ```ts
|
|
30
|
-
* import
|
|
32
|
+
* import { defineConfig } from 'kubb'
|
|
33
|
+
* import { pluginTs } from '@kubb/plugin-ts'
|
|
34
|
+
* import { pluginClient } from '@kubb/plugin-client'
|
|
35
|
+
*
|
|
31
36
|
* export default defineConfig({
|
|
32
|
-
*
|
|
37
|
+
* input: { path: './petStore.yaml' },
|
|
38
|
+
* output: { path: './src/gen' },
|
|
39
|
+
* plugins: [
|
|
40
|
+
* pluginTs(),
|
|
41
|
+
* pluginClient({
|
|
42
|
+
* output: { path: './clients' },
|
|
43
|
+
* client: 'fetch',
|
|
44
|
+
* }),
|
|
45
|
+
* ],
|
|
33
46
|
* })
|
|
34
47
|
* ```
|
|
35
48
|
*/
|
|
@@ -47,7 +60,7 @@ export const pluginClient = definePlugin<PluginClient>((options) => {
|
|
|
47
60
|
operations = false,
|
|
48
61
|
paramsCasing,
|
|
49
62
|
clientType = options.sdk ? 'class' : 'function',
|
|
50
|
-
parser =
|
|
63
|
+
parser = false,
|
|
51
64
|
client = 'axios',
|
|
52
65
|
importPath,
|
|
53
66
|
bundle = false,
|
|
@@ -63,28 +76,16 @@ export const pluginClient = definePlugin<PluginClient>((options) => {
|
|
|
63
76
|
options.generators ??
|
|
64
77
|
[
|
|
65
78
|
clientType === 'staticClass' ? staticClassClientGenerator : clientType === 'class' ? classClientGenerator : clientGenerator,
|
|
66
|
-
group && clientType === 'function' ? groupedClientGenerator :
|
|
67
|
-
operations ? operationsGenerator :
|
|
79
|
+
group && clientType === 'function' ? groupedClientGenerator : null,
|
|
80
|
+
operations ? operationsGenerator : null,
|
|
68
81
|
].filter((x): x is NonNullable<typeof x> => Boolean(x))
|
|
69
82
|
|
|
70
|
-
const groupConfig = group
|
|
71
|
-
? ({
|
|
72
|
-
...group,
|
|
73
|
-
name: group.name
|
|
74
|
-
? group.name
|
|
75
|
-
: (ctx: { group: string }) => {
|
|
76
|
-
if (group.type === 'path') {
|
|
77
|
-
return `${ctx.group.split('/')[1]}`
|
|
78
|
-
}
|
|
79
|
-
return `${camelCase(ctx.group)}Controller`
|
|
80
|
-
},
|
|
81
|
-
} satisfies Group)
|
|
82
|
-
: undefined
|
|
83
|
+
const groupConfig = createGroupConfig(group, { suffix: 'Controller', honorName: true })
|
|
83
84
|
|
|
84
85
|
return {
|
|
85
86
|
name: pluginClientName,
|
|
86
87
|
options,
|
|
87
|
-
dependencies: [pluginTsName, parser === 'zod' ? pluginZodName :
|
|
88
|
+
dependencies: [pluginTsName, parser === 'zod' ? pluginZodName : null].filter((dependency): dependency is string => Boolean(dependency)),
|
|
88
89
|
hooks: {
|
|
89
90
|
'kubb:plugin:setup'(ctx) {
|
|
90
91
|
const resolver = userResolver ? { ...resolverClient, ...userResolver } : resolverClient
|
|
@@ -1,22 +1,45 @@
|
|
|
1
|
-
import { camelCase } from '@internals/utils'
|
|
1
|
+
import { camelCase, ensureValidVarName, pascalCase } from '@internals/utils'
|
|
2
2
|
import { defineResolver } from '@kubb/core'
|
|
3
3
|
import type { PluginClient } from '../types.ts'
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
|
-
*
|
|
6
|
+
* Default resolver used by `@kubb/plugin-client`. Decides the names and file
|
|
7
|
+
* paths for every generated client function or class. Functions and files use
|
|
8
|
+
* camelCase; classes and tag groups use PascalCase.
|
|
7
9
|
*
|
|
8
|
-
*
|
|
10
|
+
* @example Resolve client function and class names
|
|
11
|
+
* ```ts
|
|
12
|
+
* import { resolverClient } from '@kubb/plugin-client'
|
|
9
13
|
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
14
|
+
* resolverClient.default('list pets', 'function') // 'listPets'
|
|
15
|
+
* resolverClient.resolveClassName('pet') // 'Pet'
|
|
16
|
+
* resolverClient.resolveUrlName(operationNode) // 'getShowPetByIdUrl'
|
|
17
|
+
* ```
|
|
12
18
|
*/
|
|
13
|
-
export const resolverClient = defineResolver<PluginClient>((
|
|
19
|
+
export const resolverClient = defineResolver<PluginClient>(() => ({
|
|
14
20
|
name: 'default',
|
|
15
21
|
pluginName: 'plugin-client',
|
|
16
22
|
default(name, type) {
|
|
17
|
-
|
|
23
|
+
const resolved = camelCase(name, { isFile: type === 'file' })
|
|
24
|
+
return type === 'file' ? resolved : ensureValidVarName(resolved)
|
|
18
25
|
},
|
|
19
26
|
resolveName(name) {
|
|
20
|
-
return
|
|
27
|
+
return this.default(name, 'function')
|
|
28
|
+
},
|
|
29
|
+
resolvePathName(name, type) {
|
|
30
|
+
return this.default(name, type)
|
|
31
|
+
},
|
|
32
|
+
resolveClassName(name) {
|
|
33
|
+
return ensureValidVarName(pascalCase(name))
|
|
34
|
+
},
|
|
35
|
+
resolveGroupName(name) {
|
|
36
|
+
return ensureValidVarName(pascalCase(name))
|
|
37
|
+
},
|
|
38
|
+
resolveClientPropertyName(name) {
|
|
39
|
+
return ensureValidVarName(camelCase(name))
|
|
40
|
+
},
|
|
41
|
+
resolveUrlName(node) {
|
|
42
|
+
const name = this.resolveName(node.operationId)
|
|
43
|
+
return `get${name.charAt(0).toUpperCase()}${name.slice(1)}Url`
|
|
21
44
|
},
|
|
22
45
|
}))
|
package/src/types.ts
CHANGED
|
@@ -7,10 +7,34 @@ import type { ast, Exclude, Generator, Group, Include, Output, Override, PluginF
|
|
|
7
7
|
export type ResolverClient = Resolver & {
|
|
8
8
|
/**
|
|
9
9
|
* Resolves the function name for a given raw operation name.
|
|
10
|
+
*
|
|
10
11
|
* @example Resolving operation names
|
|
11
12
|
* `resolver.resolveName('show pet by id') // -> 'showPetById'`
|
|
12
13
|
*/
|
|
13
14
|
resolveName(this: ResolverClient, name: string): string
|
|
15
|
+
/**
|
|
16
|
+
* Resolves the output file name for a client module.
|
|
17
|
+
*/
|
|
18
|
+
resolvePathName(this: ResolverClient, name: string, type?: 'file' | 'function' | 'type' | 'const'): string
|
|
19
|
+
/**
|
|
20
|
+
* Resolves the generated class name for class-based clients.
|
|
21
|
+
*/
|
|
22
|
+
resolveClassName(this: ResolverClient, name: string): string
|
|
23
|
+
/**
|
|
24
|
+
* Resolves the generated class name for tag-based client groups.
|
|
25
|
+
*/
|
|
26
|
+
resolveGroupName(this: ResolverClient, name: string): string
|
|
27
|
+
/**
|
|
28
|
+
* Resolves the generated SDK facade property name for a client class.
|
|
29
|
+
*/
|
|
30
|
+
resolveClientPropertyName(this: ResolverClient, name: string): string
|
|
31
|
+
/**
|
|
32
|
+
* Resolves the URL helper function name for an operation.
|
|
33
|
+
*
|
|
34
|
+
* @example Resolving URL helper names
|
|
35
|
+
* `resolver.resolveUrlName(node) // -> 'getShowPetByIdUrl'`
|
|
36
|
+
*/
|
|
37
|
+
resolveUrlName(this: ResolverClient, node: ast.OperationNode): string
|
|
14
38
|
}
|
|
15
39
|
|
|
16
40
|
/**
|
|
@@ -22,9 +46,10 @@ export type ResolverClient = Resolver & {
|
|
|
22
46
|
export type ClientImportPath =
|
|
23
47
|
| {
|
|
24
48
|
/**
|
|
25
|
-
*
|
|
26
|
-
* - 'axios'
|
|
27
|
-
* - 'fetch'
|
|
49
|
+
* HTTP client used by the generated code.
|
|
50
|
+
* - `'axios'` — imports from `@kubb/plugin-client/clients/axios`. Requires `axios` at runtime.
|
|
51
|
+
* - `'fetch'` — imports from `@kubb/plugin-client/clients/fetch`. Uses the global `fetch`.
|
|
52
|
+
*
|
|
28
53
|
* @default 'axios'
|
|
29
54
|
*/
|
|
30
55
|
client?: 'axios' | 'fetch'
|
|
@@ -33,9 +58,12 @@ export type ClientImportPath =
|
|
|
33
58
|
| {
|
|
34
59
|
client?: never
|
|
35
60
|
/**
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
61
|
+
* Path to a custom client module. Generated files import their HTTP runtime from here
|
|
62
|
+
* instead of `@kubb/plugin-client/clients/{client}`. Accepts both relative paths and
|
|
63
|
+
* bare module specifiers; the value is used as-is.
|
|
64
|
+
*
|
|
65
|
+
* @note When combined with a query plugin, the module must export `Client`,
|
|
66
|
+
* `RequestConfig`, and `ResponseErrorConfig` types.
|
|
39
67
|
*/
|
|
40
68
|
importPath: string
|
|
41
69
|
/**
|
|
@@ -57,29 +85,28 @@ export type ClientImportPath =
|
|
|
57
85
|
type ParamsTypeOptions =
|
|
58
86
|
| {
|
|
59
87
|
/**
|
|
60
|
-
*
|
|
88
|
+
* Every operation parameter (path, query, headers, body) is wrapped in a single
|
|
61
89
|
* destructured object argument.
|
|
62
|
-
* - 'object' returns the params and pathParams as an object.
|
|
63
|
-
* @default 'inline'
|
|
64
90
|
*/
|
|
65
91
|
paramsType: 'object'
|
|
66
92
|
/**
|
|
67
93
|
* `pathParamsType` has no effect when `paramsType` is `'object'`.
|
|
68
|
-
* Path params
|
|
94
|
+
* Path params already live inside the single destructured object.
|
|
69
95
|
*/
|
|
70
96
|
pathParamsType?: never
|
|
71
97
|
}
|
|
72
98
|
| {
|
|
73
99
|
/**
|
|
74
|
-
* Each parameter group is emitted as a separate function argument.
|
|
75
|
-
*
|
|
100
|
+
* Each parameter group is emitted as a separate positional function argument.
|
|
101
|
+
*
|
|
76
102
|
* @default 'inline'
|
|
77
103
|
*/
|
|
78
104
|
paramsType?: 'inline'
|
|
79
105
|
/**
|
|
80
|
-
*
|
|
81
|
-
* - 'object' groups
|
|
82
|
-
* - 'inline' emits each path param as its own argument: `petId: string`.
|
|
106
|
+
* How URL path parameters are arranged inside the inline argument list.
|
|
107
|
+
* - `'object'` groups them into one destructured object: `{ petId }: PathParams`.
|
|
108
|
+
* - `'inline'` emits each path param as its own argument: `petId: string`.
|
|
109
|
+
*
|
|
83
110
|
* @default 'inline'
|
|
84
111
|
*/
|
|
85
112
|
pathParamsType?: 'object' | 'inline'
|
|
@@ -87,87 +114,97 @@ type ParamsTypeOptions =
|
|
|
87
114
|
|
|
88
115
|
export type Options = {
|
|
89
116
|
/**
|
|
90
|
-
*
|
|
91
|
-
*
|
|
117
|
+
* Where the generated client files are written and how they are exported.
|
|
118
|
+
*
|
|
119
|
+
* @default { path: 'clients', barrel: { type: 'named' } }
|
|
92
120
|
*/
|
|
93
121
|
output?: Output
|
|
94
122
|
/**
|
|
95
|
-
*
|
|
123
|
+
* Split generated files into subfolders based on the operation's tag.
|
|
96
124
|
*/
|
|
97
125
|
group?: Group
|
|
98
126
|
/**
|
|
99
|
-
*
|
|
127
|
+
* Skip operations matching at least one entry in the list.
|
|
100
128
|
*/
|
|
101
129
|
exclude?: Array<Exclude>
|
|
102
130
|
/**
|
|
103
|
-
*
|
|
131
|
+
* Restrict generation to operations matching at least one entry in the list.
|
|
104
132
|
*/
|
|
105
133
|
include?: Array<Include>
|
|
106
134
|
/**
|
|
107
|
-
*
|
|
135
|
+
* Apply a different options object to operations matching a pattern.
|
|
108
136
|
*/
|
|
109
137
|
override?: Array<Override<ResolvedOptions>>
|
|
110
138
|
/**
|
|
111
|
-
*
|
|
139
|
+
* Emit an `operations.ts` file that re-exports every generated function grouped by HTTP method.
|
|
140
|
+
*
|
|
112
141
|
* @default false
|
|
113
142
|
*/
|
|
114
143
|
operations?: boolean
|
|
115
144
|
/**
|
|
116
|
-
*
|
|
117
|
-
* - 'export'
|
|
118
|
-
* - false
|
|
145
|
+
* Whether to also export the URL builder helpers (`get<Operation>Url`).
|
|
146
|
+
* - `'export'` exposes them via the barrel.
|
|
147
|
+
* - `false` keeps them private.
|
|
148
|
+
*
|
|
119
149
|
* @default false
|
|
120
|
-
* @example getGetPetByIdUrl
|
|
121
150
|
*/
|
|
122
151
|
urlType?: 'export' | false
|
|
123
152
|
/**
|
|
124
|
-
*
|
|
153
|
+
* Base URL prepended to every request. When omitted, falls back to the adapter's
|
|
154
|
+
* server URL (typically `servers[0].url`).
|
|
125
155
|
*/
|
|
126
156
|
baseURL?: string
|
|
127
157
|
/**
|
|
128
|
-
*
|
|
129
|
-
* - 'data'
|
|
130
|
-
* - 'full'
|
|
158
|
+
* Shape of the value returned by each generated client function.
|
|
159
|
+
* - `'data'` — only the response body.
|
|
160
|
+
* - `'full'` — the full response config (body, status, headers, request).
|
|
161
|
+
*
|
|
131
162
|
* @default 'data'
|
|
132
163
|
*/
|
|
133
164
|
dataReturnType?: 'data' | 'full'
|
|
134
165
|
/**
|
|
135
|
-
*
|
|
136
|
-
*
|
|
137
|
-
*
|
|
166
|
+
* Rename parameter properties in the generated client (path, query, headers).
|
|
167
|
+
* The HTTP request still uses the original spec names; Kubb writes the mapping for you.
|
|
168
|
+
*
|
|
169
|
+
* @note Use the same value on `@kubb/plugin-ts` so types stay compatible.
|
|
138
170
|
*/
|
|
139
171
|
paramsCasing?: 'camelcase'
|
|
140
172
|
/**
|
|
141
|
-
*
|
|
142
|
-
* -
|
|
143
|
-
* -
|
|
144
|
-
*
|
|
173
|
+
* Validator applied to response bodies before they are returned to the caller.
|
|
174
|
+
* - `false` (default) — no validation. The client has no runtime parser; the response is
|
|
175
|
+
* returned as-is, cast to the generated TypeScript type.
|
|
176
|
+
* - `'zod'` — pipes responses through schemas from `@kubb/plugin-zod`.
|
|
177
|
+
*
|
|
178
|
+
* @default false
|
|
145
179
|
*/
|
|
146
|
-
parser?:
|
|
180
|
+
parser?: false | 'zod'
|
|
147
181
|
/**
|
|
148
|
-
*
|
|
149
|
-
* - 'function'
|
|
150
|
-
* - 'class'
|
|
151
|
-
* - 'staticClass'
|
|
182
|
+
* Shape of the generated client.
|
|
183
|
+
* - `'function'` — one standalone async function per operation.
|
|
184
|
+
* - `'class'` — one class per tag with instance methods.
|
|
185
|
+
* - `'staticClass'` — one class per tag with static methods.
|
|
186
|
+
*
|
|
152
187
|
* @default 'function'
|
|
188
|
+
* @note Only `'function'` is compatible with query plugins.
|
|
153
189
|
*/
|
|
154
190
|
clientType?: 'function' | 'class' | 'staticClass'
|
|
155
191
|
/**
|
|
156
|
-
*
|
|
157
|
-
* When
|
|
192
|
+
* Copy the HTTP client runtime into the generated output so consumers do not need
|
|
193
|
+
* `@kubb/plugin-client` at runtime. When `false`, generated files import from
|
|
194
|
+
* `@kubb/plugin-client/clients/{client}`.
|
|
195
|
+
*
|
|
158
196
|
* @default false
|
|
159
|
-
* In version 5 of Kubb this is by default true
|
|
160
197
|
*/
|
|
161
198
|
bundle?: boolean
|
|
162
199
|
/**
|
|
163
|
-
* Generate
|
|
164
|
-
*
|
|
200
|
+
* Generate a single SDK class composing every tag-based client into one entry point.
|
|
201
|
+
* Automatically enables `clientType: 'class'`.
|
|
202
|
+
*
|
|
165
203
|
* @example
|
|
166
204
|
* ```ts
|
|
167
205
|
* pluginClient({
|
|
168
206
|
* sdk: { className: 'PetStoreSDK' },
|
|
169
207
|
* })
|
|
170
|
-
* // Generates a class with a shared constructor config and one property per tag:
|
|
171
208
|
* // class PetStoreSDK {
|
|
172
209
|
* // readonly petController: petController
|
|
173
210
|
* // readonly storeController: storeController
|
|
@@ -177,22 +214,23 @@ export type Options = {
|
|
|
177
214
|
*/
|
|
178
215
|
sdk?: {
|
|
179
216
|
/**
|
|
180
|
-
* Name of the generated SDK facade class.
|
|
217
|
+
* Name of the generated SDK facade class. Also the file name.
|
|
181
218
|
*/
|
|
182
219
|
className: string
|
|
183
220
|
}
|
|
184
221
|
/**
|
|
185
|
-
* Override
|
|
186
|
-
*
|
|
222
|
+
* Override how names and file paths are built for the generated client.
|
|
223
|
+
* Methods you omit fall back to the default resolver. `this` is bound to the
|
|
224
|
+
* full resolver, so `this.default(name)` delegates to the built-in implementation.
|
|
187
225
|
*/
|
|
188
226
|
resolver?: Partial<ResolverClient> & ThisType<ResolverClient>
|
|
189
227
|
/**
|
|
190
|
-
*
|
|
191
|
-
* Return `null` or `undefined`
|
|
228
|
+
* AST visitor applied to each operation node before code is printed.
|
|
229
|
+
* Return `null` or `undefined` to leave the node unchanged.
|
|
192
230
|
*/
|
|
193
231
|
transformer?: ast.Visitor
|
|
194
232
|
/**
|
|
195
|
-
*
|
|
233
|
+
* Custom generators that run alongside the built-in client generators.
|
|
196
234
|
*/
|
|
197
235
|
generators?: Array<Generator<PluginClient>>
|
|
198
236
|
} & ClientImportPath &
|
|
@@ -203,7 +241,7 @@ type ResolvedOptions = {
|
|
|
203
241
|
exclude: Array<Exclude>
|
|
204
242
|
include: Array<Include> | undefined
|
|
205
243
|
override: Array<Override<ResolvedOptions>>
|
|
206
|
-
group: Group |
|
|
244
|
+
group: Group | null
|
|
207
245
|
client: Options['client']
|
|
208
246
|
clientType: NonNullable<Options['clientType']>
|
|
209
247
|
bundle: NonNullable<Options['bundle']>
|