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