@kubb/plugin-react-query 5.0.0-alpha.9 → 5.0.0-beta.10
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 +34 -85
- package/dist/components-Dow6tde8.js +1459 -0
- package/dist/components-Dow6tde8.js.map +1 -0
- package/dist/components-HwdCDefj.cjs +1603 -0
- package/dist/components-HwdCDefj.cjs.map +1 -0
- package/dist/components.cjs +1 -1
- package/dist/components.d.ts +49 -179
- package/dist/components.js +1 -1
- package/dist/generators-CcOmnTPa.cjs +1454 -0
- package/dist/generators-CcOmnTPa.cjs.map +1 -0
- package/dist/generators-yfZr_qfT.js +1412 -0
- package/dist/generators-yfZr_qfT.js.map +1 -0
- package/dist/generators.cjs +1 -1
- package/dist/generators.d.ts +9 -505
- package/dist/generators.js +1 -1
- package/dist/index.cjs +197 -126
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.js +193 -126
- package/dist/index.js.map +1 -1
- package/dist/types-DG_OxOym.d.ts +363 -0
- package/extension.yaml +911 -0
- package/package.json +59 -64
- package/src/components/InfiniteQuery.tsx +79 -138
- package/src/components/InfiniteQueryOptions.tsx +55 -166
- package/src/components/Mutation.tsx +74 -111
- package/src/components/MutationOptions.tsx +61 -80
- package/src/components/Query.tsx +66 -142
- package/src/components/QueryOptions.tsx +56 -138
- package/src/components/SuspenseInfiniteQuery.tsx +79 -138
- package/src/components/SuspenseInfiniteQueryOptions.tsx +55 -166
- package/src/components/SuspenseQuery.tsx +66 -152
- package/src/generators/customHookOptionsFileGenerator.tsx +37 -51
- package/src/generators/hookOptionsGenerator.tsx +111 -174
- package/src/generators/infiniteQueryGenerator.tsx +158 -178
- package/src/generators/mutationGenerator.tsx +112 -139
- package/src/generators/queryGenerator.tsx +128 -142
- package/src/generators/suspenseInfiniteQueryGenerator.tsx +157 -156
- package/src/generators/suspenseQueryGenerator.tsx +126 -152
- package/src/index.ts +1 -1
- package/src/plugin.ts +134 -187
- package/src/resolvers/resolverReactQuery.ts +107 -0
- package/src/types.ts +172 -49
- package/src/utils.ts +10 -0
- package/dist/components-BHQT9ZLc.cjs +0 -1634
- package/dist/components-BHQT9ZLc.cjs.map +0 -1
- package/dist/components-CpyHYGOw.js +0 -1520
- package/dist/components-CpyHYGOw.js.map +0 -1
- package/dist/generators-DP07m3rH.cjs +0 -1469
- package/dist/generators-DP07m3rH.cjs.map +0 -1
- package/dist/generators-DkQwKTc2.js +0 -1427
- package/dist/generators-DkQwKTc2.js.map +0 -1
- package/dist/types-D5S7Ny9r.d.ts +0 -270
|
@@ -1,18 +1,21 @@
|
|
|
1
|
+
import { getOperationParameters } from '@internals/shared'
|
|
1
2
|
import { getNestedAccessor } from '@internals/utils'
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import type { FabricReactNode } from '@kubb/react-fabric/types'
|
|
3
|
+
import type { ast } from '@kubb/core'
|
|
4
|
+
import type { ResolverTs } from '@kubb/plugin-ts'
|
|
5
|
+
import { functionPrinter } from '@kubb/plugin-ts'
|
|
6
|
+
import { File, Function } from '@kubb/renderer-jsx'
|
|
7
|
+
import type { KubbReactNode } from '@kubb/renderer-jsx/types'
|
|
8
8
|
import type { Infinite, PluginReactQuery } from '../types.ts'
|
|
9
|
-
import {
|
|
9
|
+
import { buildQueryKeyParams, resolveErrorNames } from '../utils.ts'
|
|
10
|
+
import { buildEnabledCheck } from '@internals/tanstack-query'
|
|
11
|
+
import { getQueryOptionsParams } from './QueryOptions.tsx'
|
|
10
12
|
|
|
11
13
|
type Props = {
|
|
12
14
|
name: string
|
|
13
15
|
clientName: string
|
|
14
16
|
queryKeyName: string
|
|
15
|
-
|
|
17
|
+
node: ast.OperationNode
|
|
18
|
+
tsResolver: ResolverTs
|
|
16
19
|
paramsCasing: PluginReactQuery['resolvedOptions']['paramsCasing']
|
|
17
20
|
paramsType: PluginReactQuery['resolvedOptions']['paramsType']
|
|
18
21
|
pathParamsType: PluginReactQuery['resolvedOptions']['pathParamsType']
|
|
@@ -24,94 +27,8 @@ type Props = {
|
|
|
24
27
|
queryParam: Infinite['queryParam']
|
|
25
28
|
}
|
|
26
29
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
paramsType: PluginReactQuery['resolvedOptions']['paramsType']
|
|
30
|
-
pathParamsType: PluginReactQuery['resolvedOptions']['pathParamsType']
|
|
31
|
-
typeSchemas: OperationSchemas
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
function getParams({ paramsType, paramsCasing, pathParamsType, typeSchemas }: GetParamsProps) {
|
|
35
|
-
if (paramsType === 'object') {
|
|
36
|
-
const pathParams = getPathParams(typeSchemas.pathParams, { typed: true, casing: paramsCasing })
|
|
37
|
-
|
|
38
|
-
const children = {
|
|
39
|
-
...pathParams,
|
|
40
|
-
data: typeSchemas.request?.name
|
|
41
|
-
? {
|
|
42
|
-
type: typeSchemas.request?.name,
|
|
43
|
-
optional: isOptional(typeSchemas.request?.schema),
|
|
44
|
-
}
|
|
45
|
-
: undefined,
|
|
46
|
-
params: typeSchemas.queryParams?.name
|
|
47
|
-
? {
|
|
48
|
-
type: typeSchemas.queryParams?.name,
|
|
49
|
-
optional: isOptional(typeSchemas.queryParams?.schema),
|
|
50
|
-
}
|
|
51
|
-
: undefined,
|
|
52
|
-
headers: typeSchemas.headerParams?.name
|
|
53
|
-
? {
|
|
54
|
-
type: typeSchemas.headerParams?.name,
|
|
55
|
-
optional: isOptional(typeSchemas.headerParams?.schema),
|
|
56
|
-
}
|
|
57
|
-
: undefined,
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// Check if all children are optional or undefined
|
|
61
|
-
const allChildrenAreOptional = Object.values(children).every((child) => !child || child.optional)
|
|
62
|
-
|
|
63
|
-
return FunctionParams.factory({
|
|
64
|
-
data: {
|
|
65
|
-
mode: 'object',
|
|
66
|
-
children,
|
|
67
|
-
default: allChildrenAreOptional ? '{}' : undefined,
|
|
68
|
-
},
|
|
69
|
-
config: {
|
|
70
|
-
type: typeSchemas.request?.name
|
|
71
|
-
? `Partial<RequestConfig<${typeSchemas.request?.name}>> & { client?: Client }`
|
|
72
|
-
: 'Partial<RequestConfig> & { client?: Client }',
|
|
73
|
-
default: '{}',
|
|
74
|
-
},
|
|
75
|
-
})
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
return FunctionParams.factory({
|
|
79
|
-
pathParams: typeSchemas.pathParams?.name
|
|
80
|
-
? {
|
|
81
|
-
mode: pathParamsType === 'object' ? 'object' : 'inlineSpread',
|
|
82
|
-
children: getPathParams(typeSchemas.pathParams, {
|
|
83
|
-
typed: true,
|
|
84
|
-
casing: paramsCasing,
|
|
85
|
-
}),
|
|
86
|
-
default: isAllOptional(typeSchemas.pathParams?.schema) ? '{}' : undefined,
|
|
87
|
-
}
|
|
88
|
-
: undefined,
|
|
89
|
-
data: typeSchemas.request?.name
|
|
90
|
-
? {
|
|
91
|
-
type: typeSchemas.request?.name,
|
|
92
|
-
optional: isOptional(typeSchemas.request?.schema),
|
|
93
|
-
}
|
|
94
|
-
: undefined,
|
|
95
|
-
params: typeSchemas.queryParams?.name
|
|
96
|
-
? {
|
|
97
|
-
type: typeSchemas.queryParams?.name,
|
|
98
|
-
optional: isOptional(typeSchemas.queryParams?.schema),
|
|
99
|
-
}
|
|
100
|
-
: undefined,
|
|
101
|
-
headers: typeSchemas.headerParams?.name
|
|
102
|
-
? {
|
|
103
|
-
type: typeSchemas.headerParams?.name,
|
|
104
|
-
optional: isOptional(typeSchemas.headerParams?.schema),
|
|
105
|
-
}
|
|
106
|
-
: undefined,
|
|
107
|
-
config: {
|
|
108
|
-
type: typeSchemas.request?.name
|
|
109
|
-
? `Partial<RequestConfig<${typeSchemas.request?.name}>> & { client?: Client }`
|
|
110
|
-
: 'Partial<RequestConfig> & { client?: Client }',
|
|
111
|
-
default: '{}',
|
|
112
|
-
},
|
|
113
|
-
})
|
|
114
|
-
}
|
|
30
|
+
const declarationPrinter = functionPrinter({ mode: 'declaration' })
|
|
31
|
+
const callPrinter = functionPrinter({ mode: 'call' })
|
|
115
32
|
|
|
116
33
|
export function SuspenseInfiniteQueryOptions({
|
|
117
34
|
name,
|
|
@@ -120,16 +37,20 @@ export function SuspenseInfiniteQueryOptions({
|
|
|
120
37
|
cursorParam,
|
|
121
38
|
nextParam,
|
|
122
39
|
previousParam,
|
|
123
|
-
|
|
40
|
+
node,
|
|
41
|
+
tsResolver,
|
|
124
42
|
paramsCasing,
|
|
125
43
|
paramsType,
|
|
126
44
|
dataReturnType,
|
|
127
45
|
pathParamsType,
|
|
128
46
|
queryParam,
|
|
129
47
|
queryKeyName,
|
|
130
|
-
}: Props):
|
|
131
|
-
const
|
|
132
|
-
const
|
|
48
|
+
}: Props): KubbReactNode {
|
|
49
|
+
const responseName = tsResolver.resolveResponseName(node)
|
|
50
|
+
const queryFnDataType = dataReturnType === 'data' ? responseName : `ResponseConfig<${responseName}>`
|
|
51
|
+
const errorNames = resolveErrorNames(node, tsResolver)
|
|
52
|
+
const errorType = `ResponseErrorConfig<${errorNames.length > 0 ? errorNames.join(' | ') : 'Error'}>`
|
|
53
|
+
|
|
133
54
|
const isInitialPageParamDefined = initialPageParam !== undefined && initialPageParam !== null
|
|
134
55
|
const fallbackPageParamType =
|
|
135
56
|
typeof initialPageParam === 'number'
|
|
@@ -144,36 +65,37 @@ export function SuspenseInfiniteQueryOptions({
|
|
|
144
65
|
: typeof initialPageParam === 'boolean'
|
|
145
66
|
? 'boolean'
|
|
146
67
|
: 'unknown'
|
|
147
|
-
|
|
68
|
+
|
|
69
|
+
const rawQueryParams = getOperationParameters(node).query
|
|
70
|
+
const queryParamsTypeName =
|
|
71
|
+
rawQueryParams.length > 0
|
|
72
|
+
? (() => {
|
|
73
|
+
const groupName = tsResolver.resolveQueryParamsName(node, rawQueryParams[0]!)
|
|
74
|
+
const individualName = tsResolver.resolveParamName(node, rawQueryParams[0]!)
|
|
75
|
+
return groupName !== individualName ? groupName : undefined
|
|
76
|
+
})()
|
|
77
|
+
: undefined
|
|
78
|
+
|
|
79
|
+
const queryParamType = queryParam && queryParamsTypeName ? `${queryParamsTypeName}['${queryParam}']` : undefined
|
|
148
80
|
const pageParamType = queryParamType ? (isInitialPageParamDefined ? `NonNullable<${queryParamType}>` : queryParamType) : fallbackPageParamType
|
|
149
81
|
|
|
150
|
-
const
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
})
|
|
156
|
-
const
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
pathParamsType,
|
|
161
|
-
isConfigurable: true,
|
|
162
|
-
})
|
|
163
|
-
const queryKeyParams = QueryKey.getParams({
|
|
164
|
-
pathParamsType,
|
|
165
|
-
typeSchemas,
|
|
166
|
-
paramsCasing,
|
|
167
|
-
})
|
|
82
|
+
const paramsNode = getQueryOptionsParams(node, { paramsType, paramsCasing, pathParamsType, resolver: tsResolver })
|
|
83
|
+
const paramsSignature = declarationPrinter.print(paramsNode) ?? ''
|
|
84
|
+
const rawParamsCall = callPrinter.print(paramsNode) ?? ''
|
|
85
|
+
const clientCallStr = rawParamsCall.replace(/\bconfig\b(?=[^,]*$)/, '{ ...config, signal: config.signal ?? signal }')
|
|
86
|
+
|
|
87
|
+
const queryKeyParamsNode = buildQueryKeyParams(node, { pathParamsType, paramsCasing, resolver: tsResolver })
|
|
88
|
+
const queryKeyParamsCall = callPrinter.print(queryKeyParamsNode) ?? ''
|
|
89
|
+
|
|
90
|
+
const enabledSource = buildEnabledCheck(queryKeyParamsNode)
|
|
91
|
+
const enabledText = enabledSource ? `enabled: !!(${enabledSource}),` : ''
|
|
168
92
|
|
|
169
|
-
// Determine if we should use the new nextParam/previousParam or fall back to legacy cursorParam behavior
|
|
170
93
|
const hasNewParams = nextParam !== undefined || previousParam !== undefined
|
|
171
94
|
|
|
172
95
|
let getNextPageParamExpr: string | undefined
|
|
173
96
|
let getPreviousPageParamExpr: string | undefined
|
|
174
97
|
|
|
175
98
|
if (hasNewParams) {
|
|
176
|
-
// Use the new nextParam and previousParam
|
|
177
99
|
if (nextParam) {
|
|
178
100
|
const accessor = getNestedAccessor(nextParam, 'lastPage')
|
|
179
101
|
if (accessor) {
|
|
@@ -187,11 +109,9 @@ export function SuspenseInfiniteQueryOptions({
|
|
|
187
109
|
}
|
|
188
110
|
}
|
|
189
111
|
} else if (cursorParam) {
|
|
190
|
-
// Legacy behavior: use cursorParam for both next and previous
|
|
191
112
|
getNextPageParamExpr = `getNextPageParam: (lastPage) => lastPage['${cursorParam}']`
|
|
192
113
|
getPreviousPageParamExpr = `getPreviousPageParam: (firstPage) => firstPage['${cursorParam}']`
|
|
193
114
|
} else {
|
|
194
|
-
// Fallback behavior: page-based pagination
|
|
195
115
|
if (dataReturnType === 'full') {
|
|
196
116
|
getNextPageParamExpr =
|
|
197
117
|
'getNextPageParam: (lastPage, _allPages, lastPageParam) => Array.isArray(lastPage.data) && lastPage.data.length === 0 ? undefined : lastPageParam + 1'
|
|
@@ -202,56 +122,35 @@ export function SuspenseInfiniteQueryOptions({
|
|
|
202
122
|
getPreviousPageParamExpr = 'getPreviousPageParam: (_firstPage, _allPages, firstPageParam) => firstPageParam <= 1 ? undefined : firstPageParam - 1'
|
|
203
123
|
}
|
|
204
124
|
|
|
205
|
-
const
|
|
125
|
+
const queryOptionsArr = [
|
|
206
126
|
`initialPageParam: ${typeof initialPageParam === 'string' ? JSON.stringify(initialPageParam) : initialPageParam}`,
|
|
207
127
|
getNextPageParamExpr,
|
|
208
128
|
getPreviousPageParamExpr,
|
|
209
129
|
].filter(Boolean)
|
|
210
130
|
|
|
211
131
|
const infiniteOverrideParams =
|
|
212
|
-
queryParam &&
|
|
132
|
+
queryParam && queryParamsTypeName
|
|
213
133
|
? `
|
|
214
134
|
params = {
|
|
215
135
|
...(params ?? {}),
|
|
216
|
-
['${queryParam}']: pageParam as unknown as ${
|
|
217
|
-
} as ${
|
|
136
|
+
['${queryParam}']: pageParam as unknown as ${queryParamsTypeName}['${queryParam}'],
|
|
137
|
+
} as ${queryParamsTypeName}`
|
|
218
138
|
: ''
|
|
219
139
|
|
|
220
|
-
// Only add enabled check for required (non-optional) parameters
|
|
221
|
-
// Optional parameters with defaults should not prevent query execution
|
|
222
|
-
const enabled = Object.entries(queryKeyParams.flatParams)
|
|
223
|
-
.map(([key, item]) => {
|
|
224
|
-
// Only include if the parameter exists and is NOT optional
|
|
225
|
-
// This ensures we only check required parameters
|
|
226
|
-
return item && !item.optional && !item.default ? key : undefined
|
|
227
|
-
})
|
|
228
|
-
.filter(Boolean)
|
|
229
|
-
.join('&& ')
|
|
230
|
-
|
|
231
|
-
const enabledText = enabled ? `enabled: !!(${enabled}),` : ''
|
|
232
|
-
|
|
233
140
|
if (infiniteOverrideParams) {
|
|
234
141
|
return (
|
|
235
142
|
<File.Source name={name} isExportable isIndexable>
|
|
236
|
-
<Function name={name} export params={
|
|
143
|
+
<Function name={name} export params={paramsSignature}>
|
|
237
144
|
{`
|
|
238
|
-
const queryKey = ${queryKeyName}(${
|
|
145
|
+
const queryKey = ${queryKeyName}(${queryKeyParamsCall})
|
|
239
146
|
return infiniteQueryOptions<${queryFnDataType}, ${errorType}, InfiniteData<${queryFnDataType}>, typeof queryKey, ${pageParamType}>({
|
|
240
147
|
${enabledText}
|
|
241
148
|
queryKey,
|
|
242
149
|
queryFn: async ({ signal, pageParam }) => {
|
|
243
150
|
${infiniteOverrideParams}
|
|
244
|
-
return ${clientName}(${
|
|
245
|
-
transformName(name) {
|
|
246
|
-
if (name === 'config') {
|
|
247
|
-
return '{ ...config, signal: config.signal ?? signal }'
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
return name
|
|
251
|
-
},
|
|
252
|
-
})})
|
|
151
|
+
return ${clientName}(${clientCallStr})
|
|
253
152
|
},
|
|
254
|
-
${
|
|
153
|
+
${queryOptionsArr.join(',\n')}
|
|
255
154
|
})
|
|
256
155
|
`}
|
|
257
156
|
</Function>
|
|
@@ -261,29 +160,19 @@ export function SuspenseInfiniteQueryOptions({
|
|
|
261
160
|
|
|
262
161
|
return (
|
|
263
162
|
<File.Source name={name} isExportable isIndexable>
|
|
264
|
-
<Function name={name} export params={
|
|
163
|
+
<Function name={name} export params={paramsSignature}>
|
|
265
164
|
{`
|
|
266
|
-
const queryKey = ${queryKeyName}(${
|
|
165
|
+
const queryKey = ${queryKeyName}(${queryKeyParamsCall})
|
|
267
166
|
return infiniteQueryOptions<${queryFnDataType}, ${errorType}, InfiniteData<${queryFnDataType}>, typeof queryKey, ${pageParamType}>({
|
|
268
167
|
${enabledText}
|
|
269
168
|
queryKey,
|
|
270
169
|
queryFn: async ({ signal }) => {
|
|
271
|
-
return ${clientName}(${
|
|
272
|
-
transformName(name) {
|
|
273
|
-
if (name === 'config') {
|
|
274
|
-
return '{ ...config, signal: config.signal ?? signal }'
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
return name
|
|
278
|
-
},
|
|
279
|
-
})})
|
|
170
|
+
return ${clientName}(${clientCallStr})
|
|
280
171
|
},
|
|
281
|
-
${
|
|
172
|
+
${queryOptionsArr.join(',\n')}
|
|
282
173
|
})
|
|
283
174
|
`}
|
|
284
175
|
</Function>
|
|
285
176
|
</File.Source>
|
|
286
177
|
)
|
|
287
178
|
}
|
|
288
|
-
|
|
289
|
-
SuspenseInfiniteQueryOptions.getParams = getParams
|
|
@@ -1,22 +1,19 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import type {
|
|
3
|
-
import {
|
|
4
|
-
import { File, Function
|
|
5
|
-
import type {
|
|
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'
|
|
6
6
|
import type { PluginReactQuery } from '../types.ts'
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
7
|
+
import { buildQueryKeyParams, getComments, resolveErrorNames } from '../utils.ts'
|
|
8
|
+
import { getQueryOptionsParams } from './QueryOptions.tsx'
|
|
9
9
|
|
|
10
10
|
type Props = {
|
|
11
|
-
/**
|
|
12
|
-
* Name of the function
|
|
13
|
-
*/
|
|
14
11
|
name: string
|
|
15
12
|
queryOptionsName: string
|
|
16
13
|
queryKeyName: string
|
|
17
14
|
queryKeyTypeName: string
|
|
18
|
-
|
|
19
|
-
|
|
15
|
+
node: ast.OperationNode
|
|
16
|
+
tsResolver: ResolverTs
|
|
20
17
|
paramsCasing: PluginReactQuery['resolvedOptions']['paramsCasing']
|
|
21
18
|
paramsType: PluginReactQuery['resolvedOptions']['paramsType']
|
|
22
19
|
pathParamsType: PluginReactQuery['resolvedOptions']['pathParamsType']
|
|
@@ -24,112 +21,48 @@ type Props = {
|
|
|
24
21
|
customOptions: PluginReactQuery['resolvedOptions']['customOptions']
|
|
25
22
|
}
|
|
26
23
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
optional: isOptional(typeSchemas.queryParams?.schema),
|
|
54
|
-
}
|
|
55
|
-
: undefined,
|
|
56
|
-
headers: typeSchemas.headerParams?.name
|
|
57
|
-
? {
|
|
58
|
-
type: typeSchemas.headerParams?.name,
|
|
59
|
-
optional: isOptional(typeSchemas.headerParams?.schema),
|
|
60
|
-
}
|
|
61
|
-
: undefined,
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
// Check if all children are optional or undefined
|
|
65
|
-
const allChildrenAreOptional = Object.values(children).every((child) => !child || child.optional)
|
|
66
|
-
|
|
67
|
-
return FunctionParams.factory({
|
|
68
|
-
data: {
|
|
69
|
-
mode: 'object',
|
|
70
|
-
children,
|
|
71
|
-
default: allChildrenAreOptional ? '{}' : undefined,
|
|
72
|
-
},
|
|
73
|
-
options: {
|
|
74
|
-
type: `
|
|
75
|
-
{
|
|
24
|
+
const declarationPrinter = functionPrinter({ mode: 'declaration' })
|
|
25
|
+
const callPrinter = functionPrinter({ mode: 'call' })
|
|
26
|
+
|
|
27
|
+
function buildSuspenseQueryParamsNode(
|
|
28
|
+
node: ast.OperationNode,
|
|
29
|
+
options: {
|
|
30
|
+
paramsType: PluginReactQuery['resolvedOptions']['paramsType']
|
|
31
|
+
paramsCasing: PluginReactQuery['resolvedOptions']['paramsCasing']
|
|
32
|
+
pathParamsType: PluginReactQuery['resolvedOptions']['pathParamsType']
|
|
33
|
+
dataReturnType: PluginReactQuery['resolvedOptions']['client']['dataReturnType']
|
|
34
|
+
resolver: ResolverTs
|
|
35
|
+
},
|
|
36
|
+
): ast.FunctionParametersNode {
|
|
37
|
+
const { paramsType, paramsCasing, pathParamsType, dataReturnType, resolver } = options
|
|
38
|
+
const responseName = resolver.resolveResponseName(node)
|
|
39
|
+
const requestName = node.requestBody?.content?.[0]?.schema ? resolver.resolveDataName(node) : undefined
|
|
40
|
+
const errorNames = resolveErrorNames(node, resolver)
|
|
41
|
+
|
|
42
|
+
const TData = dataReturnType === 'data' ? responseName : `ResponseConfig<${responseName}>`
|
|
43
|
+
const TError = `ResponseErrorConfig<${errorNames.length > 0 ? errorNames.join(' | ') : 'Error'}>`
|
|
44
|
+
|
|
45
|
+
const optionsParam = ast.createFunctionParameter({
|
|
46
|
+
name: 'options',
|
|
47
|
+
type: ast.createParamsType({
|
|
48
|
+
variant: 'reference',
|
|
49
|
+
name: `{
|
|
76
50
|
query?: Partial<UseSuspenseQueryOptions<${[TData, TError, 'TData', 'TQueryKey'].join(', ')}>> & { client?: QueryClient },
|
|
77
|
-
client?: ${
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
})
|
|
83
|
-
}
|
|
51
|
+
client?: ${requestName ? `Partial<RequestConfig<${requestName}>> & { client?: Client }` : 'Partial<RequestConfig> & { client?: Client }'}
|
|
52
|
+
}`,
|
|
53
|
+
}),
|
|
54
|
+
default: '{}',
|
|
55
|
+
})
|
|
84
56
|
|
|
85
|
-
return
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
casing: paramsCasing,
|
|
92
|
-
}),
|
|
93
|
-
default: isAllOptional(typeSchemas.pathParams?.schema) ? '{}' : undefined,
|
|
94
|
-
}
|
|
95
|
-
: undefined,
|
|
96
|
-
data: typeSchemas.request?.name
|
|
97
|
-
? {
|
|
98
|
-
type: typeSchemas.request?.name,
|
|
99
|
-
optional: isOptional(typeSchemas.request?.schema),
|
|
100
|
-
}
|
|
101
|
-
: undefined,
|
|
102
|
-
params: typeSchemas.queryParams?.name
|
|
103
|
-
? {
|
|
104
|
-
type: typeSchemas.queryParams?.name,
|
|
105
|
-
optional: isOptional(typeSchemas.queryParams?.schema),
|
|
106
|
-
}
|
|
107
|
-
: undefined,
|
|
108
|
-
headers: typeSchemas.headerParams?.name
|
|
109
|
-
? {
|
|
110
|
-
type: typeSchemas.headerParams?.name,
|
|
111
|
-
optional: isOptional(typeSchemas.headerParams?.schema),
|
|
112
|
-
}
|
|
113
|
-
: undefined,
|
|
114
|
-
options: {
|
|
115
|
-
type: `
|
|
116
|
-
{
|
|
117
|
-
query?: Partial<UseSuspenseQueryOptions<${[TData, TError, 'TData', 'TQueryKey'].join(', ')}>> & { client?: QueryClient },
|
|
118
|
-
client?: ${typeSchemas.request?.name ? `Partial<RequestConfig<${typeSchemas.request?.name}>> & { client?: Client }` : 'Partial<RequestConfig> & { client?: Client }'}
|
|
119
|
-
}
|
|
120
|
-
`,
|
|
121
|
-
default: '{}',
|
|
122
|
-
},
|
|
57
|
+
return ast.createOperationParams(node, {
|
|
58
|
+
paramsType,
|
|
59
|
+
pathParamsType: paramsType === 'object' ? 'object' : pathParamsType === 'object' ? 'object' : 'inline',
|
|
60
|
+
paramsCasing,
|
|
61
|
+
resolver,
|
|
62
|
+
extraParams: [optionsParam],
|
|
123
63
|
})
|
|
124
64
|
}
|
|
125
65
|
|
|
126
|
-
/**
|
|
127
|
-
* Generates a strongly-typed React Query Suspense hook function for an OpenAPI operation.
|
|
128
|
-
*
|
|
129
|
-
* The generated function wraps `useSuspenseQuery`, providing type-safe parameters and return types based on the supplied OpenAPI schemas and configuration.
|
|
130
|
-
*
|
|
131
|
-
* @returns A React component source node containing the generated query function.
|
|
132
|
-
*/
|
|
133
66
|
export function SuspenseQuery({
|
|
134
67
|
name,
|
|
135
68
|
queryKeyTypeName,
|
|
@@ -139,55 +72,38 @@ export function SuspenseQuery({
|
|
|
139
72
|
paramsCasing,
|
|
140
73
|
pathParamsType,
|
|
141
74
|
dataReturnType,
|
|
142
|
-
|
|
143
|
-
|
|
75
|
+
node,
|
|
76
|
+
tsResolver,
|
|
144
77
|
customOptions,
|
|
145
|
-
}: Props):
|
|
146
|
-
const
|
|
147
|
-
const
|
|
148
|
-
|
|
78
|
+
}: Props): KubbReactNode {
|
|
79
|
+
const responseName = tsResolver.resolveResponseName(node)
|
|
80
|
+
const errorNames = resolveErrorNames(node, tsResolver)
|
|
81
|
+
|
|
82
|
+
const TData = dataReturnType === 'data' ? responseName : `ResponseConfig<${responseName}>`
|
|
83
|
+
const TError = `ResponseErrorConfig<${errorNames.length > 0 ? errorNames.join(' | ') : 'Error'}>`
|
|
84
|
+
const returnType = `UseSuspenseQueryResult<${'TData'}, ${TError}> & { queryKey: TQueryKey }`
|
|
149
85
|
const generics = [`TData = ${TData}`, `TQueryKey extends QueryKey = ${queryKeyTypeName}`]
|
|
150
86
|
|
|
151
|
-
const
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
const queryOptionsParams = QueryOptions.getParams({
|
|
157
|
-
paramsCasing,
|
|
158
|
-
paramsType,
|
|
159
|
-
pathParamsType,
|
|
160
|
-
typeSchemas,
|
|
161
|
-
})
|
|
162
|
-
const params = getParams({
|
|
163
|
-
paramsCasing,
|
|
164
|
-
paramsType,
|
|
165
|
-
pathParamsType,
|
|
166
|
-
dataReturnType,
|
|
167
|
-
typeSchemas,
|
|
168
|
-
})
|
|
87
|
+
const queryKeyParamsNode = buildQueryKeyParams(node, { pathParamsType, paramsCasing, resolver: tsResolver })
|
|
88
|
+
const queryKeyParamsCall = callPrinter.print(queryKeyParamsNode) ?? ''
|
|
89
|
+
|
|
90
|
+
const queryOptionsParamsNode = getQueryOptionsParams(node, { paramsType, paramsCasing, pathParamsType, resolver: tsResolver })
|
|
91
|
+
const queryOptionsParamsCall = callPrinter.print(queryOptionsParamsNode) ?? ''
|
|
169
92
|
|
|
170
|
-
const
|
|
93
|
+
const paramsNode = buildSuspenseQueryParamsNode(node, { paramsType, paramsCasing, pathParamsType, dataReturnType, resolver: tsResolver })
|
|
94
|
+
const paramsSignature = declarationPrinter.print(paramsNode) ?? ''
|
|
171
95
|
|
|
172
96
|
return (
|
|
173
97
|
<File.Source name={name} isExportable isIndexable>
|
|
174
|
-
<Function
|
|
175
|
-
name={name}
|
|
176
|
-
export
|
|
177
|
-
generics={generics.join(', ')}
|
|
178
|
-
params={params.toConstructor()}
|
|
179
|
-
JSDoc={{
|
|
180
|
-
comments: getComments(operation),
|
|
181
|
-
}}
|
|
182
|
-
>
|
|
98
|
+
<Function name={name} export generics={generics.join(', ')} params={paramsSignature} returnType={undefined} JSDoc={{ comments: getComments(node) }}>
|
|
183
99
|
{`
|
|
184
100
|
const { query: queryConfig = {}, client: config = {} } = options ?? {}
|
|
185
101
|
const { client: queryClient, ...resolvedOptions } = queryConfig
|
|
186
|
-
const queryKey = resolvedOptions?.queryKey ?? ${queryKeyName}(${
|
|
187
|
-
${customOptions ? `const customOptions = ${customOptions.name}({ hookName: '${name}', operationId: '${
|
|
102
|
+
const queryKey = resolvedOptions?.queryKey ?? ${queryKeyName}(${queryKeyParamsCall})
|
|
103
|
+
${customOptions ? `const customOptions = ${customOptions.name}({ hookName: '${name}', operationId: '${node.operationId}' })` : ''}
|
|
188
104
|
|
|
189
105
|
const query = useSuspenseQuery({
|
|
190
|
-
...${
|
|
106
|
+
...${queryOptionsName}(${queryOptionsParamsCall}),${customOptions ? '\n...customOptions,' : ''}
|
|
191
107
|
...resolvedOptions,
|
|
192
108
|
queryKey,
|
|
193
109
|
} as unknown as UseSuspenseQueryOptions, queryClient) as ${returnType}
|
|
@@ -200,5 +116,3 @@ export function SuspenseQuery({
|
|
|
200
116
|
</File.Source>
|
|
201
117
|
)
|
|
202
118
|
}
|
|
203
|
-
|
|
204
|
-
SuspenseQuery.getParams = getParams
|