@kubb/plugin-vue-query 5.0.0-alpha.9 → 5.0.0-beta.4
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 +1 -3
- package/dist/components-D1UhYFgY.js +1277 -0
- package/dist/components-D1UhYFgY.js.map +1 -0
- package/dist/components-qfOFRSoM.cjs +1367 -0
- package/dist/components-qfOFRSoM.cjs.map +1 -0
- package/dist/components.cjs +1 -1
- package/dist/components.d.ts +118 -109
- package/dist/components.js +1 -1
- package/dist/generators-C4gs_P1i.cjs +726 -0
- package/dist/generators-C4gs_P1i.cjs.map +1 -0
- package/dist/generators-CbnIVBgY.js +709 -0
- package/dist/generators-CbnIVBgY.js.map +1 -0
- package/dist/generators.cjs +1 -1
- package/dist/generators.d.ts +5 -501
- package/dist/generators.js +1 -1
- package/dist/index.cjs +106 -121
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.js +102 -121
- package/dist/index.js.map +1 -1
- package/dist/types-nVDTfuS1.d.ts +194 -0
- package/extension.yaml +793 -0
- package/package.json +61 -64
- package/src/components/InfiniteQuery.tsx +104 -153
- package/src/components/InfiniteQueryOptions.tsx +122 -162
- package/src/components/Mutation.tsx +110 -136
- package/src/components/Query.tsx +102 -151
- package/src/components/QueryKey.tsx +68 -58
- package/src/components/QueryOptions.tsx +147 -139
- package/src/generators/infiniteQueryGenerator.tsx +165 -170
- package/src/generators/mutationGenerator.tsx +117 -124
- package/src/generators/queryGenerator.tsx +138 -136
- package/src/index.ts +1 -1
- package/src/plugin.ts +124 -175
- package/src/resolvers/resolverVueQuery.ts +19 -0
- package/src/types.ts +68 -48
- package/src/utils.ts +37 -0
- package/dist/components-Yjoe78Y7.cjs +0 -1119
- package/dist/components-Yjoe78Y7.cjs.map +0 -1
- package/dist/components-_AMBl0g-.js +0 -1029
- package/dist/components-_AMBl0g-.js.map +0 -1
- package/dist/generators-CR34GjVu.js +0 -661
- package/dist/generators-CR34GjVu.js.map +0 -1
- package/dist/generators-DH8VkK1q.cjs +0 -678
- package/dist/generators-DH8VkK1q.cjs.map +0 -1
- package/dist/types-CgDFUvfZ.d.ts +0 -211
|
@@ -1,18 +1,20 @@
|
|
|
1
1
|
import { getNestedAccessor } from '@internals/utils'
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import type { FabricReactNode } from '@kubb/react-fabric/types'
|
|
2
|
+
import type { ast } from '@kubb/core'
|
|
3
|
+
import type { ResolverTs } from '@kubb/plugin-ts'
|
|
4
|
+
import { functionPrinter } from '@kubb/plugin-ts'
|
|
5
|
+
import { File, Function } from '@kubb/renderer-jsx'
|
|
6
|
+
import type { KubbReactNode } from '@kubb/renderer-jsx/types'
|
|
8
7
|
import type { Infinite, PluginVueQuery } from '../types.ts'
|
|
8
|
+
import { resolveErrorNames } from '../utils.ts'
|
|
9
9
|
import { QueryKey } from './QueryKey.tsx'
|
|
10
|
+
import { buildEnabledCheck, getQueryOptionsParams } from './QueryOptions.tsx'
|
|
10
11
|
|
|
11
12
|
type Props = {
|
|
12
13
|
name: string
|
|
13
14
|
clientName: string
|
|
14
15
|
queryKeyName: string
|
|
15
|
-
|
|
16
|
+
node: ast.OperationNode
|
|
17
|
+
tsResolver: ResolverTs
|
|
16
18
|
paramsCasing: PluginVueQuery['resolvedOptions']['paramsCasing']
|
|
17
19
|
paramsType: PluginVueQuery['resolvedOptions']['paramsType']
|
|
18
20
|
pathParamsType: PluginVueQuery['resolvedOptions']['pathParamsType']
|
|
@@ -24,105 +26,8 @@ type Props = {
|
|
|
24
26
|
queryParam: Infinite['queryParam']
|
|
25
27
|
}
|
|
26
28
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
paramsType: PluginVueQuery['resolvedOptions']['paramsType']
|
|
30
|
-
pathParamsType: PluginVueQuery['resolvedOptions']['pathParamsType']
|
|
31
|
-
typeSchemas: OperationSchemas
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
function getParams({ paramsType, paramsCasing, pathParamsType, typeSchemas }: GetParamsProps) {
|
|
35
|
-
if (paramsType === 'object') {
|
|
36
|
-
const children = {
|
|
37
|
-
...getPathParams(typeSchemas.pathParams, {
|
|
38
|
-
typed: true,
|
|
39
|
-
casing: paramsCasing,
|
|
40
|
-
override(item) {
|
|
41
|
-
return {
|
|
42
|
-
...item,
|
|
43
|
-
type: `MaybeRefOrGetter<${item.type}>`,
|
|
44
|
-
}
|
|
45
|
-
},
|
|
46
|
-
}),
|
|
47
|
-
data: typeSchemas.request?.name
|
|
48
|
-
? {
|
|
49
|
-
type: `MaybeRefOrGetter<${typeSchemas.request?.name}>`,
|
|
50
|
-
optional: isOptional(typeSchemas.request?.schema),
|
|
51
|
-
}
|
|
52
|
-
: undefined,
|
|
53
|
-
params: typeSchemas.queryParams?.name
|
|
54
|
-
? {
|
|
55
|
-
type: `MaybeRefOrGetter<${typeSchemas.queryParams?.name}>`,
|
|
56
|
-
optional: isOptional(typeSchemas.queryParams?.schema),
|
|
57
|
-
}
|
|
58
|
-
: undefined,
|
|
59
|
-
headers: typeSchemas.headerParams?.name
|
|
60
|
-
? {
|
|
61
|
-
type: `MaybeRefOrGetter<${typeSchemas.queryParams?.name}>`,
|
|
62
|
-
optional: isOptional(typeSchemas.headerParams?.schema),
|
|
63
|
-
}
|
|
64
|
-
: undefined,
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
// Check if all children are optional or undefined
|
|
68
|
-
const allChildrenAreOptional = Object.values(children).every((child) => !child || child.optional)
|
|
69
|
-
|
|
70
|
-
return FunctionParams.factory({
|
|
71
|
-
data: {
|
|
72
|
-
mode: 'object',
|
|
73
|
-
children,
|
|
74
|
-
default: allChildrenAreOptional ? '{}' : undefined,
|
|
75
|
-
},
|
|
76
|
-
config: {
|
|
77
|
-
type: typeSchemas.request?.name
|
|
78
|
-
? `Partial<RequestConfig<${typeSchemas.request?.name}>> & { client?: Client }`
|
|
79
|
-
: 'Partial<RequestConfig> & { client?: Client }',
|
|
80
|
-
default: '{}',
|
|
81
|
-
},
|
|
82
|
-
})
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
return FunctionParams.factory({
|
|
86
|
-
pathParams: {
|
|
87
|
-
mode: pathParamsType === 'object' ? 'object' : 'inlineSpread',
|
|
88
|
-
children: getPathParams(typeSchemas.pathParams, {
|
|
89
|
-
typed: true,
|
|
90
|
-
casing: paramsCasing,
|
|
91
|
-
override(item) {
|
|
92
|
-
return {
|
|
93
|
-
...item,
|
|
94
|
-
type: `MaybeRefOrGetter<${item.type}>`,
|
|
95
|
-
}
|
|
96
|
-
},
|
|
97
|
-
}),
|
|
98
|
-
default: getDefaultValue(typeSchemas.pathParams?.schema),
|
|
99
|
-
},
|
|
100
|
-
data: typeSchemas.request?.name
|
|
101
|
-
? {
|
|
102
|
-
type: `MaybeRefOrGetter<${typeSchemas.request?.name}>`,
|
|
103
|
-
optional: isOptional(typeSchemas.request?.schema),
|
|
104
|
-
}
|
|
105
|
-
: undefined,
|
|
106
|
-
params: typeSchemas.queryParams?.name
|
|
107
|
-
? {
|
|
108
|
-
type: `MaybeRefOrGetter<${typeSchemas.queryParams?.name}>`,
|
|
109
|
-
optional: isOptional(typeSchemas.queryParams?.schema),
|
|
110
|
-
}
|
|
111
|
-
: undefined,
|
|
112
|
-
headers: typeSchemas.headerParams?.name
|
|
113
|
-
? {
|
|
114
|
-
type: `MaybeRefOrGetter<${typeSchemas.headerParams?.name}>`,
|
|
115
|
-
optional: isOptional(typeSchemas.headerParams?.schema),
|
|
116
|
-
}
|
|
117
|
-
: undefined,
|
|
118
|
-
config: {
|
|
119
|
-
type: typeSchemas.request?.name
|
|
120
|
-
? `Partial<RequestConfig<${typeSchemas.request?.name}>> & { client?: Client }`
|
|
121
|
-
: 'Partial<RequestConfig> & { client?: Client }',
|
|
122
|
-
default: '{}',
|
|
123
|
-
},
|
|
124
|
-
})
|
|
125
|
-
}
|
|
29
|
+
const declarationPrinter = functionPrinter({ mode: 'declaration' })
|
|
30
|
+
const callPrinter = functionPrinter({ mode: 'call' })
|
|
126
31
|
|
|
127
32
|
export function InfiniteQueryOptions({
|
|
128
33
|
name,
|
|
@@ -131,39 +36,65 @@ export function InfiniteQueryOptions({
|
|
|
131
36
|
cursorParam,
|
|
132
37
|
nextParam,
|
|
133
38
|
previousParam,
|
|
134
|
-
|
|
135
|
-
|
|
39
|
+
node,
|
|
40
|
+
tsResolver,
|
|
136
41
|
paramsCasing,
|
|
42
|
+
paramsType,
|
|
137
43
|
dataReturnType,
|
|
138
44
|
pathParamsType,
|
|
139
45
|
queryParam,
|
|
140
46
|
queryKeyName,
|
|
141
|
-
}: Props):
|
|
142
|
-
const
|
|
143
|
-
const
|
|
144
|
-
|
|
145
|
-
const
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
47
|
+
}: Props): KubbReactNode {
|
|
48
|
+
const responseName = tsResolver.resolveResponseName(node)
|
|
49
|
+
const queryFnDataType = dataReturnType === 'data' ? responseName : `ResponseConfig<${responseName}>`
|
|
50
|
+
const errorNames = resolveErrorNames(node, tsResolver)
|
|
51
|
+
const errorType = `ResponseErrorConfig<${errorNames.length > 0 ? errorNames.join(' | ') : 'Error'}>`
|
|
52
|
+
|
|
53
|
+
const isInitialPageParamDefined = initialPageParam !== undefined && initialPageParam !== null
|
|
54
|
+
const fallbackPageParamType =
|
|
55
|
+
typeof initialPageParam === 'number'
|
|
56
|
+
? 'number'
|
|
57
|
+
: typeof initialPageParam === 'string'
|
|
58
|
+
? initialPageParam.includes(' as ')
|
|
59
|
+
? (() => {
|
|
60
|
+
const parts = initialPageParam.split(' as ')
|
|
61
|
+
return parts[parts.length - 1] ?? 'unknown'
|
|
62
|
+
})()
|
|
63
|
+
: 'string'
|
|
64
|
+
: typeof initialPageParam === 'boolean'
|
|
65
|
+
? 'boolean'
|
|
66
|
+
: 'unknown'
|
|
67
|
+
|
|
68
|
+
const rawQueryParams = node.parameters.filter((p) => p.in === 'query')
|
|
69
|
+
const queryParamsTypeName =
|
|
70
|
+
rawQueryParams.length > 0
|
|
71
|
+
? (() => {
|
|
72
|
+
const groupName = tsResolver.resolveQueryParamsName(node, rawQueryParams[0]!)
|
|
73
|
+
const individualName = tsResolver.resolveParamName(node, rawQueryParams[0]!)
|
|
74
|
+
return groupName !== individualName ? groupName : undefined
|
|
75
|
+
})()
|
|
76
|
+
: undefined
|
|
77
|
+
|
|
78
|
+
const queryParamType = queryParam && queryParamsTypeName ? `${queryParamsTypeName}['${queryParam}']` : undefined
|
|
79
|
+
const pageParamType = queryParamType ? (isInitialPageParamDefined ? `NonNullable<${queryParamType}>` : queryParamType) : fallbackPageParamType
|
|
80
|
+
|
|
81
|
+
const paramsNode = getQueryOptionsParams(node, { paramsType, paramsCasing, pathParamsType, resolver: tsResolver })
|
|
82
|
+
const paramsSignature = declarationPrinter.print(paramsNode) ?? ''
|
|
83
|
+
const rawParamsCall = callPrinter.print(paramsNode) ?? ''
|
|
84
|
+
const clientCallStr = rawParamsCall.replace(/\bconfig\b(?=[^,]*$)/, '{ ...config, signal: config.signal ?? signal }')
|
|
85
|
+
|
|
86
|
+
const queryKeyParamsNode = QueryKey.getParams(node, { pathParamsType, paramsCasing, resolver: tsResolver })
|
|
87
|
+
const queryKeyParamsCall = callPrinter.print(queryKeyParamsNode) ?? ''
|
|
88
|
+
|
|
89
|
+
const enabledSource = buildEnabledCheck(queryKeyParamsNode)
|
|
90
|
+
const enabledText = enabledSource ? `enabled: () => !!(${enabledSource}),` : ''
|
|
158
91
|
|
|
159
|
-
// Determine if we should use the new nextParam/previousParam or fall back to legacy cursorParam behavior
|
|
160
92
|
const hasNewParams = nextParam !== undefined || previousParam !== undefined
|
|
161
93
|
|
|
162
94
|
let getNextPageParamExpr: string | undefined
|
|
163
95
|
let getPreviousPageParamExpr: string | undefined
|
|
164
96
|
|
|
165
97
|
if (hasNewParams) {
|
|
166
|
-
// Use the new nextParam and previousParam
|
|
167
98
|
if (nextParam) {
|
|
168
99
|
const accessor = getNestedAccessor(nextParam, 'lastPage')
|
|
169
100
|
if (accessor) {
|
|
@@ -177,11 +108,9 @@ export function InfiniteQueryOptions({
|
|
|
177
108
|
}
|
|
178
109
|
}
|
|
179
110
|
} else if (cursorParam) {
|
|
180
|
-
// Legacy behavior: use cursorParam for both next and previous
|
|
181
111
|
getNextPageParamExpr = `getNextPageParam: (lastPage) => lastPage['${cursorParam}']`
|
|
182
112
|
getPreviousPageParamExpr = `getPreviousPageParam: (firstPage) => firstPage['${cursorParam}']`
|
|
183
113
|
} else {
|
|
184
|
-
// Fallback behavior: page-based pagination
|
|
185
114
|
if (dataReturnType === 'full') {
|
|
186
115
|
getNextPageParamExpr =
|
|
187
116
|
'getNextPageParam: (lastPage, _allPages, lastPageParam) => Array.isArray(lastPage.data) && lastPage.data.length === 0 ? undefined : lastPageParam + 1'
|
|
@@ -192,53 +121,54 @@ export function InfiniteQueryOptions({
|
|
|
192
121
|
getPreviousPageParamExpr = 'getPreviousPageParam: (_firstPage, _allPages, firstPageParam) => firstPageParam <= 1 ? undefined : firstPageParam - 1'
|
|
193
122
|
}
|
|
194
123
|
|
|
195
|
-
const
|
|
124
|
+
const queryOptionsArr = [
|
|
196
125
|
`initialPageParam: ${typeof initialPageParam === 'string' ? JSON.stringify(initialPageParam) : initialPageParam}`,
|
|
197
126
|
getNextPageParamExpr,
|
|
198
127
|
getPreviousPageParamExpr,
|
|
199
128
|
].filter(Boolean)
|
|
200
129
|
|
|
201
130
|
const infiniteOverrideParams =
|
|
202
|
-
queryParam &&
|
|
131
|
+
queryParam && queryParamsTypeName
|
|
203
132
|
? `
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
133
|
+
params = {
|
|
134
|
+
...(params ?? {}),
|
|
135
|
+
['${queryParam}']: pageParam as unknown as ${queryParamsTypeName}['${queryParam}'],
|
|
136
|
+
} as ${queryParamsTypeName}`
|
|
208
137
|
: ''
|
|
209
138
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
139
|
+
if (infiniteOverrideParams) {
|
|
140
|
+
return (
|
|
141
|
+
<File.Source name={name} isExportable isIndexable>
|
|
142
|
+
<Function name={name} export params={paramsSignature}>
|
|
143
|
+
{`
|
|
144
|
+
const queryKey = ${queryKeyName}(${queryKeyParamsCall})
|
|
145
|
+
return infiniteQueryOptions<${queryFnDataType}, ${errorType}, InfiniteData<${queryFnDataType}>, QueryKey, ${pageParamType}>({
|
|
146
|
+
${enabledText}
|
|
147
|
+
queryKey,
|
|
148
|
+
queryFn: async ({ signal, pageParam }) => {
|
|
149
|
+
${infiniteOverrideParams}
|
|
150
|
+
return ${clientName}(${addToValueCalls(clientCallStr)})
|
|
151
|
+
},
|
|
152
|
+
${queryOptionsArr.join(',\n')}
|
|
153
|
+
})
|
|
154
|
+
`}
|
|
155
|
+
</Function>
|
|
156
|
+
</File.Source>
|
|
157
|
+
)
|
|
158
|
+
}
|
|
220
159
|
|
|
221
160
|
return (
|
|
222
161
|
<File.Source name={name} isExportable isIndexable>
|
|
223
|
-
<Function name={name} export params={
|
|
162
|
+
<Function name={name} export params={paramsSignature}>
|
|
224
163
|
{`
|
|
225
|
-
const queryKey = ${queryKeyName}(${
|
|
226
|
-
return infiniteQueryOptions<${
|
|
164
|
+
const queryKey = ${queryKeyName}(${queryKeyParamsCall})
|
|
165
|
+
return infiniteQueryOptions<${queryFnDataType}, ${errorType}, InfiniteData<${queryFnDataType}>, QueryKey, ${pageParamType}>({
|
|
227
166
|
${enabledText}
|
|
228
167
|
queryKey,
|
|
229
|
-
queryFn: async ({ signal
|
|
230
|
-
${
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
if (name === 'config') {
|
|
234
|
-
return '{ ...config, signal: config.signal ?? signal }'
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
return `toValue(${name})`
|
|
238
|
-
},
|
|
239
|
-
})})
|
|
240
|
-
},
|
|
241
|
-
${queryOptions.join(',\n')}
|
|
168
|
+
queryFn: async ({ signal }) => {
|
|
169
|
+
return ${clientName}(${addToValueCalls(clientCallStr)})
|
|
170
|
+
},
|
|
171
|
+
${queryOptionsArr.join(',\n')}
|
|
242
172
|
})
|
|
243
173
|
`}
|
|
244
174
|
</Function>
|
|
@@ -246,4 +176,34 @@ export function InfiniteQueryOptions({
|
|
|
246
176
|
)
|
|
247
177
|
}
|
|
248
178
|
|
|
249
|
-
|
|
179
|
+
function addToValueCalls(callStr: string): string {
|
|
180
|
+
// Step 1: Transform shorthand object params like { petId } → { petId: toValue(petId) }
|
|
181
|
+
let result = callStr.replace(/\{\s*([\w,\s]+)\s*\}(?=\s*,)/g, (match, inner: string) => {
|
|
182
|
+
if (inner.includes(':') || inner.includes('...')) return match
|
|
183
|
+
const keys = inner
|
|
184
|
+
.split(',')
|
|
185
|
+
.map((k: string) => k.trim())
|
|
186
|
+
.filter(Boolean)
|
|
187
|
+
const wrapped = keys.map((k: string) => `${k}: toValue(${k})`).join(', ')
|
|
188
|
+
return `{ ${wrapped} }`
|
|
189
|
+
})
|
|
190
|
+
|
|
191
|
+
// Step 2: Handle standalone identifiers like `data, params`
|
|
192
|
+
result = result.replace(/(?<![{.:?])\b(\w+)\b(?=\s*,)/g, (match, name: string) => {
|
|
193
|
+
if (name === 'config' || name === 'signal' || name === 'undefined') return match
|
|
194
|
+
if (match.includes('toValue(')) return match
|
|
195
|
+
return `toValue(${name})`
|
|
196
|
+
})
|
|
197
|
+
|
|
198
|
+
return result
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
InfiniteQueryOptions.getParams = (
|
|
202
|
+
node: ast.OperationNode,
|
|
203
|
+
options: {
|
|
204
|
+
paramsType: PluginVueQuery['resolvedOptions']['paramsType']
|
|
205
|
+
paramsCasing: PluginVueQuery['resolvedOptions']['paramsCasing']
|
|
206
|
+
pathParamsType: PluginVueQuery['resolvedOptions']['pathParamsType']
|
|
207
|
+
resolver: ResolverTs
|
|
208
|
+
},
|
|
209
|
+
) => getQueryOptionsParams(node, options)
|
|
@@ -1,84 +1,90 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import type { FabricReactNode, Params } from '@kubb/react-fabric/types'
|
|
1
|
+
import { ast } from '@kubb/core'
|
|
2
|
+
import type { ResolverTs } from '@kubb/plugin-ts'
|
|
3
|
+
import { functionPrinter } from '@kubb/plugin-ts'
|
|
4
|
+
import { File, Function } from '@kubb/renderer-jsx'
|
|
5
|
+
import type { KubbReactNode } from '@kubb/renderer-jsx/types'
|
|
7
6
|
import type { PluginVueQuery } from '../types.ts'
|
|
7
|
+
import { buildMutationArgParams, getComments, resolveErrorNames } from '../utils.ts'
|
|
8
8
|
import { MutationKey } from './MutationKey.tsx'
|
|
9
9
|
|
|
10
10
|
type Props = {
|
|
11
|
-
/**
|
|
12
|
-
* Name of the function
|
|
13
|
-
*/
|
|
14
11
|
name: string
|
|
15
12
|
typeName: string
|
|
16
13
|
clientName: string
|
|
17
14
|
mutationKeyName: string
|
|
18
|
-
|
|
19
|
-
|
|
15
|
+
node: ast.OperationNode
|
|
16
|
+
tsResolver: ResolverTs
|
|
20
17
|
paramsCasing: PluginVueQuery['resolvedOptions']['paramsCasing']
|
|
21
18
|
paramsType: PluginVueQuery['resolvedOptions']['paramsType']
|
|
22
19
|
dataReturnType: PluginVueQuery['resolvedOptions']['client']['dataReturnType']
|
|
23
20
|
pathParamsType: PluginVueQuery['resolvedOptions']['pathParamsType']
|
|
24
21
|
}
|
|
25
22
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
23
|
+
const declarationPrinter = functionPrinter({ mode: 'declaration' })
|
|
24
|
+
const callPrinter = functionPrinter({ mode: 'call' })
|
|
25
|
+
const keysPrinter = functionPrinter({ mode: 'keys' })
|
|
26
|
+
|
|
27
|
+
function getParams(
|
|
28
|
+
node: ast.OperationNode,
|
|
29
|
+
options: {
|
|
30
|
+
paramsCasing: PluginVueQuery['resolvedOptions']['paramsCasing']
|
|
31
|
+
dataReturnType: PluginVueQuery['resolvedOptions']['client']['dataReturnType']
|
|
32
|
+
resolver: ResolverTs
|
|
33
|
+
},
|
|
34
|
+
): ast.FunctionParametersNode {
|
|
35
|
+
const { paramsCasing, dataReturnType, resolver } = options
|
|
36
|
+
const responseName = resolver.resolveResponseName(node)
|
|
37
|
+
const requestName = node.requestBody?.content?.[0]?.schema ? resolver.resolveDataName(node) : undefined
|
|
38
|
+
const errorNames = resolveErrorNames(node, resolver)
|
|
39
|
+
|
|
40
|
+
const TData = dataReturnType === 'data' ? responseName : `ResponseConfig<${responseName}>`
|
|
41
|
+
const TError = `ResponseErrorConfig<${errorNames.length > 0 ? errorNames.join(' | ') : 'Error'}>`
|
|
42
|
+
|
|
43
|
+
const mutationArgParamsNode = buildMutationArgParams(node, { paramsCasing, resolver })
|
|
32
44
|
|
|
33
|
-
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
casing: paramsCasing,
|
|
41
|
-
override(item) {
|
|
42
|
-
return {
|
|
43
|
-
...item,
|
|
44
|
-
type: `MaybeRefOrGetter<${item.type}>`,
|
|
45
|
-
}
|
|
46
|
-
},
|
|
47
|
-
}),
|
|
48
|
-
data: typeSchemas.request?.name
|
|
49
|
-
? {
|
|
50
|
-
type: `MaybeRefOrGetter<${typeSchemas.request?.name}>`,
|
|
51
|
-
optional: isOptional(typeSchemas.request?.schema),
|
|
52
|
-
}
|
|
53
|
-
: undefined,
|
|
54
|
-
params: typeSchemas.queryParams?.name
|
|
55
|
-
? {
|
|
56
|
-
type: `MaybeRefOrGetter<${typeSchemas.queryParams?.name}>`,
|
|
57
|
-
optional: isOptional(typeSchemas.queryParams?.schema),
|
|
58
|
-
}
|
|
59
|
-
: undefined,
|
|
60
|
-
headers: typeSchemas.headerParams?.name
|
|
61
|
-
? {
|
|
62
|
-
type: `MaybeRefOrGetter<${typeSchemas.headerParams?.name}>`,
|
|
63
|
-
optional: isOptional(typeSchemas.headerParams?.schema),
|
|
64
|
-
}
|
|
65
|
-
: undefined,
|
|
45
|
+
// Vue-query uses MutationObserverOptions instead of UseMutationOptions, and wraps params with MaybeRefOrGetter
|
|
46
|
+
const mutationArgWrapped = mutationArgParamsNode.params.map((param) => {
|
|
47
|
+
const fp = param as ast.FunctionParameterNode
|
|
48
|
+
return {
|
|
49
|
+
...fp,
|
|
50
|
+
type: fp.type ? ast.createParamsType({ variant: 'reference', name: `MaybeRefOrGetter<${printType(fp.type)}>` }) : fp.type,
|
|
51
|
+
}
|
|
66
52
|
})
|
|
67
|
-
const
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
{
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
53
|
+
const wrappedParamsNode = ast.createFunctionParameters({ params: mutationArgWrapped })
|
|
54
|
+
const TRequestWrapped = wrappedParamsNode.params.length > 0 ? (declarationPrinter.print(wrappedParamsNode) ?? '') : ''
|
|
55
|
+
|
|
56
|
+
return ast.createFunctionParameters({
|
|
57
|
+
params: [
|
|
58
|
+
ast.createFunctionParameter({
|
|
59
|
+
name: 'options',
|
|
60
|
+
type: ast.createParamsType({
|
|
61
|
+
variant: 'reference',
|
|
62
|
+
name: `{
|
|
63
|
+
mutation?: MutationObserverOptions<${[TData, TError, TRequestWrapped ? `{${TRequestWrapped}}` : 'void', 'TContext'].join(', ')}> & { client?: QueryClient },
|
|
64
|
+
client?: ${requestName ? `Partial<RequestConfig<${requestName}>> & { client?: Client }` : 'Partial<RequestConfig> & { client?: Client }'},
|
|
65
|
+
}`,
|
|
66
|
+
}),
|
|
67
|
+
default: '{}',
|
|
68
|
+
}),
|
|
69
|
+
],
|
|
79
70
|
})
|
|
80
71
|
}
|
|
81
72
|
|
|
73
|
+
function printType(typeNode: ast.ParamsTypeNode | undefined): string {
|
|
74
|
+
if (!typeNode) return 'unknown'
|
|
75
|
+
if (typeNode.variant === 'reference') return typeNode.name
|
|
76
|
+
if (typeNode.variant === 'member') return `${typeNode.base}['${typeNode.key}']`
|
|
77
|
+
if (typeNode.variant === 'struct') {
|
|
78
|
+
const parts = typeNode.properties.map((p) => {
|
|
79
|
+
const typeStr = printType(p.type)
|
|
80
|
+
const key = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(p.name) ? p.name : JSON.stringify(p.name)
|
|
81
|
+
return p.optional ? `${key}?: ${typeStr}` : `${key}: ${typeStr}`
|
|
82
|
+
})
|
|
83
|
+
return `{ ${parts.join('; ')} }`
|
|
84
|
+
}
|
|
85
|
+
return 'unknown'
|
|
86
|
+
}
|
|
87
|
+
|
|
82
88
|
export function Mutation({
|
|
83
89
|
name,
|
|
84
90
|
clientName,
|
|
@@ -86,94 +92,60 @@ export function Mutation({
|
|
|
86
92
|
paramsType,
|
|
87
93
|
pathParamsType,
|
|
88
94
|
dataReturnType,
|
|
89
|
-
|
|
90
|
-
|
|
95
|
+
node,
|
|
96
|
+
tsResolver,
|
|
91
97
|
mutationKeyName,
|
|
92
|
-
}: Props):
|
|
93
|
-
const
|
|
94
|
-
|
|
95
|
-
typeSchemas,
|
|
96
|
-
})
|
|
98
|
+
}: Props): KubbReactNode {
|
|
99
|
+
const responseName = tsResolver.resolveResponseName(node)
|
|
100
|
+
const errorNames = resolveErrorNames(node, tsResolver)
|
|
97
101
|
|
|
98
|
-
const
|
|
99
|
-
|
|
100
|
-
pathParamsType,
|
|
101
|
-
dataReturnType,
|
|
102
|
-
typeSchemas,
|
|
103
|
-
})
|
|
102
|
+
const TData = dataReturnType === 'data' ? responseName : `ResponseConfig<${responseName}>`
|
|
103
|
+
const TError = `ResponseErrorConfig<${errorNames.length > 0 ? errorNames.join(' | ') : 'Error'}>`
|
|
104
104
|
|
|
105
|
-
const
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
pathParamsType,
|
|
110
|
-
isConfigurable: true,
|
|
111
|
-
})
|
|
105
|
+
const mutationArgParamsNode = buildMutationArgParams(node, { paramsCasing, resolver: tsResolver })
|
|
106
|
+
const hasMutationParams = mutationArgParamsNode.params.length > 0
|
|
107
|
+
const TRequest = hasMutationParams ? (declarationPrinter.print(mutationArgParamsNode) ?? '') : ''
|
|
108
|
+
const argKeysStr = hasMutationParams ? (keysPrinter.print(mutationArgParamsNode) ?? '') : ''
|
|
112
109
|
|
|
113
|
-
const
|
|
114
|
-
...getPathParams(typeSchemas.pathParams, { typed: true, casing: paramsCasing }),
|
|
115
|
-
data: typeSchemas.request?.name
|
|
116
|
-
? {
|
|
117
|
-
type: typeSchemas.request?.name,
|
|
118
|
-
optional: isOptional(typeSchemas.request?.schema),
|
|
119
|
-
}
|
|
120
|
-
: undefined,
|
|
121
|
-
params: typeSchemas.queryParams?.name
|
|
122
|
-
? {
|
|
123
|
-
type: typeSchemas.queryParams?.name,
|
|
124
|
-
optional: isOptional(typeSchemas.queryParams?.schema),
|
|
125
|
-
}
|
|
126
|
-
: undefined,
|
|
127
|
-
headers: typeSchemas.headerParams?.name
|
|
128
|
-
? {
|
|
129
|
-
type: typeSchemas.headerParams?.name,
|
|
130
|
-
optional: isOptional(typeSchemas.headerParams?.schema),
|
|
131
|
-
}
|
|
132
|
-
: undefined,
|
|
133
|
-
})
|
|
134
|
-
const dataParams = FunctionParams.factory({
|
|
135
|
-
data: {
|
|
136
|
-
// No use of pathParams because useMutation can only take one argument in object form,
|
|
137
|
-
// see https://tanstack.com/query/latest/docs/framework/react/reference/useMutation#usemutation
|
|
138
|
-
mode: 'object',
|
|
139
|
-
children: Object.entries(mutationParams.params).reduce((acc, [key, value]) => {
|
|
140
|
-
if (value) {
|
|
141
|
-
acc[key] = {
|
|
142
|
-
...value,
|
|
143
|
-
type: undefined,
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
return acc
|
|
148
|
-
}, {} as Params),
|
|
149
|
-
},
|
|
150
|
-
})
|
|
110
|
+
const generics = [TData, TError, TRequest ? `{${TRequest}}` : 'void', 'TContext'].join(', ')
|
|
151
111
|
|
|
152
|
-
const
|
|
153
|
-
const
|
|
154
|
-
const TError = `ResponseErrorConfig<${typeSchemas.errors?.map((item) => item.name).join(' | ') || 'Error'}>`
|
|
112
|
+
const mutationKeyParamsNode = MutationKey.getParams()
|
|
113
|
+
const mutationKeyParamsCall = callPrinter.print(mutationKeyParamsNode) ?? ''
|
|
155
114
|
|
|
156
|
-
const
|
|
115
|
+
const clientCallParamsNode = ast.createOperationParams(node, {
|
|
116
|
+
paramsType,
|
|
117
|
+
pathParamsType: paramsType === 'object' ? 'object' : pathParamsType === 'object' ? 'object' : 'inline',
|
|
118
|
+
paramsCasing,
|
|
119
|
+
resolver: tsResolver,
|
|
120
|
+
extraParams: [
|
|
121
|
+
ast.createFunctionParameter({
|
|
122
|
+
name: 'config',
|
|
123
|
+
type: ast.createParamsType({
|
|
124
|
+
variant: 'reference',
|
|
125
|
+
name: node.requestBody?.content?.[0]?.schema
|
|
126
|
+
? `Partial<RequestConfig<${tsResolver.resolveDataName(node)}>> & { client?: Client }`
|
|
127
|
+
: 'Partial<RequestConfig> & { client?: Client }',
|
|
128
|
+
}),
|
|
129
|
+
default: '{}',
|
|
130
|
+
}),
|
|
131
|
+
],
|
|
132
|
+
})
|
|
133
|
+
const clientCallStr = callPrinter.print(clientCallParamsNode) ?? ''
|
|
134
|
+
|
|
135
|
+
const paramsNode = getParams(node, { paramsCasing, dataReturnType, resolver: tsResolver })
|
|
136
|
+
const paramsSignature = declarationPrinter.print(paramsNode) ?? ''
|
|
157
137
|
|
|
158
138
|
return (
|
|
159
139
|
<File.Source name={name} isExportable isIndexable>
|
|
160
|
-
<Function
|
|
161
|
-
name={name}
|
|
162
|
-
export
|
|
163
|
-
params={params.toConstructor()}
|
|
164
|
-
JSDoc={{
|
|
165
|
-
comments: getComments(operation),
|
|
166
|
-
}}
|
|
167
|
-
generics={['TContext']}
|
|
168
|
-
>
|
|
140
|
+
<Function name={name} export params={paramsSignature} JSDoc={{ comments: getComments(node) }} generics={['TContext']}>
|
|
169
141
|
{`
|
|
170
142
|
const { mutation = {}, client: config = {} } = options ?? {}
|
|
171
143
|
const { client: queryClient, ...mutationOptions } = mutation;
|
|
172
|
-
const mutationKey = mutationOptions?.mutationKey ?? ${mutationKeyName}(${
|
|
144
|
+
const mutationKey = mutationOptions?.mutationKey ?? ${mutationKeyName}(${mutationKeyParamsCall})
|
|
173
145
|
|
|
174
146
|
return useMutation<${generics}>({
|
|
175
|
-
mutationFn: async(${
|
|
176
|
-
return ${clientName}(${
|
|
147
|
+
mutationFn: async(${hasMutationParams ? `{ ${argKeysStr} }` : ''}) => {
|
|
148
|
+
return ${clientName}(${clientCallStr})
|
|
177
149
|
},
|
|
178
150
|
mutationKey,
|
|
179
151
|
...mutationOptions
|
|
@@ -183,3 +155,5 @@ export function Mutation({
|
|
|
183
155
|
</File.Source>
|
|
184
156
|
)
|
|
185
157
|
}
|
|
158
|
+
|
|
159
|
+
Mutation.getParams = getParams
|