@kubb/plugin-client 5.0.0-alpha.9 → 5.0.0-beta.15
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/LICENSE +17 -10
- package/README.md +27 -7
- package/dist/clients/axios.cjs +10 -3
- package/dist/clients/axios.cjs.map +1 -1
- package/dist/clients/axios.d.ts +5 -4
- package/dist/clients/axios.js +9 -2
- package/dist/clients/axios.js.map +1 -1
- package/dist/clients/fetch.cjs +5 -2
- package/dist/clients/fetch.cjs.map +1 -1
- package/dist/clients/fetch.d.ts +3 -2
- package/dist/clients/fetch.js +5 -2
- package/dist/clients/fetch.js.map +1 -1
- package/dist/index.cjs +1830 -97
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +330 -4
- package/dist/index.js +1816 -95
- 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 +779 -0
- package/package.json +62 -85
- package/src/clients/axios.ts +19 -4
- package/src/clients/fetch.ts +10 -2
- package/src/components/ClassClient.tsx +46 -145
- package/src/components/Client.tsx +109 -139
- package/src/components/Operations.tsx +10 -10
- package/src/components/StaticClassClient.tsx +46 -142
- package/src/components/Url.tsx +38 -50
- package/src/components/WrapperClient.tsx +11 -7
- package/src/functionParams.ts +118 -0
- package/src/generators/classClientGenerator.tsx +143 -172
- package/src/generators/clientGenerator.tsx +83 -81
- package/src/generators/groupedClientGenerator.tsx +50 -52
- package/src/generators/operationsGenerator.tsx +11 -18
- package/src/generators/staticClassClientGenerator.tsx +172 -184
- package/src/index.ts +9 -2
- package/src/plugin.ts +115 -145
- package/src/resolvers/resolverClient.ts +38 -0
- package/src/types.ts +128 -44
- package/src/utils.ts +156 -0
- package/dist/StaticClassClient-By-aMAe4.cjs +0 -677
- package/dist/StaticClassClient-By-aMAe4.cjs.map +0 -1
- package/dist/StaticClassClient-CCn9g9eF.js +0 -636
- package/dist/StaticClassClient-CCn9g9eF.js.map +0 -1
- package/dist/components.cjs +0 -7
- package/dist/components.d.ts +0 -216
- package/dist/components.js +0 -2
- package/dist/generators-BYUJaeZP.js +0 -723
- package/dist/generators-BYUJaeZP.js.map +0 -1
- package/dist/generators-DTxD9FDY.cjs +0 -753
- package/dist/generators-DTxD9FDY.cjs.map +0 -1
- package/dist/generators.cjs +0 -7
- package/dist/generators.d.ts +0 -517
- package/dist/generators.js +0 -2
- package/dist/types-DBQdg-BV.d.ts +0 -169
- package/src/components/index.ts +0 -5
- package/src/generators/index.ts +0 -5
- package/templates/clients/axios.ts +0 -70
- package/templates/clients/fetch.ts +0 -93
- package/templates/config.ts +0 -43
|
@@ -1,133 +1,129 @@
|
|
|
1
1
|
import path from 'node:path'
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import type {
|
|
5
|
-
import
|
|
6
|
-
import type {
|
|
7
|
-
import { createReactGenerator } from '@kubb/plugin-oas/generators'
|
|
8
|
-
import { useOas, useOperationManager } from '@kubb/plugin-oas/hooks'
|
|
9
|
-
import { getBanner, getFooter } from '@kubb/plugin-oas/utils'
|
|
2
|
+
import { resolveOperationTypeNames } from '@internals/shared'
|
|
3
|
+
import { camelCase } from '@internals/utils'
|
|
4
|
+
import type { ast } from '@kubb/core'
|
|
5
|
+
import { defineGenerator } from '@kubb/core'
|
|
6
|
+
import type { ResolverTs } from '@kubb/plugin-ts'
|
|
10
7
|
import { pluginTsName } from '@kubb/plugin-ts'
|
|
8
|
+
import type { ResolverZod } from '@kubb/plugin-zod'
|
|
11
9
|
import { pluginZodName } from '@kubb/plugin-zod'
|
|
12
|
-
import { File } from '@kubb/
|
|
10
|
+
import { File, jsxRendererSync } from '@kubb/renderer-jsx'
|
|
13
11
|
import { ClassClient } from '../components/ClassClient'
|
|
14
12
|
import { WrapperClient } from '../components/WrapperClient'
|
|
15
13
|
import type { PluginClient } from '../types'
|
|
16
14
|
|
|
17
15
|
type OperationData = {
|
|
18
|
-
|
|
16
|
+
node: ast.OperationNode
|
|
19
17
|
name: string
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
typeFile:
|
|
23
|
-
zodFile:
|
|
18
|
+
tsResolver: ResolverTs
|
|
19
|
+
zodResolver: ResolverZod | undefined
|
|
20
|
+
typeFile: ast.FileNode
|
|
21
|
+
zodFile: ast.FileNode | undefined
|
|
24
22
|
}
|
|
25
23
|
|
|
26
24
|
type Controller = {
|
|
27
25
|
name: string
|
|
28
|
-
|
|
26
|
+
propertyName: string
|
|
27
|
+
file: ast.FileNode
|
|
29
28
|
operations: Array<OperationData>
|
|
30
29
|
}
|
|
31
30
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
const { options, name: pluginName } = plugin
|
|
36
|
-
const driver = usePluginDriver()
|
|
37
|
-
|
|
38
|
-
const oas = useOas()
|
|
39
|
-
const { getName, getFile, getGroup, getSchemas } = useOperationManager(generator)
|
|
31
|
+
function resolveTypeImportNames(node: ast.OperationNode, tsResolver: ResolverTs): Array<string> {
|
|
32
|
+
return resolveOperationTypeNames(node, tsResolver, { order: 'body-response-first' })
|
|
33
|
+
}
|
|
40
34
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
35
|
+
function resolveZodImportNames(node: ast.OperationNode, zodResolver: ResolverZod): Array<string> {
|
|
36
|
+
const names: Array<string | undefined> = [
|
|
37
|
+
zodResolver.resolveResponseName?.(node),
|
|
38
|
+
node.requestBody?.content?.[0]?.schema ? zodResolver.resolveDataName?.(node) : undefined,
|
|
39
|
+
]
|
|
40
|
+
return names.filter((n): n is string => Boolean(n))
|
|
41
|
+
}
|
|
46
42
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
43
|
+
export const classClientGenerator = defineGenerator<PluginClient>({
|
|
44
|
+
name: 'classClient',
|
|
45
|
+
renderer: jsxRendererSync,
|
|
46
|
+
operations(nodes, ctx) {
|
|
47
|
+
const { config, driver, resolver, root, inputNode } = ctx
|
|
48
|
+
const { output, group, dataReturnType, paramsCasing, paramsType, pathParamsType, parser, importPath, sdk } = ctx.options
|
|
49
|
+
const baseURL = ctx.options.baseURL ?? inputNode.meta?.baseURL
|
|
50
|
+
|
|
51
|
+
const pluginTs = driver.getPlugin(pluginTsName)
|
|
52
|
+
if (!pluginTs) return null
|
|
53
|
+
|
|
54
|
+
const tsResolver = driver.getResolver(pluginTsName)
|
|
55
|
+
const tsPluginOptions = pluginTs.options
|
|
56
|
+
const pluginZod = parser === 'zod' ? driver.getPlugin(pluginZodName) : undefined
|
|
57
|
+
const zodResolver = pluginZod ? driver.getResolver(pluginZodName) : undefined
|
|
58
|
+
|
|
59
|
+
function buildOperationData(node: ast.OperationNode): OperationData {
|
|
60
|
+
const typeFile = tsResolver.resolveFile(
|
|
61
|
+
{ name: node.operationId, extname: '.ts', tag: node.tags[0] ?? 'default', path: node.path },
|
|
62
|
+
{ root, output: tsPluginOptions?.output ?? output, group: tsPluginOptions?.group },
|
|
63
|
+
)
|
|
64
|
+
const zodFile =
|
|
65
|
+
zodResolver && pluginZod?.options
|
|
66
|
+
? zodResolver.resolveFile(
|
|
67
|
+
{ name: node.operationId, extname: '.ts', tag: node.tags[0] ?? 'default', path: node.path },
|
|
68
|
+
{ root, output: pluginZod.options?.output ?? output, group: pluginZod.options?.group },
|
|
69
|
+
)
|
|
70
|
+
: undefined
|
|
51
71
|
|
|
52
72
|
return {
|
|
53
|
-
|
|
54
|
-
name:
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
typeFile
|
|
58
|
-
zodFile
|
|
73
|
+
node: node,
|
|
74
|
+
name: resolver.resolveName(node.operationId),
|
|
75
|
+
tsResolver,
|
|
76
|
+
zodResolver,
|
|
77
|
+
typeFile,
|
|
78
|
+
zodFile,
|
|
59
79
|
}
|
|
60
80
|
}
|
|
61
81
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
(
|
|
65
|
-
const group = getGroup(operation)
|
|
66
|
-
const groupName = group?.tag ? (options.group?.name?.({ group: camelCase(group.tag) }) ?? pascalCase(group.tag)) : 'Client'
|
|
67
|
-
|
|
68
|
-
if (!group?.tag && !options.group) {
|
|
69
|
-
// If no grouping, put all operations in a single class
|
|
70
|
-
const name = 'ApiClient'
|
|
71
|
-
const file = driver.getFile({
|
|
72
|
-
name,
|
|
73
|
-
extname: '.ts',
|
|
74
|
-
pluginName,
|
|
75
|
-
})
|
|
76
|
-
|
|
77
|
-
const operationData = buildOperationData(operation)
|
|
78
|
-
const previousFile = acc.find((item) => item.file.path === file.path)
|
|
82
|
+
const controllers = nodes.reduce((acc, operationNode) => {
|
|
83
|
+
const tag = operationNode.tags[0]
|
|
84
|
+
const groupName = tag ? (group?.name?.({ group: camelCase(tag) }) ?? resolver.resolveGroupName(tag)) : resolver.resolveGroupName('Client')
|
|
79
85
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
} else if (group?.tag) {
|
|
86
|
-
// Group by tag
|
|
87
|
-
const name = groupName
|
|
88
|
-
const file = driver.getFile({
|
|
89
|
-
name,
|
|
90
|
-
extname: '.ts',
|
|
91
|
-
pluginName,
|
|
92
|
-
options: { group },
|
|
93
|
-
})
|
|
86
|
+
if (!tag && !group) {
|
|
87
|
+
const name = resolver.resolveClassName('ApiClient')
|
|
88
|
+
const file = resolver.resolveFile({ name, extname: '.ts' }, { root, output, group })
|
|
89
|
+
const operationData = buildOperationData(operationNode)
|
|
90
|
+
const previous = acc.find((item) => item.file.path === file.path)
|
|
94
91
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
92
|
+
if (previous) {
|
|
93
|
+
previous.operations.push(operationData)
|
|
94
|
+
} else {
|
|
95
|
+
acc.push({ name, propertyName: resolver.resolveClientPropertyName(name), file, operations: [operationData] })
|
|
96
|
+
}
|
|
97
|
+
} else if (tag) {
|
|
98
|
+
const name = groupName
|
|
99
|
+
const file = resolver.resolveFile({ name, extname: '.ts', tag }, { root, output, group })
|
|
100
|
+
const operationData = buildOperationData(operationNode)
|
|
101
|
+
const previous = acc.find((item) => item.file.path === file.path)
|
|
102
|
+
|
|
103
|
+
if (previous) {
|
|
104
|
+
previous.operations.push(operationData)
|
|
105
|
+
} else {
|
|
106
|
+
acc.push({ name, propertyName: resolver.resolveClientPropertyName(name), file, operations: [operationData] })
|
|
103
107
|
}
|
|
108
|
+
}
|
|
104
109
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
[] as Array<Controller>,
|
|
108
|
-
)
|
|
110
|
+
return acc
|
|
111
|
+
}, [] as Array<Controller>)
|
|
109
112
|
|
|
110
113
|
function collectTypeImports(ops: Array<OperationData>) {
|
|
111
114
|
const typeImportsByFile = new Map<string, Set<string>>()
|
|
112
|
-
const typeFilesByPath = new Map<string,
|
|
115
|
+
const typeFilesByPath = new Map<string, ast.FileNode>()
|
|
113
116
|
|
|
114
117
|
ops.forEach((op) => {
|
|
115
|
-
const
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
typeImportsByFile.set(typeFile.path, new Set())
|
|
118
|
+
const names = resolveTypeImportNames(op.node, tsResolver)
|
|
119
|
+
if (!typeImportsByFile.has(op.typeFile.path)) {
|
|
120
|
+
typeImportsByFile.set(op.typeFile.path, new Set())
|
|
119
121
|
}
|
|
120
|
-
const
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
if (typeSchemas.response?.name) typeImports.add(typeSchemas.response.name)
|
|
124
|
-
if (typeSchemas.pathParams?.name) typeImports.add(typeSchemas.pathParams.name)
|
|
125
|
-
if (typeSchemas.queryParams?.name) typeImports.add(typeSchemas.queryParams.name)
|
|
126
|
-
if (typeSchemas.headerParams?.name) typeImports.add(typeSchemas.headerParams.name)
|
|
127
|
-
typeSchemas.statusCodes?.forEach((item) => {
|
|
128
|
-
if (item?.name) typeImports.add(item.name)
|
|
122
|
+
const imports = typeImportsByFile.get(op.typeFile.path)!
|
|
123
|
+
names.forEach((n) => {
|
|
124
|
+
imports.add(n)
|
|
129
125
|
})
|
|
130
|
-
typeFilesByPath.set(typeFile.path, typeFile)
|
|
126
|
+
typeFilesByPath.set(op.typeFile.path, op.typeFile)
|
|
131
127
|
})
|
|
132
128
|
|
|
133
129
|
return { typeImportsByFile, typeFilesByPath }
|
|
@@ -135,19 +131,19 @@ export const classClientGenerator = createReactGenerator<PluginClient>({
|
|
|
135
131
|
|
|
136
132
|
function collectZodImports(ops: Array<OperationData>) {
|
|
137
133
|
const zodImportsByFile = new Map<string, Set<string>>()
|
|
138
|
-
const zodFilesByPath = new Map<string,
|
|
134
|
+
const zodFilesByPath = new Map<string, ast.FileNode>()
|
|
139
135
|
|
|
140
136
|
ops.forEach((op) => {
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
if (!zodImportsByFile.has(zodFile.path)) {
|
|
144
|
-
zodImportsByFile.set(zodFile.path, new Set())
|
|
137
|
+
if (!op.zodFile || !zodResolver) return
|
|
138
|
+
const names = resolveZodImportNames(op.node, zodResolver)
|
|
139
|
+
if (!zodImportsByFile.has(op.zodFile.path)) {
|
|
140
|
+
zodImportsByFile.set(op.zodFile.path, new Set())
|
|
145
141
|
}
|
|
146
|
-
const
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
zodFilesByPath.set(zodFile.path, zodFile)
|
|
142
|
+
const imports = zodImportsByFile.get(op.zodFile.path)!
|
|
143
|
+
names.forEach((n) => {
|
|
144
|
+
imports.add(n)
|
|
145
|
+
})
|
|
146
|
+
zodFilesByPath.set(op.zodFile.path, op.zodFile)
|
|
151
147
|
})
|
|
152
148
|
|
|
153
149
|
return { zodImportsByFile, zodFilesByPath }
|
|
@@ -156,10 +152,8 @@ export const classClientGenerator = createReactGenerator<PluginClient>({
|
|
|
156
152
|
const files = controllers.map(({ name, file, operations: ops }) => {
|
|
157
153
|
const { typeImportsByFile, typeFilesByPath } = collectTypeImports(ops)
|
|
158
154
|
const { zodImportsByFile, zodFilesByPath } =
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
: { zodImportsByFile: new Map<string, Set<string>>(), zodFilesByPath: new Map<string, KubbFile.File>() }
|
|
162
|
-
const hasFormData = ops.some((op) => op.operation.getContentType() === 'multipart/form-data')
|
|
155
|
+
parser === 'zod' ? collectZodImports(ops) : { zodImportsByFile: new Map<string, Set<string>>(), zodFilesByPath: new Map<string, ast.FileNode>() }
|
|
156
|
+
const hasFormData = ops.some((op) => op.node.requestBody?.content?.some((e) => e.contentType === 'multipart/form-data') ?? false)
|
|
163
157
|
|
|
164
158
|
return (
|
|
165
159
|
<File
|
|
@@ -167,106 +161,83 @@ export const classClientGenerator = createReactGenerator<PluginClient>({
|
|
|
167
161
|
baseName={file.baseName}
|
|
168
162
|
path={file.path}
|
|
169
163
|
meta={file.meta}
|
|
170
|
-
banner={
|
|
171
|
-
footer={
|
|
164
|
+
banner={resolver.resolveBanner(inputNode, { output, config })}
|
|
165
|
+
footer={resolver.resolveFooter(inputNode, { output, config })}
|
|
172
166
|
>
|
|
173
|
-
{
|
|
167
|
+
{importPath ? (
|
|
174
168
|
<>
|
|
175
|
-
<File.Import name={'fetch'} path={
|
|
176
|
-
<File.Import name={['mergeConfig']} path={
|
|
177
|
-
<File.Import name={['Client', 'RequestConfig', 'ResponseErrorConfig']} path={
|
|
169
|
+
<File.Import name={'fetch'} path={importPath} />
|
|
170
|
+
<File.Import name={['mergeConfig']} path={importPath} />
|
|
171
|
+
<File.Import name={['Client', 'RequestConfig', 'ResponseErrorConfig']} path={importPath} isTypeOnly />
|
|
178
172
|
</>
|
|
179
173
|
) : (
|
|
180
174
|
<>
|
|
181
|
-
<File.Import name={['fetch']} root={file.path} path={path.resolve(
|
|
182
|
-
<File.Import name={['mergeConfig']} root={file.path} path={path.resolve(
|
|
183
|
-
<File.Import
|
|
184
|
-
name={['Client', 'RequestConfig', 'ResponseErrorConfig']}
|
|
185
|
-
root={file.path}
|
|
186
|
-
path={path.resolve(config.root, config.output.path, '.kubb/fetch.ts')}
|
|
187
|
-
isTypeOnly
|
|
188
|
-
/>
|
|
175
|
+
<File.Import name={['fetch']} root={file.path} path={path.resolve(root, '.kubb/client.ts')} />
|
|
176
|
+
<File.Import name={['mergeConfig']} root={file.path} path={path.resolve(root, '.kubb/client.ts')} />
|
|
177
|
+
<File.Import name={['Client', 'RequestConfig', 'ResponseErrorConfig']} root={file.path} path={path.resolve(root, '.kubb/client.ts')} isTypeOnly />
|
|
189
178
|
</>
|
|
190
179
|
)}
|
|
191
180
|
|
|
192
|
-
{hasFormData && <File.Import name={['buildFormData']} root={file.path} path={path.resolve(
|
|
181
|
+
{hasFormData && <File.Import name={['buildFormData']} root={file.path} path={path.resolve(root, '.kubb/config.ts')} />}
|
|
193
182
|
|
|
194
|
-
{Array.from(typeImportsByFile.entries()).map(([filePath,
|
|
183
|
+
{Array.from(typeImportsByFile.entries()).map(([filePath, importSet]) => {
|
|
195
184
|
const typeFile = typeFilesByPath.get(filePath)
|
|
196
|
-
if (!typeFile)
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
const importNames = Array.from(imports).filter(Boolean)
|
|
200
|
-
if (importNames.length === 0) {
|
|
201
|
-
return null
|
|
202
|
-
}
|
|
185
|
+
if (!typeFile) return null
|
|
186
|
+
const importNames = Array.from(importSet).filter(Boolean)
|
|
187
|
+
if (importNames.length === 0) return null
|
|
203
188
|
return <File.Import key={filePath} name={importNames} root={file.path} path={typeFile.path} isTypeOnly />
|
|
204
189
|
})}
|
|
205
190
|
|
|
206
|
-
{
|
|
207
|
-
Array.from(zodImportsByFile.entries()).map(([filePath,
|
|
191
|
+
{parser === 'zod' &&
|
|
192
|
+
Array.from(zodImportsByFile.entries()).map(([filePath, importSet]) => {
|
|
208
193
|
const zodFile = zodFilesByPath.get(filePath)
|
|
209
|
-
if (!zodFile)
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
const importNames = Array.from(imports).filter(Boolean)
|
|
213
|
-
if (importNames.length === 0) {
|
|
214
|
-
return null
|
|
215
|
-
}
|
|
216
|
-
|
|
194
|
+
if (!zodFile) return null
|
|
195
|
+
const importNames = Array.from(importSet).filter(Boolean)
|
|
196
|
+
if (importNames.length === 0) return null
|
|
217
197
|
return <File.Import key={filePath} name={importNames} root={file.path} path={zodFile.path} />
|
|
218
198
|
})}
|
|
219
199
|
|
|
220
200
|
<ClassClient
|
|
221
201
|
name={name}
|
|
222
202
|
operations={ops}
|
|
223
|
-
baseURL={
|
|
224
|
-
dataReturnType={
|
|
225
|
-
pathParamsType={
|
|
226
|
-
paramsCasing={
|
|
227
|
-
paramsType={
|
|
228
|
-
parser={
|
|
203
|
+
baseURL={baseURL}
|
|
204
|
+
dataReturnType={dataReturnType}
|
|
205
|
+
pathParamsType={pathParamsType}
|
|
206
|
+
paramsCasing={paramsCasing}
|
|
207
|
+
paramsType={paramsType}
|
|
208
|
+
parser={parser}
|
|
229
209
|
/>
|
|
230
210
|
</File>
|
|
231
211
|
)
|
|
232
212
|
})
|
|
233
213
|
|
|
234
|
-
if (
|
|
235
|
-
const
|
|
236
|
-
name: options.wrapper.className,
|
|
237
|
-
extname: '.ts',
|
|
238
|
-
pluginName,
|
|
239
|
-
})
|
|
214
|
+
if (sdk) {
|
|
215
|
+
const sdkFile = resolver.resolveFile({ name: sdk.className, extname: '.ts' }, { root, output, group })
|
|
240
216
|
|
|
241
217
|
files.push(
|
|
242
218
|
<File
|
|
243
|
-
key={
|
|
244
|
-
baseName={
|
|
245
|
-
path={
|
|
246
|
-
meta={
|
|
247
|
-
banner={
|
|
248
|
-
footer={
|
|
219
|
+
key={sdkFile.path}
|
|
220
|
+
baseName={sdkFile.baseName}
|
|
221
|
+
path={sdkFile.path}
|
|
222
|
+
meta={sdkFile.meta}
|
|
223
|
+
banner={resolver.resolveBanner(inputNode, { output, config })}
|
|
224
|
+
footer={resolver.resolveFooter(inputNode, { output, config })}
|
|
249
225
|
>
|
|
250
|
-
{
|
|
251
|
-
<File.Import name={['Client', 'RequestConfig']} path={
|
|
226
|
+
{importPath ? (
|
|
227
|
+
<File.Import name={['Client', 'RequestConfig']} path={importPath} isTypeOnly />
|
|
252
228
|
) : (
|
|
253
|
-
<File.Import
|
|
254
|
-
name={['Client', 'RequestConfig']}
|
|
255
|
-
root={wrapperFile.path}
|
|
256
|
-
path={path.resolve(config.root, config.output.path, '.kubb/fetch.ts')}
|
|
257
|
-
isTypeOnly
|
|
258
|
-
/>
|
|
229
|
+
<File.Import name={['Client', 'RequestConfig']} root={sdkFile.path} path={path.resolve(root, '.kubb/client.ts')} isTypeOnly />
|
|
259
230
|
)}
|
|
260
231
|
|
|
261
232
|
{controllers.map(({ name, file }) => (
|
|
262
|
-
<File.Import key={name} name={[name]} root={
|
|
233
|
+
<File.Import key={name} name={[name]} root={sdkFile.path} path={file.path} />
|
|
263
234
|
))}
|
|
264
235
|
|
|
265
|
-
<WrapperClient name={
|
|
236
|
+
<WrapperClient name={sdk.className} controllers={controllers.map(({ name, propertyName }) => ({ className: name, propertyName }))} />
|
|
266
237
|
</File>,
|
|
267
238
|
)
|
|
268
239
|
}
|
|
269
240
|
|
|
270
|
-
return files
|
|
241
|
+
return <>{files}</>
|
|
271
242
|
},
|
|
272
243
|
})
|
|
@@ -1,123 +1,125 @@
|
|
|
1
1
|
import path from 'node:path'
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { useOas, useOperationManager } from '@kubb/plugin-oas/hooks'
|
|
5
|
-
import { getBanner, getFooter } from '@kubb/plugin-oas/utils'
|
|
2
|
+
import { resolveOperationTypeNames } from '@internals/shared'
|
|
3
|
+
import { defineGenerator } from '@kubb/core'
|
|
6
4
|
import { pluginTsName } from '@kubb/plugin-ts'
|
|
7
5
|
import { pluginZodName } from '@kubb/plugin-zod'
|
|
8
|
-
import { File } from '@kubb/
|
|
6
|
+
import { File, jsxRendererSync } from '@kubb/renderer-jsx'
|
|
9
7
|
import { Client } from '../components/Client'
|
|
10
8
|
import { Url } from '../components/Url.tsx'
|
|
11
9
|
import type { PluginClient } from '../types'
|
|
12
10
|
|
|
13
|
-
export const clientGenerator =
|
|
11
|
+
export const clientGenerator = defineGenerator<PluginClient>({
|
|
14
12
|
name: 'client',
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
const {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
} = plugin
|
|
13
|
+
renderer: jsxRendererSync,
|
|
14
|
+
operation(node, ctx) {
|
|
15
|
+
const { config, driver, resolver, root, inputNode } = ctx
|
|
16
|
+
const { output, urlType, dataReturnType, paramsCasing, paramsType, pathParamsType, parser, importPath, group } = ctx.options
|
|
17
|
+
const baseURL = ctx.options.baseURL ?? inputNode.meta?.baseURL
|
|
21
18
|
|
|
22
|
-
const
|
|
23
|
-
const { getSchemas, getName, getFile } = useOperationManager(generator)
|
|
19
|
+
const pluginTs = driver.getPlugin(pluginTsName)
|
|
24
20
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
file: getFile(operation),
|
|
21
|
+
if (!pluginTs) {
|
|
22
|
+
return null
|
|
28
23
|
}
|
|
29
24
|
|
|
30
|
-
const
|
|
31
|
-
name: getName(operation, { type: 'function', suffix: 'url', prefix: 'get' }),
|
|
32
|
-
file: getFile(operation),
|
|
33
|
-
}
|
|
25
|
+
const tsResolver = driver.getResolver(pluginTsName)
|
|
34
26
|
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
schemas: getSchemas(operation, { pluginName: pluginTsName, type: 'type' }),
|
|
38
|
-
}
|
|
27
|
+
const pluginZod = parser === 'zod' ? driver.getPlugin(pluginZodName) : undefined
|
|
28
|
+
const zodResolver = pluginZod ? driver.getResolver(pluginZodName) : undefined
|
|
39
29
|
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
30
|
+
const importedTypeNames = resolveOperationTypeNames(node, tsResolver, { paramsCasing })
|
|
31
|
+
|
|
32
|
+
const importedZodNames =
|
|
33
|
+
zodResolver && parser === 'zod'
|
|
34
|
+
? [zodResolver.resolveResponseName?.(node), node.requestBody?.content?.[0]?.schema ? zodResolver.resolveDataName?.(node) : undefined].filter(
|
|
35
|
+
(name): name is string => Boolean(name),
|
|
36
|
+
)
|
|
37
|
+
: []
|
|
44
38
|
|
|
45
|
-
const
|
|
39
|
+
const meta = {
|
|
40
|
+
name: resolver.resolveName(node.operationId),
|
|
41
|
+
urlName: resolver.resolveUrlName(node),
|
|
42
|
+
file: resolver.resolveFile({ name: node.operationId, extname: '.ts', tag: node.tags[0] ?? 'default', path: node.path }, { root, output, group }),
|
|
43
|
+
fileTs: tsResolver.resolveFile(
|
|
44
|
+
{ name: node.operationId, extname: '.ts', tag: node.tags[0] ?? 'default', path: node.path },
|
|
45
|
+
{
|
|
46
|
+
root,
|
|
47
|
+
output: pluginTs.options?.output ?? output,
|
|
48
|
+
group: pluginTs.options?.group,
|
|
49
|
+
},
|
|
50
|
+
),
|
|
51
|
+
fileZod:
|
|
52
|
+
zodResolver && pluginZod?.options
|
|
53
|
+
? zodResolver.resolveFile(
|
|
54
|
+
{ name: node.operationId, extname: '.ts', tag: node.tags[0] ?? 'default', path: node.path },
|
|
55
|
+
{
|
|
56
|
+
root,
|
|
57
|
+
output: pluginZod.options.output ?? output,
|
|
58
|
+
group: pluginZod.options?.group,
|
|
59
|
+
},
|
|
60
|
+
)
|
|
61
|
+
: undefined,
|
|
62
|
+
} as const
|
|
63
|
+
|
|
64
|
+
const hasFormData = node.requestBody?.content?.some((e) => e.contentType === 'multipart/form-data') ?? false
|
|
46
65
|
|
|
47
66
|
return (
|
|
48
67
|
<File
|
|
49
|
-
baseName={
|
|
50
|
-
path={
|
|
51
|
-
meta={
|
|
52
|
-
banner={
|
|
53
|
-
footer={
|
|
68
|
+
baseName={meta.file.baseName}
|
|
69
|
+
path={meta.file.path}
|
|
70
|
+
meta={meta.file.meta}
|
|
71
|
+
banner={resolver.resolveBanner(inputNode, { output, config })}
|
|
72
|
+
footer={resolver.resolveFooter(inputNode, { output, config })}
|
|
54
73
|
>
|
|
55
|
-
{
|
|
74
|
+
{importPath ? (
|
|
56
75
|
<>
|
|
57
|
-
<File.Import name={'fetch'} path={
|
|
58
|
-
<File.Import name={['Client', 'RequestConfig', 'ResponseErrorConfig']} path={
|
|
76
|
+
<File.Import name={'fetch'} path={importPath} />
|
|
77
|
+
<File.Import name={['Client', 'RequestConfig', 'ResponseErrorConfig']} path={importPath} isTypeOnly />
|
|
59
78
|
</>
|
|
60
79
|
) : (
|
|
61
80
|
<>
|
|
62
|
-
<File.Import name={['fetch']} root={
|
|
81
|
+
<File.Import name={['fetch']} root={meta.file.path} path={path.resolve(root, '.kubb/client.ts')} />
|
|
63
82
|
<File.Import
|
|
64
83
|
name={['Client', 'RequestConfig', 'ResponseErrorConfig']}
|
|
65
|
-
root={
|
|
66
|
-
path={path.resolve(
|
|
84
|
+
root={meta.file.path}
|
|
85
|
+
path={path.resolve(root, '.kubb/client.ts')}
|
|
67
86
|
isTypeOnly
|
|
68
87
|
/>
|
|
69
88
|
</>
|
|
70
89
|
)}
|
|
71
90
|
|
|
72
|
-
{
|
|
73
|
-
<File.Import name={['buildFormData']} root={client.file.path} path={path.resolve(config.root, config.output.path, '.kubb/config.ts')} />
|
|
74
|
-
)}
|
|
91
|
+
{hasFormData && <File.Import name={['buildFormData']} root={meta.file.path} path={path.resolve(root, '.kubb/config.ts')} />}
|
|
75
92
|
|
|
76
|
-
{
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
path={zod.file.path}
|
|
81
|
-
/>
|
|
93
|
+
{meta.fileZod && importedZodNames.length > 0 && <File.Import name={importedZodNames as string[]} root={meta.file.path} path={meta.fileZod.path} />}
|
|
94
|
+
|
|
95
|
+
{meta.fileTs && importedTypeNames.length > 0 && (
|
|
96
|
+
<File.Import name={Array.from(new Set(importedTypeNames))} root={meta.file.path} path={meta.fileTs.path} isTypeOnly />
|
|
82
97
|
)}
|
|
83
|
-
<File.Import
|
|
84
|
-
name={[
|
|
85
|
-
type.schemas.request?.name,
|
|
86
|
-
type.schemas.response.name,
|
|
87
|
-
type.schemas.pathParams?.name,
|
|
88
|
-
type.schemas.queryParams?.name,
|
|
89
|
-
type.schemas.headerParams?.name,
|
|
90
|
-
...(type.schemas.statusCodes?.map((item) => item.name) || []),
|
|
91
|
-
].filter((x): x is string => Boolean(x))}
|
|
92
|
-
root={client.file.path}
|
|
93
|
-
path={type.file.path}
|
|
94
|
-
isTypeOnly
|
|
95
|
-
/>
|
|
96
98
|
|
|
97
99
|
<Url
|
|
98
|
-
name={
|
|
99
|
-
baseURL={
|
|
100
|
-
pathParamsType={
|
|
101
|
-
paramsCasing={
|
|
102
|
-
paramsType={
|
|
103
|
-
|
|
104
|
-
|
|
100
|
+
name={meta.urlName}
|
|
101
|
+
baseURL={baseURL}
|
|
102
|
+
pathParamsType={pathParamsType}
|
|
103
|
+
paramsCasing={paramsCasing}
|
|
104
|
+
paramsType={paramsType}
|
|
105
|
+
node={node}
|
|
106
|
+
tsResolver={tsResolver}
|
|
105
107
|
isIndexable={urlType === 'export'}
|
|
106
108
|
isExportable={urlType === 'export'}
|
|
107
109
|
/>
|
|
108
110
|
|
|
109
111
|
<Client
|
|
110
|
-
name={
|
|
111
|
-
urlName={
|
|
112
|
-
baseURL={
|
|
113
|
-
dataReturnType={
|
|
114
|
-
pathParamsType={
|
|
115
|
-
paramsCasing={
|
|
116
|
-
paramsType={
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
112
|
+
name={meta.name}
|
|
113
|
+
urlName={meta.urlName}
|
|
114
|
+
baseURL={baseURL}
|
|
115
|
+
dataReturnType={dataReturnType}
|
|
116
|
+
pathParamsType={pathParamsType}
|
|
117
|
+
paramsCasing={paramsCasing}
|
|
118
|
+
paramsType={paramsType}
|
|
119
|
+
node={node}
|
|
120
|
+
tsResolver={tsResolver}
|
|
121
|
+
zodResolver={zodResolver}
|
|
122
|
+
parser={parser}
|
|
121
123
|
/>
|
|
122
124
|
</File>
|
|
123
125
|
)
|