@kubb/plugin-react-query 5.0.0-alpha.8 → 5.0.0-beta.3

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 (52) hide show
  1. package/LICENSE +17 -10
  2. package/README.md +1 -3
  3. package/dist/components-DTGLu4UV.js +1451 -0
  4. package/dist/components-DTGLu4UV.js.map +1 -0
  5. package/dist/components-dAKJEn9b.cjs +1571 -0
  6. package/dist/components-dAKJEn9b.cjs.map +1 -0
  7. package/dist/components.cjs +1 -1
  8. package/dist/components.d.ts +105 -161
  9. package/dist/components.js +1 -1
  10. package/dist/generators-CWEQsdO9.cjs +1502 -0
  11. package/dist/generators-CWEQsdO9.cjs.map +1 -0
  12. package/dist/generators-C_fbcjpG.js +1460 -0
  13. package/dist/generators-C_fbcjpG.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 +114 -126
  18. package/dist/index.cjs.map +1 -1
  19. package/dist/index.d.ts +4 -4
  20. package/dist/index.js +110 -126
  21. package/dist/index.js.map +1 -1
  22. package/dist/{types-D5S7Ny9r.d.ts → types-DfaFRSBf.d.ts} +100 -86
  23. package/package.json +59 -62
  24. package/src/components/InfiniteQuery.tsx +75 -139
  25. package/src/components/InfiniteQueryOptions.tsx +62 -164
  26. package/src/components/Mutation.tsx +58 -113
  27. package/src/components/MutationOptions.tsx +61 -80
  28. package/src/components/Query.tsx +67 -140
  29. package/src/components/QueryOptions.tsx +75 -135
  30. package/src/components/SuspenseInfiniteQuery.tsx +75 -139
  31. package/src/components/SuspenseInfiniteQueryOptions.tsx +62 -164
  32. package/src/components/SuspenseQuery.tsx +67 -150
  33. package/src/generators/customHookOptionsFileGenerator.tsx +33 -45
  34. package/src/generators/hookOptionsGenerator.tsx +115 -175
  35. package/src/generators/infiniteQueryGenerator.tsx +183 -176
  36. package/src/generators/mutationGenerator.tsx +127 -138
  37. package/src/generators/queryGenerator.tsx +141 -141
  38. package/src/generators/suspenseInfiniteQueryGenerator.tsx +175 -155
  39. package/src/generators/suspenseQueryGenerator.tsx +149 -148
  40. package/src/index.ts +1 -1
  41. package/src/plugin.ts +133 -183
  42. package/src/resolvers/resolverReactQuery.ts +22 -0
  43. package/src/types.ts +67 -45
  44. package/src/utils.ts +40 -0
  45. package/dist/components-BHQT9ZLc.cjs +0 -1634
  46. package/dist/components-BHQT9ZLc.cjs.map +0 -1
  47. package/dist/components-CpyHYGOw.js +0 -1520
  48. package/dist/components-CpyHYGOw.js.map +0 -1
  49. package/dist/generators-DP07m3rH.cjs +0 -1469
  50. package/dist/generators-DP07m3rH.cjs.map +0 -1
  51. package/dist/generators-DkQwKTc2.js +0 -1427
  52. package/dist/generators-DkQwKTc2.js.map +0 -1
@@ -1,18 +1,20 @@
1
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'
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, PluginReactQuery } 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
- typeSchemas: OperationSchemas
16
+ node: ast.OperationNode
17
+ tsResolver: ResolverTs
16
18
  paramsCasing: PluginReactQuery['resolvedOptions']['paramsCasing']
17
19
  paramsType: PluginReactQuery['resolvedOptions']['paramsType']
18
20
  pathParamsType: PluginReactQuery['resolvedOptions']['pathParamsType']
@@ -24,94 +26,8 @@ type Props = {
24
26
  queryParam: Infinite['queryParam']
25
27
  }
26
28
 
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
- }
29
+ const declarationPrinter = functionPrinter({ mode: 'declaration' })
30
+ const callPrinter = functionPrinter({ mode: 'call' })
115
31
 
