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