@kubb/plugin-react-query 5.0.0-alpha.8 → 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.
Files changed (54) hide show
  1. package/LICENSE +17 -10
  2. package/README.md +34 -85
  3. package/dist/components-Dow6tde8.js +1459 -0
  4. package/dist/components-Dow6tde8.js.map +1 -0
  5. package/dist/components-HwdCDefj.cjs +1603 -0
  6. package/dist/components-HwdCDefj.cjs.map +1 -0
  7. package/dist/components.cjs +1 -1
  8. package/dist/components.d.ts +49 -179
  9. package/dist/components.js +1 -1
  10. package/dist/generators-CcOmnTPa.cjs +1454 -0
  11. package/dist/generators-CcOmnTPa.cjs.map +1 -0
  12. package/dist/generators-yfZr_qfT.js +1412 -0
  13. package/dist/generators-yfZr_qfT.js.map +1 -0
  14. package/dist/generators.cjs +1 -1
  15. package/dist/generators.d.ts +9 -476
  16. package/dist/generators.js +1 -1
  17. package/dist/index.cjs +197 -126
  18. package/dist/index.cjs.map +1 -1
  19. package/dist/index.d.ts +4 -4
  20. package/dist/index.js +193 -126
  21. package/dist/index.js.map +1 -1
  22. package/dist/types-DG_OxOym.d.ts +363 -0
  23. package/extension.yaml +911 -0
  24. package/package.json +59 -64
  25. package/src/components/InfiniteQuery.tsx +79 -138
  26. package/src/components/InfiniteQueryOptions.tsx +55 -166
  27. package/src/components/Mutation.tsx +74 -111
  28. package/src/components/MutationOptions.tsx +61 -80
  29. package/src/components/Query.tsx +66 -142
  30. package/src/components/QueryOptions.tsx +56 -138
  31. package/src/components/SuspenseInfiniteQuery.tsx +79 -138
  32. package/src/components/SuspenseInfiniteQueryOptions.tsx +55 -166
  33. package/src/components/SuspenseQuery.tsx +66 -152
  34. package/src/generators/customHookOptionsFileGenerator.tsx +37 -51
  35. package/src/generators/hookOptionsGenerator.tsx +111 -174
  36. package/src/generators/infiniteQueryGenerator.tsx +158 -178
  37. package/src/generators/mutationGenerator.tsx +112 -139
  38. package/src/generators/queryGenerator.tsx +128 -142
  39. package/src/generators/suspenseInfiniteQueryGenerator.tsx +157 -156
  40. package/src/generators/suspenseQueryGenerator.tsx +126 -152
  41. package/src/index.ts +1 -1
  42. package/src/plugin.ts +134 -187
  43. package/src/resolvers/resolverReactQuery.ts +107 -0
  44. package/src/types.ts +172 -49
  45. package/src/utils.ts +10 -0
  46. package/dist/components-BHQT9ZLc.cjs +0 -1634
  47. package/dist/components-BHQT9ZLc.cjs.map +0 -1
  48. package/dist/components-CpyHYGOw.js +0 -1520
  49. package/dist/components-CpyHYGOw.js.map +0 -1
  50. package/dist/generators-DP07m3rH.cjs +0 -1469
  51. package/dist/generators-DP07m3rH.cjs.map +0 -1
  52. package/dist/generators-DkQwKTc2.js +0 -1427
  53. package/dist/generators-DkQwKTc2.js.map +0 -1
  54. 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 { 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'
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 { QueryKey } from './QueryKey.tsx'
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
- typeSchemas: OperationSchemas
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
- 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
- }
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
- typeSchemas,
40
+ node,
41
+ tsResolver,
124
42
  paramsCasing,
125
43
  paramsType,
126
44
  dataReturnType,
127
45
  pathParamsType,
128
46
  queryParam,
129
47
  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'}>`
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
- const queryParamType = queryParam && typeSchemas.queryParams?.name ? `${typeSchemas.queryParams?.name}['${queryParam}']` : undefined
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 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
- })
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 queryOptions = [
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 && typeSchemas.queryParams?.name
132
+ queryParam && queryParamsTypeName
213
133
  ? `
214
134
  params = {
215
135
  ...(params ?? {}),
216
- ['${queryParam}']: pageParam as unknown as ${typeSchemas.queryParams?.name}['${queryParam}'],
217
- } as ${typeSchemas.queryParams?.name}`
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={params.toConstructor()}>
143
+ <Function name={name} export params={paramsSignature}>
237
144
  {`
238
- const queryKey = ${queryKeyName}(${queryKeyParams.toCall()})
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}(${clientParams.toCall({
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
- ${queryOptions.join(',\n')}
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={params.toConstructor()}>
163
+ <Function name={name} export params={paramsSignature}>
265
164
  {`
266
- const queryKey = ${queryKeyName}(${queryKeyParams.toCall()})
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}(${clientParams.toCall({
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
- ${queryOptions.join(',\n')}
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 { 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'
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 { QueryKey } from './QueryKey.tsx'
8
- import { QueryOptions } from './QueryOptions.tsx'
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
- typeSchemas: OperationSchemas
19
- operation: Operation
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
- 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
- {
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?: ${typeSchemas.request?.name ? `Partial<RequestConfig<${typeSchemas.request?.name}>> & { client?: Client }` : 'Partial<RequestConfig> & { client?: Client }'}
78
- }
79
- `,
80
- default: '{}',
81
- },
82
- })
83
- }
51
+ client?: ${requestName ? `Partial<RequestConfig<${requestName}>> & { client?: Client }` : 'Partial<RequestConfig> & { client?: Client }'}
52
+ }`,
53
+ }),
54
+ default: '{}',
55
+ })
84
56
 
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
- },
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
- typeSchemas,
143
- operation,
75
+ node,
76
+ tsResolver,
144
77
  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 }`
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 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
- })
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 queryOptions = `${queryOptionsName}(${queryOptionsParams.toCall()})`
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}(${queryKeyParams.toCall()})
187
- ${customOptions ? `const customOptions = ${customOptions.name}({ hookName: '${name}', operationId: '${operation.getOperationId()}' })` : ''}
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
- ...${queryOptions},${customOptions ? '\n...customOptions,' : ''}
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