@kubb/plugin-react-query 5.0.0-beta.4 → 5.0.0-beta.56

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 (49) hide show
  1. package/README.md +38 -91
  2. package/dist/{components-DTGLu4UV.js → components-DL0Cai7l.js} +570 -514
  3. package/dist/components-DL0Cai7l.js.map +1 -0
  4. package/dist/{components-dAKJEn9b.cjs → components-yMQOuFmI.cjs} +600 -514
  5. package/dist/components-yMQOuFmI.cjs.map +1 -0
  6. package/dist/components.cjs +1 -1
  7. package/dist/components.d.ts +5 -77
  8. package/dist/components.js +1 -1
  9. package/dist/{generators-C_fbcjpG.js → generators-BG-Vcvfg.js} +444 -597
  10. package/dist/generators-BG-Vcvfg.js.map +1 -0
  11. package/dist/{generators-CWEQsdO9.cjs → generators-zGKP8yII.cjs} +442 -595
  12. package/dist/generators-zGKP8yII.cjs.map +1 -0
  13. package/dist/generators.cjs +1 -1
  14. package/dist/generators.d.ts +49 -10
  15. package/dist/generators.js +1 -1
  16. package/dist/index.cjs +201 -28
  17. package/dist/index.cjs.map +1 -1
  18. package/dist/index.d.ts +32 -4
  19. package/dist/index.js +203 -30
  20. package/dist/index.js.map +1 -1
  21. package/dist/types-X7D0NSvJ.d.ts +396 -0
  22. package/package.json +18 -27
  23. package/src/components/InfiniteQuery.tsx +27 -17
  24. package/src/components/InfiniteQueryOptions.tsx +60 -81
  25. package/src/components/Mutation.tsx +39 -20
  26. package/src/components/MutationOptions.tsx +15 -14
  27. package/src/components/Query.tsx +18 -15
  28. package/src/components/QueryOptions.tsx +20 -56
  29. package/src/components/SuspenseInfiniteQuery.tsx +22 -17
  30. package/src/components/SuspenseInfiniteQueryOptions.tsx +51 -76
  31. package/src/components/SuspenseQuery.tsx +13 -15
  32. package/src/generators/customHookOptionsFileGenerator.tsx +16 -12
  33. package/src/generators/hookOptionsGenerator.tsx +42 -49
  34. package/src/generators/infiniteQueryGenerator.tsx +55 -80
  35. package/src/generators/mutationGenerator.tsx +54 -66
  36. package/src/generators/queryGenerator.tsx +52 -65
  37. package/src/generators/suspenseInfiniteQueryGenerator.tsx +50 -67
  38. package/src/generators/suspenseQueryGenerator.tsx +54 -78
  39. package/src/plugin.ts +47 -33
  40. package/src/resolvers/resolverReactQuery.ts +104 -8
  41. package/src/types.ts +202 -68
  42. package/src/utils.ts +11 -33
  43. package/dist/components-DTGLu4UV.js.map +0 -1
  44. package/dist/components-dAKJEn9b.cjs.map +0 -1
  45. package/dist/generators-CWEQsdO9.cjs.map +0 -1
  46. package/dist/generators-C_fbcjpG.js.map +0 -1
  47. package/dist/types-DfaFRSBf.d.ts +0 -284
  48. package/extension.yaml +0 -938
  49. /package/dist/{chunk--u3MIqq1.js → chunk-C0LytTxp.js} +0 -0
@@ -1,13 +1,14 @@
1
- import { getNestedAccessor } from '@internals/utils'
1
+ import { getOperationParameters } from '@internals/shared'
2
+ import { getNestedAccessor } from '@kubb/ast/utils'
2
3
  import type { ast } from '@kubb/core'
3
4
  import type { ResolverTs } from '@kubb/plugin-ts'
4
5
  import { functionPrinter } from '@kubb/plugin-ts'
5
6
  import { File, Function } from '@kubb/renderer-jsx'
6
7
  import type { KubbReactNode } from '@kubb/renderer-jsx/types'
7
8
  import type { Infinite, PluginReactQuery } from '../types.ts'
8
- import { resolveErrorNames } from '../utils.ts'
9
- import { QueryKey } from './QueryKey.tsx'
10
- import { buildEnabledCheck, getQueryOptionsParams } from './QueryOptions.tsx'
9
+ import { buildQueryKeyParams, buildStatusUnionType, resolveErrorNames, resolveSuccessNames } from '../utils.ts'
10
+ import { getEnabledParamNames, injectNonNullAssertions, markParamsOptional } from '@internals/tanstack-query'
11
+ import { getQueryOptionsParams } from './QueryOptions.tsx'
11
12
 
