@kubb/plugin-swr 5.0.0-alpha.33 → 5.0.0-alpha.35
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/components-BJSzUg7M.cjs +955 -0
- package/dist/components-BJSzUg7M.cjs.map +1 -0
- package/dist/components-JQ2KRFCa.js +877 -0
- package/dist/components-JQ2KRFCa.js.map +1 -0
- package/dist/components.cjs +1 -1
- package/dist/components.d.ts +77 -37
- package/dist/components.js +1 -1
- package/dist/generators-17ulS9mu.cjs +537 -0
- package/dist/generators-17ulS9mu.cjs.map +1 -0
- package/dist/generators-Cl7nr-FB.js +526 -0
- package/dist/generators-Cl7nr-FB.js.map +1 -0
- package/dist/generators.cjs +1 -1
- package/dist/generators.d.ts +4 -4
- package/dist/generators.js +1 -1
- package/dist/index.cjs +132 -110
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +22 -2
- package/dist/index.js +132 -110
- package/dist/index.js.map +1 -1
- package/dist/{types-BVDtH9S7.d.ts → types-FA5mH9Ch.d.ts} +46 -90
- package/package.json +7 -11
- package/src/components/Mutation.tsx +165 -170
- package/src/components/MutationKey.tsx +50 -1
- package/src/components/Query.tsx +122 -126
- package/src/components/QueryKey.tsx +65 -1
- package/src/components/QueryOptions.tsx +38 -93
- package/src/generators/mutationGenerator.tsx +194 -117
- package/src/generators/queryGenerator.tsx +205 -139
- package/src/plugin.ts +117 -152
- package/src/resolvers/resolverSwr.ts +26 -0
- package/src/resolvers/resolverSwrLegacy.ts +17 -0
- package/src/types.ts +55 -18
- package/src/utils.ts +209 -0
- package/dist/components-DaCTPplv.js +0 -756
- package/dist/components-DaCTPplv.js.map +0 -1
- package/dist/components-Qs8_faOt.cjs +0 -834
- package/dist/components-Qs8_faOt.cjs.map +0 -1
- package/dist/generators-0YayIrse.js +0 -400
- package/dist/generators-0YayIrse.js.map +0 -1
- package/dist/generators-Bd4rCa3l.cjs +0 -411
- package/dist/generators-Bd4rCa3l.cjs.map +0 -1
|
@@ -1,168 +1,245 @@
|
|
|
1
1
|
import path from 'node:path'
|
|
2
|
-
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { useOas, useOperationManager } from '@kubb/plugin-oas/hooks'
|
|
6
|
-
import { getBanner, getFooter } from '@kubb/plugin-oas/utils'
|
|
2
|
+
|
|
3
|
+
import { ast, defineGenerator } from '@kubb/core'
|
|
4
|
+
import { ClientLegacy as ClientLegacyComponent, pluginClientName } from '@kubb/plugin-client'
|
|
7
5
|
import { pluginTsName } from '@kubb/plugin-ts'
|
|
8
6
|
import { pluginZodName } from '@kubb/plugin-zod'
|
|
9
|
-
import { File } from '@kubb/renderer-jsx'
|
|
7
|
+
import { File, jsxRenderer } from '@kubb/renderer-jsx'
|
|
10
8
|
import { difference } from 'remeda'
|
|
11
9
|
import { Mutation, MutationKey } from '../components'
|
|
12
10
|
import type { PluginSwr } from '../types'
|
|
11
|
+
import { transformName } from '../utils.ts'
|
|
13
12
|
|
|
14
|
-
export const mutationGenerator =
|
|
13
|
+
export const mutationGenerator = defineGenerator<PluginSwr>({
|
|
15
14
|
name: 'swr-mutation',
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
const isQuery = !!options.query && options.query?.methods.some((method) => operation.method === method)
|
|
15
|
+
renderer: jsxRenderer,
|
|
16
|
+
operation(node, ctx) {
|
|
17
|
+
const { adapter, config, driver, resolver, root } = ctx
|
|
18
|
+
const { output, query, mutation, paramsCasing, paramsType, pathParamsType, parser, client: clientOptions, group, transformers } = ctx.options
|
|
19
|
+
|
|
20
|
+
const pluginTs = driver.getPlugin(pluginTsName)
|
|
21
|
+
if (!pluginTs?.resolver) return null
|
|
22
|
+
const tsResolver = pluginTs.resolver
|
|
23
|
+
|
|
24
|
+
// Check if this operation is a mutation
|
|
25
|
+
const isQuery = !!query && query.methods.some((method) => node.method.toLowerCase() === method.toLowerCase())
|
|
28
26
|
const isMutation =
|
|
29
|
-
|
|
27
|
+
mutation !== false &&
|
|
30
28
|
!isQuery &&
|
|
31
|
-
difference(
|
|
29
|
+
difference(mutation ? mutation.methods : [], query ? query.methods : []).some((method) => node.method.toLowerCase() === method.toLowerCase())
|
|
32
30
|
|
|
33
|
-
|
|
31
|
+
if (!isMutation) return null
|
|
34
32
|
|
|
35
|
-
const
|
|
36
|
-
name: getName(operation, { type: 'function', prefix: 'use' }),
|
|
37
|
-
typeName: getName(operation, { type: 'type' }),
|
|
38
|
-
file: getFile(operation, { prefix: 'use' }),
|
|
39
|
-
}
|
|
33
|
+
const importPath = mutation ? mutation.importPath : 'swr/mutation'
|
|
40
34
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
}
|
|
35
|
+
// Resolve names — apply transformers.name to each constructed name to match the old
|
|
36
|
+
// createPlugin resolveName lifecycle (e.g. `addPetMutationKey` → `addPetMutationKeySWR`)
|
|
37
|
+
const baseName = resolver.resolveName(node.operationId)
|
|
38
|
+
const mutationHookName = transformName(`use${baseName.charAt(0).toUpperCase()}${baseName.slice(1)}`, 'function', transformers)
|
|
39
|
+
const mutationTypeName = transformName(`${baseName.charAt(0).toUpperCase()}${baseName.slice(1)}`, 'type', transformers)
|
|
40
|
+
const mutationKeyName = transformName(`${baseName}MutationKey`, 'const', transformers)
|
|
41
|
+
const mutationKeyTypeName = transformName(`${baseName.charAt(0).toUpperCase()}${baseName.slice(1)}MutationKey`, 'type', transformers)
|
|
42
|
+
const clientName = baseName
|
|
46
43
|
|
|
47
|
-
const
|
|
48
|
-
file:
|
|
49
|
-
|
|
44
|
+
const meta = {
|
|
45
|
+
file: resolver.resolveFile({ name: mutationHookName, extname: '.ts', tag: node.tags[0] ?? 'default', path: node.path }, { root, output, group }),
|
|
46
|
+
fileTs: tsResolver.resolveFile(
|
|
47
|
+
{ name: node.operationId, extname: '.ts', tag: node.tags[0] ?? 'default', path: node.path },
|
|
48
|
+
{ root, output: pluginTs.options?.output ?? output, group: pluginTs.options?.group },
|
|
49
|
+
),
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
const
|
|
53
|
-
|
|
54
|
-
const
|
|
55
|
-
const
|
|
56
|
-
name: shouldUseClientPlugin
|
|
57
|
-
? getName(operation, {
|
|
58
|
-
type: 'function',
|
|
59
|
-
pluginName: pluginClientName,
|
|
60
|
-
})
|
|
61
|
-
: getName(operation, {
|
|
62
|
-
type: 'function',
|
|
63
|
-
}),
|
|
64
|
-
file: getFile(operation, { pluginName: pluginClientName }),
|
|
65
|
-
}
|
|
52
|
+
const casedParams = ast.caseParams(node.parameters, paramsCasing)
|
|
53
|
+
const pathParams = casedParams.filter((p) => p.in === 'path')
|
|
54
|
+
const queryParams = casedParams.filter((p) => p.in === 'query')
|
|
55
|
+
const headerParams = casedParams.filter((p) => p.in === 'header')
|
|
66
56
|
|
|
67
|
-
const
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
57
|
+
const importedTypeNames = [
|
|
58
|
+
...pathParams.map((p) => tsResolver.resolvePathParamsName(node, p)),
|
|
59
|
+
...queryParams.map((p) => tsResolver.resolveQueryParamsName(node, p)),
|
|
60
|
+
...headerParams.map((p) => tsResolver.resolveHeaderParamsName(node, p)),
|
|
61
|
+
node.requestBody?.schema ? tsResolver.resolveDataName(node) : undefined,
|
|
62
|
+
tsResolver.resolveResponseName(node),
|
|
63
|
+
...node.responses.map((res) => tsResolver.resolveResponseStatusName(node, res.statusCode)),
|
|
64
|
+
].filter(Boolean)
|
|
71
65
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
66
|
+
const pluginZodRaw = parser === 'zod' ? driver.getPlugin(pluginZodName) : undefined
|
|
67
|
+
const pluginZod = pluginZodRaw?.name === pluginZodName ? pluginZodRaw : undefined
|
|
68
|
+
const zodResolver = pluginZod?.resolver
|
|
69
|
+
const fileZod = zodResolver
|
|
70
|
+
? zodResolver.resolveFile(
|
|
71
|
+
{ name: node.operationId, extname: '.ts', tag: node.tags[0] ?? 'default', path: node.path },
|
|
72
|
+
{ root, output: pluginZod?.options?.output ?? output, group: pluginZod?.options?.group },
|
|
73
|
+
)
|
|
74
|
+
: undefined
|
|
75
|
+
const zodSchemaNames =
|
|
76
|
+
zodResolver && parser === 'zod'
|
|
77
|
+
? [zodResolver.resolveResponseName?.(node), node.requestBody?.schema ? zodResolver.resolveDataName?.(node) : undefined].filter(Boolean)
|
|
78
|
+
: []
|
|
79
|
+
|
|
80
|
+
const clientPlugin = driver.getPlugin(pluginClientName)
|
|
81
|
+
const hasClientPlugin = clientPlugin?.name === pluginClientName
|
|
82
|
+
const shouldUseClientPlugin = hasClientPlugin && clientOptions.clientType !== 'class'
|
|
83
|
+
|
|
84
|
+
const clientFile = shouldUseClientPlugin
|
|
85
|
+
? clientPlugin?.resolver?.resolveFile(
|
|
86
|
+
{ name: node.operationId, extname: '.ts', tag: node.tags[0] ?? 'default', path: node.path },
|
|
87
|
+
{
|
|
88
|
+
root,
|
|
89
|
+
output: clientPlugin?.options?.output ?? output,
|
|
90
|
+
group: clientPlugin?.options?.group,
|
|
91
|
+
},
|
|
92
|
+
)
|
|
93
|
+
: undefined
|
|
94
|
+
|
|
95
|
+
const resolvedClientName = shouldUseClientPlugin ? (clientPlugin?.resolver?.resolveName(node.operationId) ?? clientName) : clientName
|
|
75
96
|
|
|
76
97
|
return (
|
|
77
98
|
<File
|
|
78
|
-
baseName={
|
|
79
|
-
path={
|
|
80
|
-
meta={
|
|
81
|
-
banner={
|
|
82
|
-
footer={
|
|
99
|
+
baseName={meta.file.baseName}
|
|
100
|
+
path={meta.file.path}
|
|
101
|
+
meta={meta.file.meta}
|
|
102
|
+
banner={resolver.resolveBanner(adapter.inputNode, { output, config })}
|
|
103
|
+
footer={resolver.resolveFooter(adapter.inputNode, { output, config })}
|
|
83
104
|
>
|
|
84
|
-
{
|
|
85
|
-
<File.Import name={[
|
|
105
|
+
{parser === 'zod' && fileZod && zodSchemaNames.length > 0 && (
|
|
106
|
+
<File.Import name={zodSchemaNames as string[]} root={meta.file.path} path={fileZod.path} />
|
|
86
107
|
)}
|
|
87
|
-
{
|
|
108
|
+
{clientOptions.importPath ? (
|
|
88
109
|
<>
|
|
89
|
-
{!shouldUseClientPlugin && <File.Import name={'fetch'} path={
|
|
90
|
-
<File.Import name={['Client', 'RequestConfig', 'ResponseErrorConfig']} path={
|
|
91
|
-
{
|
|
110
|
+
{!shouldUseClientPlugin && <File.Import name={'fetch'} path={clientOptions.importPath} />}
|
|
111
|
+
<File.Import name={['Client', 'RequestConfig', 'ResponseErrorConfig']} path={clientOptions.importPath} isTypeOnly />
|
|
112
|
+
{clientOptions.dataReturnType === 'full' && <File.Import name={['ResponseConfig']} path={clientOptions.importPath} isTypeOnly />}
|
|
92
113
|
</>
|
|
93
114
|
) : (
|
|
94
115
|
<>
|
|
95
|
-
{!shouldUseClientPlugin && <File.Import name={['fetch']} root={
|
|
116
|
+
{!shouldUseClientPlugin && <File.Import name={['fetch']} root={meta.file.path} path={path.resolve(root, '.kubb/fetch.ts')} />}
|
|
96
117
|
<File.Import
|
|
97
118
|
name={['Client', 'RequestConfig', 'ResponseErrorConfig']}
|
|
98
|
-
root={
|
|
119
|
+
root={meta.file.path}
|
|
99
120
|
path={path.resolve(root, '.kubb/fetch.ts')}
|
|
100
121
|
isTypeOnly
|
|
101
122
|
/>
|
|
102
|
-
{
|
|
103
|
-
<File.Import name={['ResponseConfig']} root={
|
|
123
|
+
{clientOptions.dataReturnType === 'full' && (
|
|
124
|
+
<File.Import name={['ResponseConfig']} root={meta.file.path} path={path.resolve(root, '.kubb/fetch.ts')} isTypeOnly />
|
|
104
125
|
)}
|
|
105
126
|
</>
|
|
106
127
|
)}
|
|
107
128
|
<File.Import name="useSWRMutation" path={importPath} />
|
|
108
129
|
<File.Import name={['SWRMutationConfiguration', 'SWRMutationResponse']} path={importPath} isTypeOnly />
|
|
109
|
-
{shouldUseClientPlugin && <File.Import name={[
|
|
110
|
-
{!shouldUseClientPlugin && <File.Import name={['buildFormData']} root={
|
|
111
|
-
|
|
112
|
-
name={
|
|
113
|
-
|
|
114
|
-
type.schemas.response.name,
|
|
115
|
-
type.schemas.pathParams?.name,
|
|
116
|
-
type.schemas.queryParams?.name,
|
|
117
|
-
type.schemas.headerParams?.name,
|
|
118
|
-
...(type.schemas.statusCodes?.map((item) => item.name) || []),
|
|
119
|
-
].filter(Boolean)}
|
|
120
|
-
root={mutation.file.path}
|
|
121
|
-
path={type.file.path}
|
|
122
|
-
isTypeOnly
|
|
123
|
-
/>
|
|
130
|
+
{shouldUseClientPlugin && clientFile && <File.Import name={[resolvedClientName]} root={meta.file.path} path={clientFile.path} />}
|
|
131
|
+
{!shouldUseClientPlugin && <File.Import name={['buildFormData']} root={meta.file.path} path={path.resolve(root, '.kubb/config.ts')} />}
|
|
132
|
+
{meta.fileTs && importedTypeNames.length > 0 && (
|
|
133
|
+
<File.Import name={Array.from(new Set(importedTypeNames))} root={meta.file.path} path={meta.fileTs.path} isTypeOnly />
|
|
134
|
+
)}
|
|
124
135
|
|
|
125
136
|
<MutationKey
|
|
126
|
-
name={
|
|
127
|
-
typeName={
|
|
128
|
-
|
|
129
|
-
pathParamsType={
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
transformer={options.mutationKey}
|
|
137
|
+
name={mutationKeyName}
|
|
138
|
+
typeName={mutationKeyTypeName}
|
|
139
|
+
node={node}
|
|
140
|
+
pathParamsType={pathParamsType}
|
|
141
|
+
paramsCasing={paramsCasing}
|
|
142
|
+
transformer={ctx.options.mutationKey}
|
|
133
143
|
/>
|
|
134
144
|
|
|
135
145
|
{!shouldUseClientPlugin && (
|
|
136
|
-
<
|
|
137
|
-
name={
|
|
138
|
-
baseURL={
|
|
139
|
-
operation={
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
146
|
+
<ClientLegacyComponent
|
|
147
|
+
name={resolvedClientName}
|
|
148
|
+
baseURL={clientOptions.baseURL}
|
|
149
|
+
operation={{
|
|
150
|
+
path: node.path,
|
|
151
|
+
method: node.method,
|
|
152
|
+
getDescription: () => node.description,
|
|
153
|
+
getSummary: () => node.summary,
|
|
154
|
+
isDeprecated: () => node.deprecated ?? false,
|
|
155
|
+
getContentType: () => node.requestBody?.contentType ?? 'application/json',
|
|
156
|
+
}}
|
|
157
|
+
typeSchemas={buildLegacyTypeSchemas(node, tsResolver)}
|
|
158
|
+
zodSchemas={zodResolver ? buildLegacyTypeSchemas(node, zodResolver) : undefined}
|
|
159
|
+
dataReturnType={clientOptions.dataReturnType || 'data'}
|
|
160
|
+
paramsCasing={clientOptions.paramsCasing || paramsCasing}
|
|
161
|
+
paramsType={paramsType}
|
|
162
|
+
pathParamsType={pathParamsType}
|
|
163
|
+
parser={parser}
|
|
147
164
|
/>
|
|
148
165
|
)}
|
|
149
|
-
|
|
166
|
+
|
|
167
|
+
{mutation && (
|
|
150
168
|
<Mutation
|
|
151
|
-
name={
|
|
152
|
-
clientName={
|
|
153
|
-
typeName={
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
dataReturnType={
|
|
157
|
-
paramsType={
|
|
158
|
-
paramsCasing={
|
|
159
|
-
pathParamsType={
|
|
160
|
-
mutationKeyName={
|
|
161
|
-
mutationKeyTypeName={
|
|
162
|
-
paramsToTrigger={
|
|
169
|
+
name={mutationHookName}
|
|
170
|
+
clientName={resolvedClientName}
|
|
171
|
+
typeName={mutationTypeName}
|
|
172
|
+
node={node}
|
|
173
|
+
tsResolver={tsResolver}
|
|
174
|
+
dataReturnType={clientOptions.dataReturnType || 'data'}
|
|
175
|
+
paramsType={paramsType}
|
|
176
|
+
paramsCasing={paramsCasing}
|
|
177
|
+
pathParamsType={pathParamsType}
|
|
178
|
+
mutationKeyName={mutationKeyName}
|
|
179
|
+
mutationKeyTypeName={mutationKeyTypeName}
|
|
180
|
+
paramsToTrigger={mutation.paramsToTrigger}
|
|
163
181
|
/>
|
|
164
182
|
)}
|
|
165
183
|
</File>
|
|
166
184
|
)
|
|
167
185
|
},
|
|
168
186
|
})
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Builds a legacy-compatible OperationSchemas object from OperationNode + resolver.
|
|
190
|
+
* Used for the ClientLegacy component which still expects the old format.
|
|
191
|
+
*/
|
|
192
|
+
// biome-ignore lint/suspicious/noExplicitAny: bridge between v5 resolver types and legacy OperationSchemas format
|
|
193
|
+
function buildLegacyTypeSchemas(node: ast.OperationNode, resolver: any) {
|
|
194
|
+
const pathParams = node.parameters.filter((p) => p.in === 'path')
|
|
195
|
+
const queryParams = node.parameters.filter((p) => p.in === 'query')
|
|
196
|
+
const headerParams = node.parameters.filter((p) => p.in === 'header')
|
|
197
|
+
|
|
198
|
+
const buildSchemaProps = (params: typeof pathParams) => {
|
|
199
|
+
const properties: Record<string, { type: string }> = {}
|
|
200
|
+
const required: string[] = []
|
|
201
|
+
for (const p of params) {
|
|
202
|
+
properties[p.name] = { type: p.schema?.primitive ?? 'unknown' }
|
|
203
|
+
if (p.required) required.push(p.name)
|
|
204
|
+
}
|
|
205
|
+
return { properties, required }
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
return {
|
|
209
|
+
response: { name: resolver.resolveResponseName(node) },
|
|
210
|
+
request: node.requestBody?.schema
|
|
211
|
+
? {
|
|
212
|
+
name: resolver.resolveDataName(node),
|
|
213
|
+
schema: { required: node.requestBody.required ? ['body'] : [] },
|
|
214
|
+
}
|
|
215
|
+
: undefined,
|
|
216
|
+
pathParams:
|
|
217
|
+
pathParams.length > 0 && resolver.resolvePathParamsName
|
|
218
|
+
? {
|
|
219
|
+
name: resolver.resolvePathParamsName(node, pathParams[0]!),
|
|
220
|
+
schema: buildSchemaProps(pathParams),
|
|
221
|
+
}
|
|
222
|
+
: undefined,
|
|
223
|
+
queryParams:
|
|
224
|
+
queryParams.length > 0 && resolver.resolveQueryParamsName
|
|
225
|
+
? {
|
|
226
|
+
name: resolver.resolveQueryParamsName(node, queryParams[0]!),
|
|
227
|
+
schema: buildSchemaProps(queryParams),
|
|
228
|
+
}
|
|
229
|
+
: undefined,
|
|
230
|
+
headerParams:
|
|
231
|
+
headerParams.length > 0 && resolver.resolveHeaderParamsName
|
|
232
|
+
? {
|
|
233
|
+
name: resolver.resolveHeaderParamsName(node, headerParams[0]!),
|
|
234
|
+
schema: buildSchemaProps(headerParams),
|
|
235
|
+
}
|
|
236
|
+
: undefined,
|
|
237
|
+
errors: node.responses
|
|
238
|
+
.filter((r) => {
|
|
239
|
+
const code = Number.parseInt(r.statusCode, 10)
|
|
240
|
+
return code >= 400 || r.statusCode === 'default'
|
|
241
|
+
})
|
|
242
|
+
.map((r) => ({ name: resolver.resolveResponseStatusName(node, r.statusCode) })),
|
|
243
|
+
statusCodes: node.responses.map((r) => ({ name: resolver.resolveResponseStatusName(node, r.statusCode) })),
|
|
244
|
+
}
|
|
245
|
+
}
|