116
32
  export function SuspenseInfiniteQueryOptions({
117
33
  name,
@@ -120,16 +36,20 @@ export function SuspenseInfiniteQueryOptions({
120
36
  cursorParam,
121
37
  nextParam,
122
38
  previousParam,
123
- typeSchemas,
39
+ node,
40
+ tsResolver,
124
41
  paramsCasing,
125
42
  paramsType,
126
43
  dataReturnType,
127
44
  pathParamsType,
128
45
  queryParam,
129
46
  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'}>`
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
+
133
53
  const isInitialPageParamDefined = initialPageParam !== undefined && initialPageParam !== null
134
54
  const fallbackPageParamType =
135
55
  typeof initialPageParam === 'number'
@@ -144,36 +64,37 @@ export function SuspenseInfiniteQueryOptions({
144
64
  : typeof initialPageParam === 'boolean'
145
65
  ? 'boolean'
146
66
  : 'unknown'
147
- const queryParamType = queryParam && typeSchemas.queryParams?.name ? `${typeSchemas.queryParams?.name}['${queryParam}']` : undefined
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
148
79
  const pageParamType = queryParamType ? (isInitialPageParamDefined ? `NonNullable<${queryParamType}>` : queryParamType) : fallbackPageParamType
149
80
 
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
- })
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}),` : ''
168
91
 
169
- // Determine if we should use the new nextParam/previousParam or fall back to legacy cursorParam behavior
170
92
  const hasNewParams = nextParam !== undefined || previousParam !== undefined
171
93
 
172
94
  let getNextPageParamExpr: string | undefined
173
95
  let getPreviousPageParamExpr: string | undefined
174
96
 
175
97
  if (hasNewParams) {
176
- // Use the new nextParam and previousParam
177
98
  if (nextParam) {
178
99
  const accessor = getNestedAccessor(nextParam, 'lastPage')
179
100
  if (accessor) {
@@ -187,11 +108,9 @@ export function SuspenseInfiniteQueryOptions({
187
108
  }
188
109
  }
189
110
  } else if (cursorParam) {
190
- // Legacy behavior: use cursorParam for both next and previous
191
111
  getNextPageParamExpr = `getNextPageParam: (lastPage) => lastPage['${cursorParam}']`
192
112
  getPreviousPageParamExpr = `getPreviousPageParam: (firstPage) => firstPage['${cursorParam}']`
193
113
  } else {
194
- // Fallback behavior: page-based pagination
195
114
  if (dataReturnType === 'full') {
196
115
  getNextPageParamExpr =
197
116
  'getNextPageParam: (lastPage, _allPages, lastPageParam) => Array.isArray(lastPage.data) && lastPage.data.length === 0 ? undefined : lastPageParam + 1'
@@ -202,56 +121,35 @@ export function SuspenseInfiniteQueryOptions({
202
121
  getPreviousPageParamExpr = 'getPreviousPageParam: (_firstPage, _allPages, firstPageParam) => firstPageParam <= 1 ? undefined : firstPageParam - 1'
203
122
  }
204
123
 
205
- const queryOptions = [
124
+ const queryOptionsArr = [
206
125
  `initialPageParam: ${typeof initialPageParam === 'string' ? JSON.stringify(initialPageParam) : initialPageParam}`,
207
126
  getNextPageParamExpr,
208
127
  getPreviousPageParamExpr,
209
128
  ].filter(Boolean)
210
129
 
211
130
  const infiniteOverrideParams =
212
- queryParam && typeSchemas.queryParams?.name
131
+ queryParam && queryParamsTypeName
213
132
  ? `
214
133
  params = {
215
134
  ...(params ?? {}),
216
- ['${queryParam}']: pageParam as unknown as ${typeSchemas.queryParams?.name}['${queryParam}'],
217
- } as ${typeSchemas.queryParams?.name}`
135
+ ['${queryParam}']: pageParam as unknown as ${queryParamsTypeName}['${queryParam}'],
136
+ } as ${queryParamsTypeName}`
218
137
  : ''
219
138
 
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
139
  if (infiniteOverrideParams) {
234
140
  return (
235
141
  <File.Source name={name} isExportable isIndexable>
236
- <Function name={name} export params={params.toConstructor()}>
142
+ <Function name={name} export params={paramsSignature}>
237
143
  {`
238
- const queryKey = ${queryKeyName}(${queryKeyParams.toCall()})
144
+ const queryKey = ${queryKeyName}(${queryKeyParamsCall})
239
145
  return infiniteQueryOptions<${queryFnDataType}, ${errorType}, InfiniteData<${queryFnDataType}>, typeof queryKey, ${pageParamType}>({
240
146
  ${enabledText}
241
147
  queryKey,
242
148
  queryFn: async ({ signal, pageParam }) => {
243
149
  ${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
- })})
150
+ return ${clientName}(${clientCallStr})
253
151
  },
254
- ${queryOptions.join(',\n')}
152
+ ${queryOptionsArr.join(',\n')}
255
153
  })
256
154
  `}
257
155
  </Function>
@@ -261,24 +159,16 @@ export function SuspenseInfiniteQueryOptions({
261
159
 
262
160
  return (
263
161
  <File.Source name={name} isExportable isIndexable>
264
- <Function name={name} export params={params.toConstructor()}>
162
+ <Function name={name} export params={paramsSignature}>
265
163
  {`
266
- const queryKey = ${queryKeyName}(${queryKeyParams.toCall()})
164
+ const queryKey = ${queryKeyName}(${queryKeyParamsCall})
267
165
  return infiniteQueryOptions<${queryFnDataType}, ${errorType}, InfiniteData<${queryFnDataType}>, typeof queryKey, ${pageParamType}>({
268
166
  ${enabledText}
269
167
  queryKey,
270
168
  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
- })})
169
+ return ${clientName}(${clientCallStr})
280
170
  },
281
- ${queryOptions.join(',\n')}
171
+ ${queryOptionsArr.join(',\n')}
282
172
  })
283
173
  `}
284
174
  </Function>
@@ -286,4 +176,12 @@ export function SuspenseInfiniteQueryOptions({
286
176
  )
287
177
  }
288
178
 
289
- SuspenseInfiniteQueryOptions.getParams = getParams
179
+ SuspenseInfiniteQueryOptions.getParams = (
180
+ node: ast.OperationNode,
181
+ options: {
182
+ paramsType: PluginReactQuery['resolvedOptions']['paramsType']
183
+ paramsCasing: PluginReactQuery['resolvedOptions']['paramsCasing']
184
+ pathParamsType: PluginReactQuery['resolvedOptions']['pathParamsType']
185
+ resolver: ResolverTs
186
+ },
187
+ ) => getQueryOptionsParams(node, options)
@@ -1,22 +1,20 @@
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 { getComments, resolveErrorNames } from '../utils.ts'
7
8
  import { QueryKey } from './QueryKey.tsx'
8
- import { QueryOptions } from './QueryOptions.tsx'
9
+ import { getQueryOptionsParams } from './QueryOptions.tsx'
9
10
 
10
11
  type Props = {
11
- /**
12
- * Name of the function
13
- */
14
12
  name: string
15
13
  queryOptionsName: string
16
14
  queryKeyName: string
17
15
  queryKeyTypeName: string
18
- typeSchemas: OperationSchemas
19
- operation: Operation
16
+ node: ast.OperationNode
17
+ tsResolver: ResolverTs
20
18
  paramsCasing: PluginReactQuery['resolvedOptions']['paramsCasing']
21
19
  paramsType: PluginReactQuery['resolvedOptions']['paramsType']
22
20
  pathParamsType: PluginReactQuery['resolvedOptions']['pathParamsType']
@@ -24,112 +22,48 @@ type Props = {
24
22
  customOptions: PluginReactQuery['resolvedOptions']['customOptions']
25
23
  }
26
24
 
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
- {
25
+ const declarationPrinter = functionPrinter({ mode: 'declaration' })
26
+ const callPrinter = functionPrinter({ mode: 'call' })
27
+
28
+ function getParams(
29
+ node: ast.OperationNode,
30
+ options: {
31
+ paramsType: PluginReactQuery['resolvedOptions']['paramsType']
32
+ paramsCasing: PluginReactQuery['resolvedOptions']['paramsCasing']
33
+ pathParamsType: PluginReactQuery['resolvedOptions']['pathParamsType']
34
+ dataReturnType: PluginReactQuery['resolvedOptions']['client']['dataReturnType']
35
+ resolver: ResolverTs
36
+ },
37
+ ): ast.FunctionParametersNode {
38
+ const { paramsType, paramsCasing, pathParamsType, dataReturnType, resolver } = options
39
+ const responseName = resolver.resolveResponseName(node)
40
+ const requestName = node.requestBody?.content?.[0]?.schema ? resolver.resolveDataName(node) : undefined
41
+ const errorNames = resolveErrorNames(node, resolver)
42
+
43
+ const TData = dataReturnType === 'data' ? responseName : `ResponseConfig<${responseName}>`
44
+ const TError = `ResponseErrorConfig<${errorNames.length > 0 ? errorNames.join(' | ') : 'Error'}>`
45
+
46
+ const optionsParam = ast.createFunctionParameter({
47
+ name: 'options',
48
+ type: ast.createParamsType({
49
+ variant: 'reference',
50
+ name: `{
76
51
  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
- },
52
+ client?: ${requestName ? `Partial<RequestConfig<${requestName}>> & { client?: Client }` : 'Partial<RequestConfig> & { client?: Client }'}
53
+ }`,
54
+ }),
55
+ default: '{}',
56
+ })
57
+
58
+ return ast.createOperationParams(node, {
59
+ paramsType,
60
+ pathParamsType: paramsType === 'object' ? 'object' : pathParamsType === 'object' ? 'object' : 'inline',
61
+ paramsCasing,
62
+ resolver,
63
+ extraParams: [optionsParam],
123
64
  })
124
65
  }
125
66
 
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
67
  export function SuspenseQuery({
134
68
  name,
135
69
  queryKeyTypeName,
@@ -139,55 +73,38 @@ export function SuspenseQuery({
139
73
  paramsCasing,
140
74
  pathParamsType,
141
75
  dataReturnType,
142
- typeSchemas,
143
- operation,
76
+ node,
77
+ tsResolver,
144
78
  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 }`
79
+ }: Props): KubbReactNode {
80
+ const responseName = tsResolver.resolveResponseName(node)
81
+ const errorNames = resolveErrorNames(node, tsResolver)
82
+
83
+ const TData = dataReturnType === 'data' ? responseName : `ResponseConfig<${responseName}>`
84
+ const TError = `ResponseErrorConfig<${errorNames.length > 0 ? errorNames.join(' | ') : 'Error'}>`
85
+ const returnType = `UseSuspenseQueryResult<${'TData'}, ${TError}> & { queryKey: TQueryKey }`
149
86
  const generics = [`TData = ${TData}`, `TQueryKey extends QueryKey = ${queryKeyTypeName}`]
150
87
 
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
- })
88
+ const queryKeyParamsNode = QueryKey.getParams(node, { pathParamsType, paramsCasing, resolver: tsResolver })
89
+ const queryKeyParamsCall = callPrinter.print(queryKeyParamsNode) ?? ''
90
+
91
+ const queryOptionsParamsNode = getQueryOptionsParams(node, { paramsType, paramsCasing, pathParamsType, resolver: tsResolver })
92
+ const queryOptionsParamsCall = callPrinter.print(queryOptionsParamsNode) ?? ''
169
93
 
170
- const queryOptions = `${queryOptionsName}(${queryOptionsParams.toCall()})`
94
+ const paramsNode = getParams(node, { paramsType, paramsCasing, pathParamsType, dataReturnType, resolver: tsResolver })
95
+ const paramsSignature = declarationPrinter.print(paramsNode) ?? ''
171
96
 
172
97
  return (
173
98
  <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
- >
99
+ <Function name={name} export generics={generics.join(', ')} params={paramsSignature} returnType={undefined} JSDoc={{ comments: getComments(node) }}>
183
100
  {`
184
101
  const { query: queryConfig = {}, client: config = {} } = options ?? {}
185
102
  const { client: queryClient, ...resolvedOptions } = queryConfig
186
- const queryKey = resolvedOptions?.queryKey ?? ${queryKeyName}(${queryKeyParams.toCall()})
187
- ${customOptions ? `const customOptions = ${customOptions.name}({ hookName: '${name}', operationId: '${operation.getOperationId()}' })` : ''}
103
+ const queryKey = resolvedOptions?.queryKey ?? ${queryKeyName}(${queryKeyParamsCall})
104
+ ${customOptions ? `const customOptions = ${customOptions.name}({ hookName: '${name}', operationId: '${node.operationId}' })` : ''}
188
105
 
189
106
  const query = useSuspenseQuery({
190
- ...${queryOptions},${customOptions ? '\n...customOptions,' : ''}
107
+ ...${queryOptionsName}(${queryOptionsParamsCall}),${customOptions ? '\n...customOptions,' : ''}
191
108
  ...resolvedOptions,
192
109
  queryKey,
193
110
  } as unknown as UseSuspenseQueryOptions, queryClient) as ${returnType}