12
13
  type Props = {
13
14
  name: string
@@ -45,8 +46,9 @@ export function InfiniteQueryOptions({
45
46
  queryParam,
46
47
  queryKeyName,
47
48
  }: Props): KubbReactNode {
48
- const responseName = tsResolver.resolveResponseName(node)
49
- const queryFnDataType = dataReturnType === 'data' ? responseName : `ResponseConfig<${responseName}>`
49
+ const successNames = resolveSuccessNames(node, tsResolver)
50
+ const responseName = successNames.length > 0 ? successNames.join(' | ') : tsResolver.resolveResponseName(node)
51
+ const queryFnDataType = dataReturnType === 'data' ? responseName : buildStatusUnionType(node, tsResolver)
50
52
  const errorNames = resolveErrorNames(node, tsResolver)
51
53
  const errorType = `ResponseErrorConfig<${errorNames.length > 0 ? errorNames.join(' | ') : 'Error'}>`
52
54
 
@@ -65,61 +67,51 @@ export function InfiniteQueryOptions({
65
67
  ? 'boolean'
66
68
  : 'unknown'
67
69
 
68
- const rawQueryParams = node.parameters.filter((p) => p.in === 'query')
70
+ const rawQueryParams = getOperationParameters(node).query
69
71
  const queryParamsTypeName =
70
72
  rawQueryParams.length > 0
71
73
  ? (() => {
72
74
  const groupName = tsResolver.resolveQueryParamsName(node, rawQueryParams[0]!)
73
75
  const individualName = tsResolver.resolveParamName(node, rawQueryParams[0]!)
74
- return groupName !== individualName ? groupName : undefined
76
+ return groupName !== individualName ? groupName : null
75
77
  })()
76
- : undefined
78
+ : null
77
79
 
78
- const queryParamType = queryParam && queryParamsTypeName ? `${queryParamsTypeName}['${queryParam}']` : undefined
80
+ const queryParamType = queryParam && queryParamsTypeName ? `${queryParamsTypeName}['${queryParam}']` : null
79
81
  const pageParamType = queryParamType ? (isInitialPageParamDefined ? `NonNullable<${queryParamType}>` : queryParamType) : fallbackPageParamType
80
82
 
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 })
83
+ const queryKeyParamsNode = buildQueryKeyParams(node, { pathParamsType, paramsCasing, resolver: tsResolver })
87
84
  const queryKeyParamsCall = callPrinter.print(queryKeyParamsNode) ?? ''
88
85
 
89
- const enabledSource = buildEnabledCheck(queryKeyParamsNode)
90
- const enabledText = enabledSource ? `enabled: !!(${enabledSource}),` : ''
91
-
92
- const hasNewParams = nextParam !== undefined || previousParam !== undefined
86
+ const enabledNames = getEnabledParamNames(queryKeyParamsNode)
87
+ const enabledText = enabledNames.length ? `enabled: !!(${enabledNames.join(' && ')}),` : ''
93
88
 
94
- let getNextPageParamExpr: string | undefined
95
- let getPreviousPageParamExpr: string | undefined
96
-
97
- if (hasNewParams) {
98
- if (nextParam) {
99
- const accessor = getNestedAccessor(nextParam, 'lastPage')
100
- if (accessor) {
101
- getNextPageParamExpr = `getNextPageParam: (lastPage) => ${accessor}`
102
- }
103
- }
104
- if (previousParam) {
105
- const accessor = getNestedAccessor(previousParam, 'firstPage')
106
- if (accessor) {
107
- getPreviousPageParamExpr = `getPreviousPageParam: (firstPage) => ${accessor}`
108
- }
89
+ const paramsNode = markParamsOptional(getQueryOptionsParams(node, { paramsType, paramsCasing, pathParamsType, resolver: tsResolver }), enabledNames)
90
+ const paramsSignature = declarationPrinter.print(paramsNode) ?? ''
91
+ const rawParamsCall = callPrinter.print(paramsNode) ?? ''
92
+ const clientCallStr = injectNonNullAssertions(rawParamsCall.replace(/\bconfig\b(?=[^,]*$)/, '{ ...config, signal: config.signal ?? signal }'), enabledNames)
93
+
94
+ const hasNewParams = nextParam != null || previousParam != null
95
+
96
+ const [getNextPageParamExpr, getPreviousPageParamExpr] = (() => {
97
+ if (hasNewParams) {
98
+ const nextAccessor = nextParam ? getNestedAccessor(nextParam, 'lastPage') : null
99
+ const prevAccessor = previousParam ? getNestedAccessor(previousParam, 'firstPage') : null
100
+ return [
101
+ nextAccessor ? `getNextPageParam: (lastPage) => ${nextAccessor}` : null,
102
+ prevAccessor ? `getPreviousPageParam: (firstPage) => ${prevAccessor}` : null,
103
+ ] as const
109
104
  }
110
- } else if (cursorParam) {
111
- getNextPageParamExpr = `getNextPageParam: (lastPage) => lastPage['${cursorParam}']`
112
- getPreviousPageParamExpr = `getPreviousPageParam: (firstPage) => firstPage['${cursorParam}']`
113
- } else {
114
- if (dataReturnType === 'full') {
115
- getNextPageParamExpr =
116
- 'getNextPageParam: (lastPage, _allPages, lastPageParam) => Array.isArray(lastPage.data) && lastPage.data.length === 0 ? undefined : lastPageParam + 1'
117
- } else {
118
- getNextPageParamExpr =
119
- 'getNextPageParam: (lastPage, _allPages, lastPageParam) => Array.isArray(lastPage) && lastPage.length === 0 ? undefined : lastPageParam + 1'
105
+ if (cursorParam) {
106
+ return [`getNextPageParam: (lastPage) => lastPage['${cursorParam}']`, `getPreviousPageParam: (firstPage) => firstPage['${cursorParam}']`] as const
120
107
  }
121
- getPreviousPageParamExpr = 'getPreviousPageParam: (_firstPage, _allPages, firstPageParam) => firstPageParam <= 1 ? undefined : firstPageParam - 1'
122
- }
108
+ return [
109
+ dataReturnType === 'full'
110
+ ? 'getNextPageParam: (lastPage, _allPages, lastPageParam) => Array.isArray(lastPage.data) && lastPage.data.length === 0 ? undefined : lastPageParam + 1'
111
+ : 'getNextPageParam: (lastPage, _allPages, lastPageParam) => Array.isArray(lastPage) && lastPage.length === 0 ? undefined : lastPageParam + 1',
112
+ 'getPreviousPageParam: (_firstPage, _allPages, firstPageParam) => firstPageParam <= 1 ? undefined : firstPageParam - 1',
113
+ ] as const
114
+ })()
123
115
 
124
116
  const queryOptionsArr = [
125
117
  `initialPageParam: ${typeof initialPageParam === 'string' ? JSON.stringify(initialPageParam) : initialPageParam}`,
@@ -129,11 +121,10 @@ export function InfiniteQueryOptions({
129
121
 
130
122
  const infiniteOverrideParams =
131
123
  queryParam && queryParamsTypeName
132
- ? `
133
- params = {
134
- ...(params ?? {}),
135
- ['${queryParam}']: pageParam as unknown as ${queryParamsTypeName}['${queryParam}'],
136
- } as ${queryParamsTypeName}`
124
+ ? `params = {
125
+ ...(params ?? {}),
126
+ ['${queryParam}']: pageParam as unknown as ${queryParamsTypeName}['${queryParam}'],
127
+ } as ${queryParamsTypeName}`
137
128
  : ''
138
129
 
139
130
  if (infiniteOverrideParams) {
@@ -141,16 +132,15 @@ export function InfiniteQueryOptions({
141
132
  <File.Source name={name} isExportable isIndexable>
142
133
  <Function name={name} export params={paramsSignature}>
143
134
  {`
144
- const queryKey = ${queryKeyName}(${queryKeyParamsCall})
145
- return infiniteQueryOptions<${queryFnDataType}, ${errorType}, InfiniteData<${queryFnDataType}>, typeof queryKey, ${pageParamType}>({
146
- ${enabledText}
147
- queryKey,
148
- queryFn: async ({ signal, pageParam }) => {
149
- ${infiniteOverrideParams}
150
- return ${clientName}(${clientCallStr})
151
- },
152
- ${queryOptionsArr.join(',\n')}
153
- })
135
+ const queryKey = ${queryKeyName}(${queryKeyParamsCall})
136
+ return infiniteQueryOptions<${queryFnDataType}, ${errorType}, InfiniteData<${queryFnDataType}>, typeof queryKey, ${pageParamType}>({${enabledText ? `\n ${enabledText}` : ''}
137
+ queryKey,
138
+ queryFn: async ({ signal, pageParam }) => {
139
+ ${infiniteOverrideParams}
140
+ return ${clientName}(${clientCallStr})
141
+ },
142
+ ${queryOptionsArr.join(',\n ')}
143
+ })
154
144
  `}
155
145
  </Function>
156
146
  </File.Source>
@@ -161,27 +151,16 @@ export function InfiniteQueryOptions({
161
151
  <File.Source name={name} isExportable isIndexable>
162
152
  <Function name={name} export params={paramsSignature}>
163
153
  {`
164
- const queryKey = ${queryKeyName}(${queryKeyParamsCall})
165
- return infiniteQueryOptions<${queryFnDataType}, ${errorType}, InfiniteData<${queryFnDataType}>, typeof queryKey, ${pageParamType}>({
166
- ${enabledText}
167
- queryKey,
168
- queryFn: async ({ signal }) => {
169
- return ${clientName}(${clientCallStr})
170
- },
171
- ${queryOptionsArr.join(',\n')}
172
- })
154
+ const queryKey = ${queryKeyName}(${queryKeyParamsCall})
155
+ return infiniteQueryOptions<${queryFnDataType}, ${errorType}, InfiniteData<${queryFnDataType}>, typeof queryKey, ${pageParamType}>({${enabledText ? `\n ${enabledText}` : ''}
156
+ queryKey,
157
+ queryFn: async ({ signal }) => {
158
+ return ${clientName}(${clientCallStr})
159
+ },
160
+ ${queryOptionsArr.join(',\n ')}
161
+ })
173
162
  `}
174
163
  </Function>
175
164
  </File.Source>
176
165
  )
177
166
  }
178
-
179
- InfiniteQueryOptions.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)
@@ -4,8 +4,8 @@ import { functionPrinter } from '@kubb/plugin-ts'
4
4
  import { File, Function } from '@kubb/renderer-jsx'
5
5
  import type { KubbReactNode } from '@kubb/renderer-jsx/types'
6
6
  import type { PluginReactQuery } from '../types.ts'
7
- import { buildMutationArgParams, getComments, resolveErrorNames } from '../utils.ts'
8
- import { MutationOptions } from './MutationOptions.tsx'
7
+ import { buildRequestConfigType, buildStatusUnionType, getComments, resolveErrorNames, resolveSuccessNames } from '../utils.ts'
8
+ import { buildMutationConfigParamsNode } from './MutationOptions.tsx'
9
9
 
10
10
  type Props = {
11
11
  name: string
@@ -23,7 +23,22 @@ type Props = {
23
23
  const declarationPrinter = functionPrinter({ mode: 'declaration' })
24
24
  const callPrinter = functionPrinter({ mode: 'call' })
25
25
 
26
- function getParams(
26
+ function createMutationArgParams(
27
+ node: ast.OperationNode,
28
+ options: {
29
+ paramsCasing: PluginReactQuery['resolvedOptions']['paramsCasing']
30
+ resolver: ResolverTs
31
+ },
32
+ ): ast.FunctionParametersNode {
33
+ return ast.createOperationParams(node, {
34
+ paramsType: 'inline',
35
+ pathParamsType: 'inline',
36
+ paramsCasing: options.paramsCasing,
37
+ resolver: options.resolver,
38
+ })
39
+ }
40
+
41
+ function buildMutationParamsNode(
27
42
  node: ast.OperationNode,
28
43
  options: {
29
44
  paramsCasing: PluginReactQuery['resolvedOptions']['paramsCasing']
@@ -32,16 +47,19 @@ function getParams(
32
47
  },
33
48
  ): ast.FunctionParametersNode {
34
49
  const { paramsCasing, dataReturnType, resolver } = options
35
- const responseName = resolver.resolveResponseName(node)
36
- const requestName = node.requestBody?.content?.[0]?.schema ? resolver.resolveDataName(node) : undefined
50
+ const successNames = resolveSuccessNames(node, resolver)
51
+ const responseName = successNames.length > 0 ? successNames.join(' | ') : resolver.resolveResponseName(node)
37
52
  const errorNames = resolveErrorNames(node, resolver)
38
53
 
39
- const TData = dataReturnType === 'data' ? responseName : `ResponseConfig<${responseName}>`
54
+ const TData = dataReturnType === 'data' ? responseName : buildStatusUnionType(node, resolver)
40
55
  const TError = `ResponseErrorConfig<${errorNames.length > 0 ? errorNames.join(' | ') : 'Error'}>`
41
56
 
42
- const mutationArgParamsNode = buildMutationArgParams(node, { paramsCasing, resolver })
57
+ const mutationArgParamsNode = createMutationArgParams(node, {
58
+ paramsCasing,
59
+ resolver,
60
+ })
43
61
  const TRequest = mutationArgParamsNode.params.length > 0 ? (declarationPrinter.print(mutationArgParamsNode) ?? '') : ''
44
- const generics = [TData, TError, TRequest ? `{${TRequest}}` : 'void', 'TContext'].join(', ')
62
+ const generics = [TData, TError, TRequest ? `{${TRequest}}` : 'undefined', 'TContext'].join(', ')
45
63
 
46
64
  return ast.createFunctionParameters({
47
65
  params: [
@@ -51,7 +69,7 @@ function getParams(
51
69
  variant: 'reference',
52
70
  name: `{
53
71
  mutation?: UseMutationOptions<${generics}> & { client?: QueryClient },
54
- client?: ${requestName ? `Partial<RequestConfig<${requestName}>> & { client?: Client }` : 'Partial<RequestConfig> & { client?: Client }'},
72
+ client?: ${buildRequestConfigType(node, resolver)},
55
73
  }`,
56
74
  }),
57
75
  default: '{}',
@@ -61,21 +79,25 @@ function getParams(
61
79
  }
62
80
 
63
81
  export function Mutation({ name, mutationOptionsName, paramsCasing, dataReturnType, node, tsResolver, mutationKeyName, customOptions }: Props): KubbReactNode {
64
- const responseName = tsResolver.resolveResponseName(node)
82
+ const successNames = resolveSuccessNames(node, tsResolver)
83
+ const responseName = successNames.length > 0 ? successNames.join(' | ') : tsResolver.resolveResponseName(node)
65
84
  const errorNames = resolveErrorNames(node, tsResolver)
66
85
 
67
- const TData = dataReturnType === 'data' ? responseName : `ResponseConfig<${responseName}>`
86
+ const TData = dataReturnType === 'data' ? responseName : buildStatusUnionType(node, tsResolver)
68
87
  const TError = `ResponseErrorConfig<${errorNames.length > 0 ? errorNames.join(' | ') : 'Error'}>`
69
88
 
70
- const mutationArgParamsNode = buildMutationArgParams(node, { paramsCasing, resolver: tsResolver })
89
+ const mutationArgParamsNode = createMutationArgParams(node, {
90
+ paramsCasing,
91
+ resolver: tsResolver,
92
+ })
71
93
  const TRequest = mutationArgParamsNode.params.length > 0 ? (declarationPrinter.print(mutationArgParamsNode) ?? '') : ''
72
- const generics = [TData, TError, TRequest ? `{${TRequest}}` : 'void', 'TContext'].join(', ')
94
+ const generics = [TData, TError, TRequest ? `{${TRequest}}` : 'undefined', 'TContext'].join(', ')
73
95
  const returnType = `UseMutationResult<${generics}>`
74
96
 
75
- const mutationOptionsConfigNode = MutationOptions.getParams(node, tsResolver)
97
+ const mutationOptionsConfigNode = buildMutationConfigParamsNode(node, tsResolver)
76
98
  const mutationOptionsParamsCall = callPrinter.print(mutationOptionsConfigNode) ?? ''
77
99
 
78
- const paramsNode = getParams(node, { paramsCasing, dataReturnType, resolver: tsResolver })
100
+ const paramsNode = buildMutationParamsNode(node, { paramsCasing, dataReturnType, resolver: tsResolver })
79
101
  const paramsSignature = declarationPrinter.print(paramsNode) ?? ''
80
102
 
81
103
  return (
@@ -86,11 +108,10 @@ export function Mutation({ name, mutationOptionsName, paramsCasing, dataReturnTy
86
108
  const { client: queryClient, ...mutationOptions } = mutation;
87
109
  const mutationKey = mutationOptions.mutationKey ?? ${mutationKeyName}()
88
110
 
89
- const baseOptions = ${mutationOptionsName}(${mutationOptionsParamsCall}) as UseMutationOptions<${generics}>
90
- ${customOptions ? `const customOptions = ${customOptions.name}({ hookName: '${name}', operationId: '${node.operationId}' }) as UseMutationOptions<${generics}>` : ''}
111
+ const baseOptions = ${mutationOptionsName}(${mutationOptionsParamsCall}) as UseMutationOptions<${generics}>${customOptions ? `\n const customOptions = ${customOptions.name}({ hookName: '${name}', operationId: '${node.operationId}' }) as UseMutationOptions<${generics}>` : ''}
91
112
 
92
113
  return useMutation<${generics}>({
93
- ...baseOptions,${customOptions ? '\n...customOptions,' : ''}
114
+ ...baseOptions,${customOptions ? '\n ...customOptions,' : ''}
94
115
  mutationKey,
95
116
  ...mutationOptions,
96
117
  }, queryClient) as ${returnType}
@@ -99,5 +120,3 @@ export function Mutation({ name, mutationOptionsName, paramsCasing, dataReturnTy
99
120
  </File.Source>
100
121
  )
101
122
  }
102
-
103
- Mutation.getParams = getParams
@@ -4,7 +4,7 @@ import { functionPrinter } from '@kubb/plugin-ts'
4
4
  import { File, Function } from '@kubb/renderer-jsx'
5
5
  import type { KubbReactNode } from '@kubb/renderer-jsx/types'
6
6
  import type { PluginReactQuery } from '../types.ts'
7
- import { buildMutationArgParams, resolveErrorNames } from '../utils.ts'
7
+ import { buildRequestConfigType, buildStatusUnionType, resolveErrorNames, resolveSuccessNames } from '../utils.ts'
8
8
 
9
9
  type Props = {
10
10
  name: string
@@ -22,15 +22,14 @@ const declarationPrinter = functionPrinter({ mode: 'declaration' })
22
22
  const callPrinter = functionPrinter({ mode: 'call' })
23
23
  const keysPrinter = functionPrinter({ mode: 'keys' })
24
24
 
25
- function getConfigParam(node: ast.OperationNode, resolver: ResolverTs): ast.FunctionParametersNode {
26
- const requestName = node.requestBody?.content?.[0]?.schema ? resolver.resolveDataName(node) : undefined
25
+ export function buildMutationConfigParamsNode(node: ast.OperationNode, resolver: ResolverTs): ast.FunctionParametersNode {
27
26
  return ast.createFunctionParameters({
28
27
  params: [
29
28
  ast.createFunctionParameter({
30
29
  name: 'config',
31
30
  type: ast.createParamsType({
32
31
  variant: 'reference',
33
- name: requestName ? `Partial<RequestConfig<${requestName}>> & { client?: Client }` : 'Partial<RequestConfig> & { client?: Client }',
32
+ name: buildRequestConfigType(node, resolver),
34
33
  }),
35
34
  default: '{}',
36
35
  }),
@@ -49,15 +48,21 @@ export function MutationOptions({
49
48
  pathParamsType,
50
49
  mutationKeyName,
51
50
  }: Props): KubbReactNode {
52
- const responseName = tsResolver.resolveResponseName(node)
53
- const TData = dataReturnType === 'data' ? responseName : `ResponseConfig<${responseName}>`
51
+ const successNames = resolveSuccessNames(node, tsResolver)
52
+ const responseName = successNames.length > 0 ? successNames.join(' | ') : tsResolver.resolveResponseName(node)
53
+ const TData = dataReturnType === 'data' ? responseName : buildStatusUnionType(node, tsResolver)
54
54
  const errorNames = resolveErrorNames(node, tsResolver)
55
55
  const TError = `ResponseErrorConfig<${errorNames.length > 0 ? errorNames.join(' | ') : 'Error'}>`
56
56
 
57
- const configParamsNode = getConfigParam(node, tsResolver)
57
+ const configParamsNode = buildMutationConfigParamsNode(node, tsResolver)
58
58
  const paramsSignature = declarationPrinter.print(configParamsNode) ?? ''
59
59
 
60
- const mutationArgParamsNode = buildMutationArgParams(node, { paramsCasing, resolver: tsResolver })
60
+ const mutationArgParamsNode = ast.createOperationParams(node, {
61
+ paramsType: 'inline',
62
+ pathParamsType: 'inline',
63
+ paramsCasing,
64
+ resolver: tsResolver,
65
+ })
61
66
  const hasMutationParams = mutationArgParamsNode.params.length > 0
62
67
 
63
68
  const TRequest = hasMutationParams ? (declarationPrinter.print(mutationArgParamsNode) ?? '') : ''
@@ -73,9 +78,7 @@ export function MutationOptions({
73
78
  name: 'config',
74
79
  type: ast.createParamsType({
75
80
  variant: 'reference',
76
- name: node.requestBody?.content?.[0]?.schema
77
- ? `Partial<RequestConfig<${tsResolver.resolveDataName(node)}>> & { client?: Client }`
78
- : 'Partial<RequestConfig> & { client?: Client }',
81
+ name: buildRequestConfigType(node, tsResolver),
79
82
  }),
80
83
  default: '{}',
81
84
  }),
@@ -88,7 +91,7 @@ export function MutationOptions({
88
91
  <Function name={name} export params={paramsSignature} generics={['TContext = unknown']}>
89
92
  {`
90
93
  const mutationKey = ${mutationKeyName}()
91
- return mutationOptions<${TData}, ${TError}, ${TRequest ? `{${TRequest}}` : 'void'}, TContext>({
94
+ return mutationOptions<${TData}, ${TError}, ${TRequest ? `{${TRequest}}` : 'undefined'}, TContext>({
92
95
  mutationKey,
93
96
  mutationFn: async(${hasMutationParams ? `{ ${argKeysStr} }` : '_'}) => {
94
97
  return ${clientName}(${clientCallStr})
@@ -99,5 +102,3 @@ export function MutationOptions({
99
102
  </File.Source>
100
103
  )
101
104
  }
102
-
103
- MutationOptions.getParams = getConfigParam
@@ -4,8 +4,8 @@ import { functionPrinter } from '@kubb/plugin-ts'
4
4
  import { File, Function } from '@kubb/renderer-jsx'
5
5
  import type { KubbReactNode } from '@kubb/renderer-jsx/types'
6
6
  import type { PluginReactQuery } from '../types.ts'
7
- import { getComments, resolveErrorNames } from '../utils.ts'
8
- import { QueryKey } from './QueryKey.tsx'
7
+ import { getEnabledParamNames, markParamsOptional } from '@internals/tanstack-query'
8
+ import { buildQueryKeyParams, buildStatusUnionType, getComments, resolveErrorNames, resolveSuccessNames } from '../utils.ts'
9
9
  import { getQueryOptionsParams } from './QueryOptions.tsx'
10
10
 
11
11
  type Props = {
@@ -25,7 +25,7 @@ type Props = {
25
25
  const declarationPrinter = functionPrinter({ mode: 'declaration' })
26
26
  const callPrinter = functionPrinter({ mode: 'call' })
27
27
 
28
- function getParams(
28
+ function buildQueryParamsNode(
29
29
  node: ast.OperationNode,
30
30
  options: {
31
31
  paramsType: PluginReactQuery['resolvedOptions']['paramsType']
@@ -36,11 +36,12 @@ function getParams(
36
36
  },
37
37
  ): ast.FunctionParametersNode {
38
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
39
+ const successNames = resolveSuccessNames(node, resolver)
40
+ const responseName = successNames.length > 0 ? successNames.join(' | ') : resolver.resolveResponseName(node)
41
+ const requestName = node.requestBody?.content?.[0]?.schema ? resolver.resolveDataName(node) : null
41
42
  const errorNames = resolveErrorNames(node, resolver)
42
43
 
43
- const TData = dataReturnType === 'data' ? responseName : `ResponseConfig<${responseName}>`
44
+ const TData = dataReturnType === 'data' ? responseName : buildStatusUnionType(node, resolver)
44
45
  const TError = `ResponseErrorConfig<${errorNames.length > 0 ? errorNames.join(' | ') : 'Error'}>`
45
46
 
46
47
  const optionsParam = ast.createFunctionParameter({
@@ -77,21 +78,26 @@ export function Query({
77
78
  tsResolver,
78
79
  customOptions,
79
80
  }: Props): KubbReactNode {
80
- const responseName = tsResolver.resolveResponseName(node)
81
+ const successNames = resolveSuccessNames(node, tsResolver)
82
+ const responseName = successNames.length > 0 ? successNames.join(' | ') : tsResolver.resolveResponseName(node)
81
83
  const errorNames = resolveErrorNames(node, tsResolver)
82
84
 
83
- const TData = dataReturnType === 'data' ? responseName : `ResponseConfig<${responseName}>`
85
+ const TData = dataReturnType === 'data' ? responseName : buildStatusUnionType(node, tsResolver)
84
86
  const TError = `ResponseErrorConfig<${errorNames.length > 0 ? errorNames.join(' | ') : 'Error'}>`
85
87
  const returnType = `UseQueryResult<${'TData'}, ${TError}> & { queryKey: TQueryKey }`
86
88
  const generics = [`TData = ${TData}`, `TQueryData = ${TData}`, `TQueryKey extends QueryKey = ${queryKeyTypeName}`]
87
89
 
88
- const queryKeyParamsNode = QueryKey.getParams(node, { pathParamsType, paramsCasing, resolver: tsResolver })
90
+ const queryKeyParamsNode = buildQueryKeyParams(node, { pathParamsType, paramsCasing, resolver: tsResolver })
89
91
  const queryKeyParamsCall = callPrinter.print(queryKeyParamsNode) ?? ''
92
+ const enabledNames = getEnabledParamNames(queryKeyParamsNode)
90
93
 
91
94
  const queryOptionsParamsNode = getQueryOptionsParams(node, { paramsType, paramsCasing, pathParamsType, resolver: tsResolver })
92
95
  const queryOptionsParamsCall = callPrinter.print(queryOptionsParamsNode) ?? ''
93
96
 
94
- const paramsNode = getParams(node, { paramsType, paramsCasing, pathParamsType, dataReturnType, resolver: tsResolver })
97
+ const paramsNode = markParamsOptional(
98
+ buildQueryParamsNode(node, { paramsType, paramsCasing, pathParamsType, dataReturnType, resolver: tsResolver }),
99
+ enabledNames,
100
+ )
95
101
  const paramsSignature = declarationPrinter.print(paramsNode) ?? ''
96
102
 
97
103
  return (
@@ -100,11 +106,10 @@ export function Query({
100
106
  {`
101
107
  const { query: queryConfig = {}, client: config = {} } = options ?? {}
102
108
  const { client: queryClient, ...resolvedOptions } = queryConfig
103
- const queryKey = resolvedOptions?.queryKey ?? ${queryKeyName}(${queryKeyParamsCall})
104
- ${customOptions ? `const customOptions = ${customOptions.name}({ hookName: '${name}', operationId: '${node.operationId}' })` : ''}
109
+ const queryKey = resolvedOptions?.queryKey ?? ${queryKeyName}(${queryKeyParamsCall})${customOptions ? `\n const customOptions = ${customOptions.name}({ hookName: '${name}', operationId: '${node.operationId}' })` : ''}
105
110
 
106
111
  const query = useQuery({
107
- ...${queryOptionsName}(${queryOptionsParamsCall}),${customOptions ? '\n...customOptions,' : ''}
112
+ ...${queryOptionsName}(${queryOptionsParamsCall}),${customOptions ? '\n ...customOptions,' : ''}
108
113
  ...resolvedOptions,
109
114
  queryKey,
110
115
  } as unknown as QueryObserverOptions, queryClient) as ${returnType}
@@ -117,5 +122,3 @@ export function Query({
117
122
  </File.Source>
118
123
  )
119
124
  }
120
-
121
- Query.getParams = getParams
@@ -1,11 +1,11 @@
1
- import { ast } from '@kubb/core'
1
+ import type { ast } from '@kubb/core'
2
2
  import type { ResolverTs } from '@kubb/plugin-ts'
3
3
  import { functionPrinter } from '@kubb/plugin-ts'
4
4
  import { File, Function } from '@kubb/renderer-jsx'
5
5
  import type { KubbReactNode } from '@kubb/renderer-jsx/types'
6
+ import { buildQueryOptionsParams, getEnabledParamNames, injectNonNullAssertions, markParamsOptional } from '@internals/tanstack-query'
6
7
  import type { PluginReactQuery } from '../types.ts'
7
- import { resolveErrorNames } from '../utils.ts'
8
- import { QueryKey } from './QueryKey.tsx'
8
+ import { buildQueryKeyParams, buildStatusUnionType, resolveErrorNames, resolveSuccessNames } from '../utils.ts'
9
9
 
10
10
  type Props = {
11
11
  name: string
@@ -17,6 +17,7 @@ type Props = {
17
17
  paramsType: PluginReactQuery['resolvedOptions']['paramsType']
18
18
  pathParamsType: PluginReactQuery['resolvedOptions']['pathParamsType']
19
19
  dataReturnType: PluginReactQuery['resolvedOptions']['client']['dataReturnType']
20
+ suspense?: boolean
20
21
  }
21
22
 
22
23
  const declarationPrinter = functionPrinter({ mode: 'declaration' })
@@ -31,45 +32,7 @@ export function getQueryOptionsParams(
31
32
  resolver: ResolverTs
32
33
  },
33
34
  ): ast.FunctionParametersNode {
34
- const { paramsType, paramsCasing, pathParamsType, resolver } = options
35
- const requestName = node.requestBody?.content?.[0]?.schema ? resolver.resolveDataName(node) : undefined
36
-
37
- return ast.createOperationParams(node, {
38
- paramsType,
39
- pathParamsType: paramsType === 'object' ? 'object' : pathParamsType === 'object' ? 'object' : 'inline',
40
- paramsCasing,
41
- resolver,
42
- extraParams: [
43
- ast.createFunctionParameter({
44
- name: 'config',
45
- type: ast.createParamsType({
46
- variant: 'reference',
47
- name: requestName ? `Partial<RequestConfig<${requestName}>> & { client?: Client }` : 'Partial<RequestConfig> & { client?: Client }',
48
- }),
49
- default: '{}',
50
- }),
51
- ],
52
- })
53
- }
54
-
55
- export function buildEnabledCheck(paramsNode: ast.FunctionParametersNode): string {
56
- const required: string[] = []
57
- for (const param of paramsNode.params) {
58
- if ('kind' in param && (param as ast.ParameterGroupNode).kind === 'ParameterGroup') {
59
- const group = param as ast.ParameterGroupNode
60
- for (const child of group.properties) {
61
- if (!child.optional && child.default === undefined) {
62
- required.push(child.name)
63
- }
64
- }
65
- } else {
66
- const fp = param as ast.FunctionParameterNode
67
- if (!fp.optional && fp.default === undefined) {
68
- required.push(fp.name)
69
- }
70
- }
71
- }
72
- return required.join(' && ')
35
+ return buildQueryOptionsParams(node, options)
73
36
  }
74
37
 
75
38
  export function QueryOptions({
@@ -82,31 +45,34 @@ export function QueryOptions({
82
45
  paramsType,
83
46
  pathParamsType,
84
47
  queryKeyName,
48
+ suspense,
85
49
  }: Props): KubbReactNode {
86
- const responseName = tsResolver.resolveResponseName(node)
50
+ const successNames = resolveSuccessNames(node, tsResolver)
51
+ const responseName = successNames.length > 0 ? successNames.join(' | ') : tsResolver.resolveResponseName(node)
87
52
  const errorNames = resolveErrorNames(node, tsResolver)
88
53
 
89
- const TData = dataReturnType === 'data' ? responseName : `ResponseConfig<${responseName}>`
54
+ const TData = dataReturnType === 'data' ? responseName : buildStatusUnionType(node, tsResolver)
90
55
  const TError = `ResponseErrorConfig<${errorNames.length > 0 ? errorNames.join(' | ') : 'Error'}>`
91
56
 
92
- const paramsNode = getQueryOptionsParams(node, { paramsType, paramsCasing, pathParamsType, resolver: tsResolver })
93
- const paramsSignature = declarationPrinter.print(paramsNode) ?? ''
94
- const rawParamsCall = callPrinter.print(paramsNode) ?? ''
95
- const clientCallStr = rawParamsCall.replace(/\bconfig\b(?=[^,]*$)/, '{ ...config, signal: config.signal ?? signal }')
96
-
97
- const queryKeyParamsNode = QueryKey.getParams(node, { pathParamsType, paramsCasing, resolver: tsResolver })
57
+ const queryKeyParamsNode = buildQueryKeyParams(node, { pathParamsType, paramsCasing, resolver: tsResolver })
98
58
  const queryKeyParamsCall = callPrinter.print(queryKeyParamsNode) ?? ''
99
59
 
100
- const enabledSource = buildEnabledCheck(queryKeyParamsNode)
101
- const enabledText = enabledSource ? `enabled: !!(${enabledSource}),` : ''
60
+ const enabledNames = getEnabledParamNames(queryKeyParamsNode)
61
+ // Suspense queries can't be disabled, so their params stay required.
62
+ const optionalNames = suspense ? [] : enabledNames
63
+ const enabledText = suspense ? '' : enabledNames.length ? `enabled: !!(${enabledNames.join(' && ')}),` : ''
64
+
65
+ const paramsNode = markParamsOptional(getQueryOptionsParams(node, { paramsType, paramsCasing, pathParamsType, resolver: tsResolver }), optionalNames)
66
+ const paramsSignature = declarationPrinter.print(paramsNode) ?? ''
67
+ const rawParamsCall = callPrinter.print(paramsNode) ?? ''
68
+ const clientCallStr = injectNonNullAssertions(rawParamsCall.replace(/\bconfig\b(?=[^,]*$)/, '{ ...config, signal: config.signal ?? signal }'), optionalNames)
102
69
 
103
70
  return (
104
71
  <File.Source name={name} isExportable isIndexable>
105
72
  <Function name={name} export params={paramsSignature}>
106
73
  {`
107
74
  const queryKey = ${queryKeyName}(${queryKeyParamsCall})
108
- return queryOptions<${TData}, ${TError}, ${TData}, typeof queryKey>({
109
- ${enabledText}
75
+ return queryOptions<${TData}, ${TError}, ${TData}, typeof queryKey>({${enabledText ? `\n ${enabledText}` : ''}
110
76
  queryKey,
111
77
  queryFn: async ({ signal }) => {
112
78
  return ${clientName}(${clientCallStr})
@@ -117,5 +83,3 @@ export function QueryOptions({
117
83
  </File.Source>
118
84
  )
119
85
  }
120
-
121
- QueryOptions.getParams = getQueryOptionsParams