@kubb/plugin-react-query 5.0.0-alpha.9 → 5.0.0-beta.100
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 +38 -93
- package/dist/index.cjs +2317 -149
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +494 -6
- package/dist/index.js +2283 -143
- package/dist/index.js.map +1 -1
- package/package.json +47 -75
- 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/components.cjs +0 -13
- package/dist/components.d.ts +0 -398
- package/dist/components.js +0 -2
- 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/generators.cjs +0 -9
- package/dist/generators.d.ts +0 -523
- package/dist/generators.js +0 -2
- package/dist/types-D5S7Ny9r.d.ts +0 -270
- package/src/components/InfiniteQuery.tsx +0 -220
- package/src/components/InfiniteQueryOptions.tsx +0 -289
- package/src/components/Mutation.tsx +0 -158
- package/src/components/MutationKey.tsx +0 -1
- package/src/components/MutationOptions.tsx +0 -122
- package/src/components/Query.tsx +0 -194
- package/src/components/QueryKey.tsx +0 -1
- package/src/components/QueryOptions.tsx +0 -181
- package/src/components/SuspenseInfiniteQuery.tsx +0 -220
- package/src/components/SuspenseInfiniteQueryOptions.tsx +0 -289
- package/src/components/SuspenseQuery.tsx +0 -204
- package/src/components/index.ts +0 -11
- package/src/generators/customHookOptionsFileGenerator.tsx +0 -98
- package/src/generators/hookOptionsGenerator.tsx +0 -196
- package/src/generators/index.ts +0 -7
- package/src/generators/infiniteQueryGenerator.tsx +0 -214
- package/src/generators/mutationGenerator.tsx +0 -195
- package/src/generators/queryGenerator.tsx +0 -194
- package/src/generators/suspenseInfiniteQueryGenerator.tsx +0 -202
- package/src/generators/suspenseQueryGenerator.tsx +0 -207
- package/src/index.ts +0 -2
- package/src/plugin.ts +0 -239
- package/src/types.ts +0 -205
- /package/dist/{chunk--u3MIqq1.js → rolldown-runtime-C0LytTxp.js} +0 -0
|
@@ -1,289 +0,0 @@
|
|
|
1
|
-
import { getNestedAccessor } from '@internals/utils'
|
|
2
|
-
import { isAllOptional, isOptional } from '@kubb/oas'
|
|
3
|
-
import { Client } from '@kubb/plugin-client/components'
|
|
4
|
-
import type { OperationSchemas } from '@kubb/plugin-oas'
|
|
5
|
-
import { getPathParams } from '@kubb/plugin-oas/utils'
|
|
6
|
-
import { File, Function, FunctionParams } from '@kubb/react-fabric'
|
|
7
|
-
import type { FabricReactNode } from '@kubb/react-fabric/types'
|
|
8
|
-
import type { Infinite, PluginReactQuery } from '../types.ts'
|
|
9
|
-
import { QueryKey } from './QueryKey.tsx'
|
|
10
|
-
|
|
11
|
-
type Props = {
|
|
12
|
-
name: string
|
|
13
|
-
clientName: string
|
|
14
|
-
queryKeyName: string
|
|
15
|
-
typeSchemas: OperationSchemas
|
|
16
|
-
paramsCasing: PluginReactQuery['resolvedOptions']['paramsCasing']
|
|
17
|
-
paramsType: PluginReactQuery['resolvedOptions']['paramsType']
|
|
18
|
-
pathParamsType: PluginReactQuery['resolvedOptions']['pathParamsType']
|
|
19
|
-
dataReturnType: PluginReactQuery['resolvedOptions']['client']['dataReturnType']
|
|
20
|
-
initialPageParam: Infinite['initialPageParam']
|
|
21
|
-
cursorParam: Infinite['cursorParam']
|
|
22
|
-
nextParam: Infinite['nextParam']
|
|
23
|
-
previousParam: Infinite['previousParam']
|
|
24
|
-
queryParam: Infinite['queryParam']
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
type GetParamsProps = {
|
|
28
|
-
paramsCasing: PluginReactQuery['resolvedOptions']['paramsCasing']
|
|
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
|
-
}
|
|
115
|
-
|
|
116
|
-
export function SuspenseInfiniteQueryOptions({
|
|
117
|
-
name,
|
|
118
|
-
clientName,
|
|
119
|
-
initialPageParam,
|
|
120
|
-
cursorParam,
|
|
121
|
-
nextParam,
|
|
122
|
-
previousParam,
|
|
123
|
-
typeSchemas,
|
|
124
|
-
paramsCasing,
|
|
125
|
-
paramsType,
|
|
126
|
-
dataReturnType,
|
|
127
|
-
pathParamsType,
|
|
128
|
-
queryParam,
|
|
129
|
-
queryKeyName,
|
|
130
|
-
}: Props): FabricReactNode {
|
|
131
|
-
const queryFnDataType = dataReturnType === 'data' ? typeSchemas.response.name : `ResponseConfig<${typeSchemas.response.name}>`
|
|
132
|
-
const errorType = `ResponseErrorConfig<${typeSchemas.errors?.map((item) => item.name).join(' | ') || 'Error'}>`
|
|
133
|
-
const isInitialPageParamDefined = initialPageParam !== undefined && initialPageParam !== null
|
|
134
|
-
const fallbackPageParamType =
|
|
135
|
-
typeof initialPageParam === 'number'
|
|
136
|
-
? 'number'
|
|
137
|
-
: typeof initialPageParam === 'string'
|
|
138
|
-
? initialPageParam.includes(' as ')
|
|
139
|
-
? (() => {
|
|
140
|
-
const parts = initialPageParam.split(' as ')
|
|
141
|
-
return parts[parts.length - 1] ?? 'unknown'
|
|
142
|
-
})()
|
|
143
|
-
: 'string'
|
|
144
|
-
: typeof initialPageParam === 'boolean'
|
|
145
|
-
? 'boolean'
|
|
146
|
-
: 'unknown'
|
|
147
|
-
const queryParamType = queryParam && typeSchemas.queryParams?.name ? `${typeSchemas.queryParams?.name}['${queryParam}']` : undefined
|
|
148
|
-
const pageParamType = queryParamType ? (isInitialPageParamDefined ? `NonNullable<${queryParamType}>` : queryParamType) : fallbackPageParamType
|
|
149
|
-
|
|
150
|
-
const params = getParams({
|
|
151
|
-
paramsType,
|
|
152
|
-
paramsCasing,
|
|
153
|
-
pathParamsType,
|
|
154
|
-
typeSchemas,
|
|
155
|
-
})
|
|
156
|
-
const clientParams = Client.getParams({
|
|
157
|
-
paramsCasing,
|
|
158
|
-
typeSchemas,
|
|
159
|
-
paramsType,
|
|
160
|
-
pathParamsType,
|
|
161
|
-
isConfigurable: true,
|
|
162
|
-
})
|
|
163
|
-
const queryKeyParams = QueryKey.getParams({
|
|
164
|
-
pathParamsType,
|
|
165
|
-
typeSchemas,
|
|
166
|
-
paramsCasing,
|
|
167
|
-
})
|
|
168
|
-
|
|
169
|
-
// Determine if we should use the new nextParam/previousParam or fall back to legacy cursorParam behavior
|
|
170
|
-
const hasNewParams = nextParam !== undefined || previousParam !== undefined
|
|
171
|
-
|
|
172
|
-
let getNextPageParamExpr: string | undefined
|
|
173
|
-
let getPreviousPageParamExpr: string | undefined
|
|
174
|
-
|
|
175
|
-
if (hasNewParams) {
|
|
176
|
-
// Use the new nextParam and previousParam
|
|
177
|
-
if (nextParam) {
|
|
178
|
-
const accessor = getNestedAccessor(nextParam, 'lastPage')
|
|
179
|
-
if (accessor) {
|
|
180
|
-
getNextPageParamExpr = `getNextPageParam: (lastPage) => ${accessor}`
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
if (previousParam) {
|
|
184
|
-
const accessor = getNestedAccessor(previousParam, 'firstPage')
|
|
185
|
-
if (accessor) {
|
|
186
|
-
getPreviousPageParamExpr = `getPreviousPageParam: (firstPage) => ${accessor}`
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
} else if (cursorParam) {
|
|
190
|
-
// Legacy behavior: use cursorParam for both next and previous
|
|
191
|
-
getNextPageParamExpr = `getNextPageParam: (lastPage) => lastPage['${cursorParam}']`
|
|
192
|
-
getPreviousPageParamExpr = `getPreviousPageParam: (firstPage) => firstPage['${cursorParam}']`
|
|
193
|
-
} else {
|
|
194
|
-
// Fallback behavior: page-based pagination
|
|
195
|
-
if (dataReturnType === 'full') {
|
|
196
|
-
getNextPageParamExpr =
|
|
197
|
-
'getNextPageParam: (lastPage, _allPages, lastPageParam) => Array.isArray(lastPage.data) && lastPage.data.length === 0 ? undefined : lastPageParam + 1'
|
|
198
|
-
} else {
|
|
199
|
-
getNextPageParamExpr =
|
|
200
|
-
'getNextPageParam: (lastPage, _allPages, lastPageParam) => Array.isArray(lastPage) && lastPage.length === 0 ? undefined : lastPageParam + 1'
|
|
201
|
-
}
|
|
202
|
-
getPreviousPageParamExpr = 'getPreviousPageParam: (_firstPage, _allPages, firstPageParam) => firstPageParam <= 1 ? undefined : firstPageParam - 1'
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
const queryOptions = [
|
|
206
|
-
`initialPageParam: ${typeof initialPageParam === 'string' ? JSON.stringify(initialPageParam) : initialPageParam}`,
|
|
207
|
-
getNextPageParamExpr,
|
|
208
|
-
getPreviousPageParamExpr,
|
|
209
|
-
].filter(Boolean)
|
|
210
|
-
|
|
211
|
-
const infiniteOverrideParams =
|
|
212
|
-
queryParam && typeSchemas.queryParams?.name
|
|
213
|
-
? `
|
|
214
|
-
params = {
|
|
215
|
-
...(params ?? {}),
|
|
216
|
-
['${queryParam}']: pageParam as unknown as ${typeSchemas.queryParams?.name}['${queryParam}'],
|
|
217
|
-
} as ${typeSchemas.queryParams?.name}`
|
|
218
|
-
: ''
|
|
219
|
-
|
|
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
|
-
if (infiniteOverrideParams) {
|
|
234
|
-
return (
|
|
235
|
-
<File.Source name={name} isExportable isIndexable>
|
|
236
|
-
<Function name={name} export params={params.toConstructor()}>
|
|
237
|
-
{`
|
|
238
|
-
const queryKey = ${queryKeyName}(${queryKeyParams.toCall()})
|
|
239
|
-
return infiniteQueryOptions<${queryFnDataType}, ${errorType}, InfiniteData<${queryFnDataType}>, typeof queryKey, ${pageParamType}>({
|
|
240
|
-
${enabledText}
|
|
241
|
-
queryKey,
|
|
242
|
-
queryFn: async ({ signal, pageParam }) => {
|
|
243
|
-
${infiniteOverrideParams}
|
|
244
|
-
return ${clientName}(${clientParams.toCall({
|
|
245
|
-
transformName(name) {
|
|
246
|
-
if (name === 'config') {
|
|
247
|
-
return '{ ...config, signal: config.signal ?? signal }'
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
return name
|
|
251
|
-
},
|
|
252
|
-
})})
|
|
253
|
-
},
|
|
254
|
-
${queryOptions.join(',\n')}
|
|
255
|
-
})
|
|
256
|
-
`}
|
|
257
|
-
</Function>
|
|
258
|
-
</File.Source>
|
|
259
|
-
)
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
return (
|
|
263
|
-
<File.Source name={name} isExportable isIndexable>
|
|
264
|
-
<Function name={name} export params={params.toConstructor()}>
|
|
265
|
-
{`
|
|
266
|
-
const queryKey = ${queryKeyName}(${queryKeyParams.toCall()})
|
|
267
|
-
return infiniteQueryOptions<${queryFnDataType}, ${errorType}, InfiniteData<${queryFnDataType}>, typeof queryKey, ${pageParamType}>({
|
|
268
|
-
${enabledText}
|
|
269
|
-
queryKey,
|
|
270
|
-
queryFn: async ({ signal }) => {
|
|
271
|
-
return ${clientName}(${clientParams.toCall({
|
|
272
|
-
transformName(name) {
|
|
273
|
-
if (name === 'config') {
|
|
274
|
-
return '{ ...config, signal: config.signal ?? signal }'
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
return name
|
|
278
|
-
},
|
|
279
|
-
})})
|
|
280
|
-
},
|
|
281
|
-
${queryOptions.join(',\n')}
|
|
282
|
-
})
|
|
283
|
-
`}
|
|
284
|
-
</Function>
|
|
285
|
-
</File.Source>
|
|
286
|
-
)
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
SuspenseInfiniteQueryOptions.getParams = getParams
|
|
@@ -1,204 +0,0 @@
|
|
|
1
|
-
import { isAllOptional, isOptional, type Operation } from '@kubb/oas'
|
|
2
|
-
import type { OperationSchemas } from '@kubb/plugin-oas'
|
|
3
|
-
import { getComments, getPathParams } from '@kubb/plugin-oas/utils'
|
|
4
|
-
import { File, Function, FunctionParams } from '@kubb/react-fabric'
|
|
5
|
-
import type { FabricReactNode } from '@kubb/react-fabric/types'
|
|
6
|
-
import type { PluginReactQuery } from '../types.ts'
|
|
7
|
-
import { QueryKey } from './QueryKey.tsx'
|
|
8
|
-
import { QueryOptions } from './QueryOptions.tsx'
|
|
9
|
-
|
|
10
|
-
type Props = {
|
|
11
|
-
/**
|
|
12
|
-
* Name of the function
|
|
13
|
-
*/
|
|
14
|
-
name: string
|
|
15
|
-
queryOptionsName: string
|
|
16
|
-
queryKeyName: string
|
|
17
|
-
queryKeyTypeName: string
|
|
18
|
-
typeSchemas: OperationSchemas
|
|
19
|
-
operation: Operation
|
|
20
|
-
paramsCasing: PluginReactQuery['resolvedOptions']['paramsCasing']
|
|
21
|
-
paramsType: PluginReactQuery['resolvedOptions']['paramsType']
|
|
22
|
-
pathParamsType: PluginReactQuery['resolvedOptions']['pathParamsType']
|
|
23
|
-
dataReturnType: PluginReactQuery['resolvedOptions']['client']['dataReturnType']
|
|
24
|
-
customOptions: PluginReactQuery['resolvedOptions']['customOptions']
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
type GetParamsProps = {
|
|
28
|
-
paramsCasing: PluginReactQuery['resolvedOptions']['paramsCasing']
|
|
29
|
-
paramsType: PluginReactQuery['resolvedOptions']['paramsType']
|
|
30
|
-
pathParamsType: PluginReactQuery['resolvedOptions']['pathParamsType']
|
|
31
|
-
dataReturnType: PluginReactQuery['resolvedOptions']['client']['dataReturnType']
|
|
32
|
-
typeSchemas: OperationSchemas
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
function getParams({ paramsType, paramsCasing, pathParamsType, dataReturnType, typeSchemas }: GetParamsProps) {
|
|
36
|
-
const TData = dataReturnType === 'data' ? typeSchemas.response.name : `ResponseConfig<${typeSchemas.response.name}>`
|
|
37
|
-
const TError = `ResponseErrorConfig<${typeSchemas.errors?.map((item) => item.name).join(' | ') || 'Error'}>`
|
|
38
|
-
|
|
39
|
-
if (paramsType === 'object') {
|
|
40
|
-
const pathParams = getPathParams(typeSchemas.pathParams, { typed: true, casing: paramsCasing })
|
|
41
|
-
|
|
42
|
-
const children = {
|
|
43
|
-
...pathParams,
|
|
44
|
-
data: typeSchemas.request?.name
|
|
45
|
-
? {
|
|
46
|
-
type: typeSchemas.request?.name,
|
|
47
|
-
optional: isOptional(typeSchemas.request?.schema),
|
|
48
|
-
}
|
|
49
|
-
: undefined,
|
|
50
|
-
params: typeSchemas.queryParams?.name
|
|
51
|
-
? {
|
|
52
|
-
type: typeSchemas.queryParams?.name,
|
|
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
|
-
{
|
|
76
|
-
query?: Partial<UseSuspenseQueryOptions<${[TData, TError, 'TData', 'TQueryKey'].join(', ')}>> & { client?: QueryClient },
|
|
77
|
-
client?: ${typeSchemas.request?.name ? `Partial<RequestConfig<${typeSchemas.request?.name}>> & { client?: Client }` : 'Partial<RequestConfig> & { client?: Client }'}
|
|
78
|
-
}
|
|
79
|
-
`,
|
|
80
|
-
default: '{}',
|
|
81
|
-
},
|
|
82
|
-
})
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
return FunctionParams.factory({
|
|
86
|
-
pathParams: typeSchemas.pathParams?.name
|
|
87
|
-
? {
|
|
88
|
-
mode: pathParamsType === 'object' ? 'object' : 'inlineSpread',
|
|
89
|
-
children: getPathParams(typeSchemas.pathParams, {
|
|
90
|
-
typed: true,
|
|
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
|
-
},
|
|
123
|
-
})
|
|
124
|
-
}
|
|
125
|
-
|
|
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
|
-
export function SuspenseQuery({
|
|
134
|
-
name,
|
|
135
|
-
queryKeyTypeName,
|
|
136
|
-
queryOptionsName,
|
|
137
|
-
queryKeyName,
|
|
138
|
-
paramsType,
|
|
139
|
-
paramsCasing,
|
|
140
|
-
pathParamsType,
|
|
141
|
-
dataReturnType,
|
|
142
|
-
typeSchemas,
|
|
143
|
-
operation,
|
|
144
|
-
customOptions,
|
|
145
|
-
}: Props): FabricReactNode {
|
|
146
|
-
const TData = dataReturnType === 'data' ? typeSchemas.response.name : `ResponseConfig<${typeSchemas.response.name}>`
|
|
147
|
-
const TError = `ResponseErrorConfig<${typeSchemas.errors?.map((item) => item.name).join(' | ') || 'Error'}>`
|
|
148
|
-
const returnType = `UseSuspenseQueryResult<${['TData', TError].join(', ')}> & { queryKey: TQueryKey }`
|
|
149
|
-
const generics = [`TData = ${TData}`, `TQueryKey extends QueryKey = ${queryKeyTypeName}`]
|
|
150
|
-
|
|
151
|
-
const queryKeyParams = QueryKey.getParams({
|
|
152
|
-
pathParamsType,
|
|
153
|
-
typeSchemas,
|
|
154
|
-
paramsCasing,
|
|
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
|
-
})
|
|
169
|
-
|
|
170
|
-
const queryOptions = `${queryOptionsName}(${queryOptionsParams.toCall()})`
|
|
171
|
-
|
|
172
|
-
return (
|
|
173
|
-
<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
|
-
>
|
|
183
|
-
{`
|
|
184
|
-
const { query: queryConfig = {}, client: config = {} } = options ?? {}
|
|
185
|
-
const { client: queryClient, ...resolvedOptions } = queryConfig
|
|
186
|
-
const queryKey = resolvedOptions?.queryKey ?? ${queryKeyName}(${queryKeyParams.toCall()})
|
|
187
|
-
${customOptions ? `const customOptions = ${customOptions.name}({ hookName: '${name}', operationId: '${operation.getOperationId()}' })` : ''}
|
|
188
|
-
|
|
189
|
-
const query = useSuspenseQuery({
|
|
190
|
-
...${queryOptions},${customOptions ? '\n...customOptions,' : ''}
|
|
191
|
-
...resolvedOptions,
|
|
192
|
-
queryKey,
|
|
193
|
-
} as unknown as UseSuspenseQueryOptions, queryClient) as ${returnType}
|
|
194
|
-
|
|
195
|
-
query.queryKey = queryKey as TQueryKey
|
|
196
|
-
|
|
197
|
-
return query
|
|
198
|
-
`}
|
|
199
|
-
</Function>
|
|
200
|
-
</File.Source>
|
|
201
|
-
)
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
SuspenseQuery.getParams = getParams
|
package/src/components/index.ts
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
export { InfiniteQuery } from './InfiniteQuery.tsx'
|
|
2
|
-
export { InfiniteQueryOptions } from './InfiniteQueryOptions.tsx'
|
|
3
|
-
export { Mutation } from './Mutation.tsx'
|
|
4
|
-
export { MutationKey } from './MutationKey.tsx'
|
|
5
|
-
export { MutationOptions } from './MutationOptions.tsx'
|
|
6
|
-
export { Query } from './Query.tsx'
|
|
7
|
-
export { QueryKey } from './QueryKey.tsx'
|
|
8
|
-
export { QueryOptions } from './QueryOptions.tsx'
|
|
9
|
-
export { SuspenseInfiniteQuery } from './SuspenseInfiniteQuery.tsx'
|
|
10
|
-
export { SuspenseInfiniteQueryOptions } from './SuspenseInfiniteQueryOptions.tsx'
|
|
11
|
-
export { SuspenseQuery } from './SuspenseQuery.tsx'
|
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
import fs from 'node:fs'
|
|
2
|
-
import path from 'node:path'
|
|
3
|
-
import { usePluginDriver } from '@kubb/core/hooks'
|
|
4
|
-
import type { Operation } from '@kubb/oas'
|
|
5
|
-
import { createReactGenerator } from '@kubb/plugin-oas/generators'
|
|
6
|
-
import { useOperationManager } from '@kubb/plugin-oas/hooks'
|
|
7
|
-
import { File, Function } from '@kubb/react-fabric'
|
|
8
|
-
import type { PluginReactQuery } from '../types'
|
|
9
|
-
|
|
10
|
-
export const customHookOptionsFileGenerator = createReactGenerator<PluginReactQuery>({
|
|
11
|
-
name: 'react-query-custom-hook-options-file',
|
|
12
|
-
Operations({ operations, generator, plugin, config }) {
|
|
13
|
-
const {
|
|
14
|
-
options,
|
|
15
|
-
options: { output },
|
|
16
|
-
name: pluginName,
|
|
17
|
-
} = plugin
|
|
18
|
-
const driver = usePluginDriver()
|
|
19
|
-
|
|
20
|
-
const { getFile } = useOperationManager(generator)
|
|
21
|
-
|
|
22
|
-
if (!options.customOptions) {
|
|
23
|
-
return null
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
const override = output.override ?? config.output.override ?? false
|
|
27
|
-
const { importPath, name } = options.customOptions
|
|
28
|
-
|
|
29
|
-
const root = path.resolve(config.root, config.output.path)
|
|
30
|
-
|
|
31
|
-
const reactQueryImportPath = options.query ? options.query.importPath : '@tanstack/react-query'
|
|
32
|
-
|
|
33
|
-
const getHookFilePath = (operations: Operation[]) => {
|
|
34
|
-
const firstOperation = operations[0]
|
|
35
|
-
if (firstOperation != null) {
|
|
36
|
-
// Get the file of the first generated hook
|
|
37
|
-
return getFile(firstOperation, { prefix: 'use' }).path
|
|
38
|
-
}
|
|
39
|
-
// Get the index file of the hooks directory
|
|
40
|
-
return driver.getFile({ name: 'index', extname: '.ts', pluginName }).path
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
const ensureExtension = (filePath: string, extname: string) => {
|
|
44
|
-
if (path.extname(filePath) === '') {
|
|
45
|
-
return filePath + extname
|
|
46
|
-
}
|
|
47
|
-
return filePath
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
const getExternalFile = (filePath: string, rootPath: string) => {
|
|
51
|
-
const actualFilePath = ensureExtension(filePath, '.ts')
|
|
52
|
-
return {
|
|
53
|
-
baseName: path.basename(actualFilePath) as `${string}.${string}`,
|
|
54
|
-
name: path.basename(actualFilePath, path.extname(actualFilePath)),
|
|
55
|
-
path: path.resolve(rootPath, actualFilePath),
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
const basePath = path.dirname(getHookFilePath(operations))
|
|
60
|
-
const file = getExternalFile(importPath, basePath)
|
|
61
|
-
|
|
62
|
-
if (fs.existsSync(file.path) && !override) {
|
|
63
|
-
return null
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
return (
|
|
67
|
-
<File baseName={file.baseName} path={file.path}>
|
|
68
|
-
<File.Import name={['QueryClient']} path={reactQueryImportPath} isTypeOnly />
|
|
69
|
-
<File.Import name={['useQueryClient']} path={reactQueryImportPath} />
|
|
70
|
-
<File.Import name={['HookOptions']} root={file.path} path={path.resolve(root, './index.ts')} />
|
|
71
|
-
<File.Source name={file.name} isExportable isIndexable>
|
|
72
|
-
<Function name="getCustomHookOptions" params="{ queryClient }: { queryClient: QueryClient }" returnType="Partial<HookOptions>">
|
|
73
|
-
{`return {
|
|
74
|
-
// TODO: Define custom hook options here
|
|
75
|
-
// Example:
|
|
76
|
-
// useUpdatePetHook: {
|
|
77
|
-
// onSuccess: () => {
|
|
78
|
-
// void queryClient.invalidateQueries({ queryKey: ['pet'] })
|
|
79
|
-
// }
|
|
80
|
-
// }
|
|
81
|
-
}`}
|
|
82
|
-
</Function>
|
|
83
|
-
<Function
|
|
84
|
-
name={name}
|
|
85
|
-
generics="T extends keyof HookOptions"
|
|
86
|
-
params="{ hookName, operationId }: { hookName: T, operationId: string }"
|
|
87
|
-
returnType="HookOptions[T]"
|
|
88
|
-
export
|
|
89
|
-
>
|
|
90
|
-
{`const queryClient = useQueryClient()
|
|
91
|
-
const customOptions = getCustomHookOptions({ queryClient })
|
|
92
|
-
return customOptions[hookName] ?? {}`}
|
|
93
|
-
</Function>
|
|
94
|
-
</File.Source>
|
|
95
|
-
</File>
|
|
96
|
-
)
|
|
97
|
-
},
|
|
98
|
-
})
|