@kubb/plugin-vue-query 5.0.0-alpha.9 → 5.0.0-beta.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/LICENSE +17 -10
  2. package/README.md +26 -7
  3. package/dist/components-B6jAb2as.js +1150 -0
  4. package/dist/components-B6jAb2as.js.map +1 -0
  5. package/dist/components-X0P-3W2G.cjs +1264 -0
  6. package/dist/components-X0P-3W2G.cjs.map +1 -0
  7. package/dist/components.cjs +1 -1
  8. package/dist/components.d.ts +66 -121
  9. package/dist/components.js +1 -1
  10. package/dist/generators-B33PbKzu.js +681 -0
  11. package/dist/generators-B33PbKzu.js.map +1 -0
  12. package/dist/generators-BE3KD0IR.cjs +698 -0
  13. package/dist/generators-BE3KD0IR.cjs.map +1 -0
  14. package/dist/generators.cjs +1 -1
  15. package/dist/generators.d.ts +5 -501
  16. package/dist/generators.js +1 -1
  17. package/dist/index.cjs +150 -121
  18. package/dist/index.cjs.map +1 -1
  19. package/dist/index.d.ts +4 -4
  20. package/dist/index.js +146 -121
  21. package/dist/index.js.map +1 -1
  22. package/dist/types-Bkm7bWT3.d.ts +243 -0
  23. package/extension.yaml +732 -0
  24. package/package.json +60 -65
  25. package/src/components/InfiniteQuery.tsx +71 -159
  26. package/src/components/InfiniteQueryOptions.tsx +115 -163
  27. package/src/components/Mutation.tsx +97 -134
  28. package/src/components/Query.tsx +68 -157
  29. package/src/components/QueryKey.tsx +23 -66
  30. package/src/components/QueryOptions.tsx +92 -143
  31. package/src/generators/infiniteQueryGenerator.tsx +152 -171
  32. package/src/generators/mutationGenerator.tsx +102 -125
  33. package/src/generators/queryGenerator.tsx +125 -137
  34. package/src/index.ts +1 -1
  35. package/src/plugin.ts +126 -177
  36. package/src/resolvers/resolverVueQuery.ts +65 -0
  37. package/src/types.ts +121 -52
  38. package/src/utils.ts +49 -0
  39. package/dist/components-Yjoe78Y7.cjs +0 -1119
  40. package/dist/components-Yjoe78Y7.cjs.map +0 -1
  41. package/dist/components-_AMBl0g-.js +0 -1029
  42. package/dist/components-_AMBl0g-.js.map +0 -1
  43. package/dist/generators-CR34GjVu.js +0 -661
  44. package/dist/generators-CR34GjVu.js.map +0 -1
  45. package/dist/generators-DH8VkK1q.cjs +0 -678
  46. package/dist/generators-DH8VkK1q.cjs.map +0 -1
  47. package/dist/types-CgDFUvfZ.d.ts +0 -211
@@ -1,18 +1,22 @@
1
+ import { getOperationParameters } from '@internals/shared'
1
2
  import { getNestedAccessor } from '@internals/utils'
2
- import { getDefaultValue, 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, PluginVueQuery } from '../types.ts'
9
- import { QueryKey } from './QueryKey.tsx'
9
+ import { resolveErrorNames } from '../utils.ts'
10
+ import { buildQueryKeyParamsNode } from './QueryKey.tsx'
11
+ import { buildEnabledCheck } from '@internals/tanstack-query'
12
+ import { getQueryOptionsParams } from './QueryOptions.tsx'
10
13
 
11
14
  type Props = {
12
15
  name: string
13
16
  clientName: string
14
17
  queryKeyName: string
15
- typeSchemas: OperationSchemas
18
+ node: ast.OperationNode
19
+ tsResolver: ResolverTs
16
20
  paramsCasing: PluginVueQuery['resolvedOptions']['paramsCasing']
17
21
  paramsType: PluginVueQuery['resolvedOptions']['paramsType']
18
22
  pathParamsType: PluginVueQuery['resolvedOptions']['pathParamsType']
@@ -24,105 +28,8 @@ type Props = {
24
28
  queryParam: Infinite['queryParam']
25
29
  }
26
30
 
27
- type GetParamsProps = {
28
- paramsCasing: PluginVueQuery['resolvedOptions']['paramsCasing']
29
- paramsType: PluginVueQuery['resolvedOptions']['paramsType']
30
- pathParamsType: PluginVueQuery['resolvedOptions']['pathParamsType']
31
- typeSchemas: OperationSchemas
32
- }
33
-
34
- function getParams({ paramsType, paramsCasing, pathParamsType, typeSchemas }: GetParamsProps) {
35
- if (paramsType === 'object') {
36
- const children = {
37
- ...getPathParams(typeSchemas.pathParams, {
38
- typed: true,
39
- casing: paramsCasing,
40
- override(item) {
41
- return {
42
- ...item,
43
- type: `MaybeRefOrGetter<${item.type}>`,
44
- }
45
- },
46
- }),
47
- data: typeSchemas.request?.name
48
- ? {
49
- type: `MaybeRefOrGetter<${typeSchemas.request?.name}>`,
50
- optional: isOptional(typeSchemas.request?.schema),
51
- }
52
- : undefined,
53
- params: typeSchemas.queryParams?.name
54
- ? {
55
- type: `MaybeRefOrGetter<${typeSchemas.queryParams?.name}>`,
56
- optional: isOptional(typeSchemas.queryParams?.schema),
57
- }
58
- : undefined,
59
- headers: typeSchemas.headerParams?.name
60
- ? {
61
- type: `MaybeRefOrGetter<${typeSchemas.queryParams?.name}>`,
62
- optional: isOptional(typeSchemas.headerParams?.schema),
63
- }
64
- : undefined,
65
- }
66
-
67
- // Check if all children are optional or undefined
68
- const allChildrenAreOptional = Object.values(children).every((child) => !child || child.optional)
69
-
70
- return FunctionParams.factory({
71
- data: {
72
- mode: 'object',
73
- children,
74
- default: allChildrenAreOptional ? '{}' : undefined,
75
- },
76
- config: {
77
- type: typeSchemas.request?.name
78
- ? `Partial<RequestConfig<${typeSchemas.request?.name}>> & { client?: Client }`
79
- : 'Partial<RequestConfig> & { client?: Client }',
80
- default: '{}',
81
- },
82
- })
83
- }
84
-
85
- return FunctionParams.factory({
86
- pathParams: {
87
- mode: pathParamsType === 'object' ? 'object' : 'inlineSpread',
88
- children: getPathParams(typeSchemas.pathParams, {
89
- typed: true,
90
- casing: paramsCasing,
91
- override(item) {
92
- return {
93
- ...item,
94
- type: `MaybeRefOrGetter<${item.type}>`,
95
- }
96
- },
97
- }),
98
- default: getDefaultValue(typeSchemas.pathParams?.schema),
99
- },
100
- data: typeSchemas.request?.name
101
- ? {
102
- type: `MaybeRefOrGetter<${typeSchemas.request?.name}>`,
103
- optional: isOptional(typeSchemas.request?.schema),
104
- }
105
- : undefined,
106
- params: typeSchemas.queryParams?.name
107
- ? {
108
- type: `MaybeRefOrGetter<${typeSchemas.queryParams?.name}>`,
109
- optional: isOptional(typeSchemas.queryParams?.schema),
110
- }
111
- : undefined,
112
- headers: typeSchemas.headerParams?.name
113
- ? {
114
- type: `MaybeRefOrGetter<${typeSchemas.headerParams?.name}>`,
115
- optional: isOptional(typeSchemas.headerParams?.schema),
116
- }
117
- : undefined,
118
- config: {
119
- type: typeSchemas.request?.name
120
- ? `Partial<RequestConfig<${typeSchemas.request?.name}>> & { client?: Client }`
121
- : 'Partial<RequestConfig> & { client?: Client }',
122
- default: '{}',
123
- },
124
- })
125
- }
31
+ const declarationPrinter = functionPrinter({ mode: 'declaration' })
32
+ const callPrinter = functionPrinter({ mode: 'call' })
126
33
 
127
34
  export function InfiniteQueryOptions({
128
35
  name,
@@ -131,39 +38,65 @@ export function InfiniteQueryOptions({
131
38
  cursorParam,
132
39
  nextParam,
133
40
  previousParam,
134
- typeSchemas,
135
- paramsType,
41
+ node,
42
+ tsResolver,
136
43
  paramsCasing,
44
+ paramsType,
137
45
  dataReturnType,
138
46
  pathParamsType,
139
47
  queryParam,
140
48
  queryKeyName,
141
- }: Props): FabricReactNode {
142
- const TData = dataReturnType === 'data' ? typeSchemas.response.name : `ResponseConfig<${typeSchemas.response.name}>`
143
- const TError = `ResponseErrorConfig<${typeSchemas.errors?.map((item) => item.name).join(' | ') || 'Error'}>`
144
-
145
- const params = getParams({ paramsType, paramsCasing, pathParamsType, typeSchemas })
146
- const clientParams = Client.getParams({
147
- paramsType,
148
- paramsCasing,
149
- typeSchemas,
150
- pathParamsType,
151
- isConfigurable: true,
152
- })
153
- const queryKeyParams = QueryKey.getParams({
154
- paramsCasing,
155
- pathParamsType,
156
- typeSchemas,
157
- })
49
+ }: Props): KubbReactNode {
50
+ const responseName = tsResolver.resolveResponseName(node)
51
+ const queryFnDataType = dataReturnType === 'data' ? responseName : `ResponseConfig<${responseName}>`
52
+ const errorNames = resolveErrorNames(node, tsResolver)
53
+ const errorType = `ResponseErrorConfig<${errorNames.length > 0 ? errorNames.join(' | ') : 'Error'}>`
54
+
55
+ const isInitialPageParamDefined = initialPageParam !== undefined && initialPageParam !== null
56
+ const fallbackPageParamType =
57
+ typeof initialPageParam === 'number'
58
+ ? 'number'
59
+ : typeof initialPageParam === 'string'
60
+ ? initialPageParam.includes(' as ')
61
+ ? (() => {
62
+ const parts = initialPageParam.split(' as ')
63
+ return parts[parts.length - 1] ?? 'unknown'
64
+ })()
65
+ : 'string'
66
+ : typeof initialPageParam === 'boolean'
67
+ ? 'boolean'
68
+ : 'unknown'
69
+
70
+ const rawQueryParams = getOperationParameters(node).query
71
+ const queryParamsTypeName =
72
+ rawQueryParams.length > 0
73
+ ? (() => {
74
+ const groupName = tsResolver.resolveQueryParamsName(node, rawQueryParams[0]!)
75
+ const individualName = tsResolver.resolveParamName(node, rawQueryParams[0]!)
76
+ return groupName !== individualName ? groupName : undefined
77
+ })()
78
+ : undefined
79
+
80
+ const queryParamType = queryParam && queryParamsTypeName ? `${queryParamsTypeName}['${queryParam}']` : undefined
81
+ const pageParamType = queryParamType ? (isInitialPageParamDefined ? `NonNullable<${queryParamType}>` : queryParamType) : fallbackPageParamType
82
+
83
+ const paramsNode = getQueryOptionsParams(node, { paramsType, paramsCasing, pathParamsType, resolver: tsResolver })
84
+ const paramsSignature = declarationPrinter.print(paramsNode) ?? ''
85
+ const rawParamsCall = callPrinter.print(paramsNode) ?? ''
86
+ const clientCallStr = rawParamsCall.replace(/\bconfig\b(?=[^,]*$)/, '{ ...config, signal: config.signal ?? signal }')
87
+
88
+ const queryKeyParamsNode = buildQueryKeyParamsNode(node, { pathParamsType, paramsCasing, resolver: tsResolver })
89
+ const queryKeyParamsCall = callPrinter.print(queryKeyParamsNode) ?? ''
90
+
91
+ const enabledSource = buildEnabledCheck(queryKeyParamsNode)
92
+ const enabledText = enabledSource ? `enabled: () => !!(${enabledSource}),` : ''
158
93
 
159
- // Determine if we should use the new nextParam/previousParam or fall back to legacy cursorParam behavior
160
94
  const hasNewParams = nextParam !== undefined || previousParam !== undefined
161
95
 
162
96
  let getNextPageParamExpr: string | undefined
163
97
  let getPreviousPageParamExpr: string | undefined
164
98
 
165
99
  if (hasNewParams) {
166
- // Use the new nextParam and previousParam
167
100
  if (nextParam) {
168
101
  const accessor = getNestedAccessor(nextParam, 'lastPage')
169
102
  if (accessor) {
@@ -177,11 +110,9 @@ export function InfiniteQueryOptions({
177
110
  }
178
111
  }
179
112
  } else if (cursorParam) {
180
- // Legacy behavior: use cursorParam for both next and previous
181
113
  getNextPageParamExpr = `getNextPageParam: (lastPage) => lastPage['${cursorParam}']`
182
114
  getPreviousPageParamExpr = `getPreviousPageParam: (firstPage) => firstPage['${cursorParam}']`
183
115
  } else {
184
- // Fallback behavior: page-based pagination
185
116
  if (dataReturnType === 'full') {
186
117
  getNextPageParamExpr =
187
118
  'getNextPageParam: (lastPage, _allPages, lastPageParam) => Array.isArray(lastPage.data) && lastPage.data.length === 0 ? undefined : lastPageParam + 1'
@@ -192,53 +123,54 @@ export function InfiniteQueryOptions({
192
123
  getPreviousPageParamExpr = 'getPreviousPageParam: (_firstPage, _allPages, firstPageParam) => firstPageParam <= 1 ? undefined : firstPageParam - 1'
193
124
  }
194
125
 
195
- const queryOptions = [
126
+ const queryOptionsArr = [
196
127
  `initialPageParam: ${typeof initialPageParam === 'string' ? JSON.stringify(initialPageParam) : initialPageParam}`,
197
128
  getNextPageParamExpr,
198
129
  getPreviousPageParamExpr,
199
130
  ].filter(Boolean)
200
131
 
201
132
  const infiniteOverrideParams =
202
- queryParam && typeSchemas.queryParams?.name
133
+ queryParam && queryParamsTypeName
203
134
  ? `
204
- if (!params) {
205
- params = { }
206
- }
207
- params['${queryParam}'] = pageParam as unknown as ${typeSchemas.queryParams?.name}['${queryParam}']`
135
+ params = {
136
+ ...(params ?? {}),
137
+ ['${queryParam}']: pageParam as unknown as ${queryParamsTypeName}['${queryParam}'],
138
+ } as ${queryParamsTypeName}`
208
139
  : ''
209
140
 
210
- const enabled = Object.entries(queryKeyParams.flatParams)
211
- .map(([key, item]) => {
212
- // Only include if the parameter exists and is NOT optional
213
- // This ensures we only check required parameters
214
- return item && !item.optional && !item.default ? key : undefined
215
- })
216
- .filter(Boolean)
217
- .join('&& ')
218
-
219
- const enabledText = enabled ? `enabled: !!(${enabled}),` : ''
141
+ if (infiniteOverrideParams) {
142
+ return (
143
+ <File.Source name={name} isExportable isIndexable>
144
+ <Function name={name} export params={paramsSignature}>
145
+ {`
146
+ const queryKey = ${queryKeyName}(${queryKeyParamsCall})
147
+ return infiniteQueryOptions<${queryFnDataType}, ${errorType}, InfiniteData<${queryFnDataType}>, QueryKey, ${pageParamType}>({
148
+ ${enabledText}
149
+ queryKey,
150
+ queryFn: async ({ signal, pageParam }) => {
151
+ ${infiniteOverrideParams}
152
+ return ${clientName}(${addToValueCalls(clientCallStr)})
153
+ },
154
+ ${queryOptionsArr.join(',\n')}
155
+ })
156
+ `}
157
+ </Function>
158
+ </File.Source>
159
+ )
160
+ }
220
161
 
221
162
  return (
222
163
  <File.Source name={name} isExportable isIndexable>
223
- <Function name={name} export params={params.toConstructor()}>
164
+ <Function name={name} export params={paramsSignature}>
224
165
  {`
225
- const queryKey = ${queryKeyName}(${queryKeyParams.toCall()})
226
- return infiniteQueryOptions<${TData}, ${TError}, ${TData}, typeof queryKey, number>({
166
+ const queryKey = ${queryKeyName}(${queryKeyParamsCall})
167
+ return infiniteQueryOptions<${queryFnDataType}, ${errorType}, InfiniteData<${queryFnDataType}>, QueryKey, ${pageParamType}>({
227
168
  ${enabledText}
228
169
  queryKey,
229
- queryFn: async ({ signal, pageParam }) => {
230
- ${infiniteOverrideParams}
231
- return ${clientName}(${clientParams.toCall({
232
- transformName(name) {
233
- if (name === 'config') {
234
- return '{ ...config, signal: config.signal ?? signal }'
235
- }
236
-
237
- return `toValue(${name})`
238
- },
239
- })})
240
- },
241
- ${queryOptions.join(',\n')}
170
+ queryFn: async ({ signal }) => {
171
+ return ${clientName}(${addToValueCalls(clientCallStr)})
172
+ },
173
+ ${queryOptionsArr.join(',\n')}
242
174
  })
243
175
  `}
244
176
  </Function>
@@ -246,4 +178,24 @@ export function InfiniteQueryOptions({
246
178
  )
247
179
  }
248
180
 
249
- InfiniteQueryOptions.getParams = getParams
181
+ function addToValueCalls(callStr: string): string {
182
+ // Step 1: Transform shorthand object params like { petId } → { petId: toValue(petId) }
183
+ let result = callStr.replace(/\{\s*([\w,\s]+)\s*\}(?=\s*,)/g, (match, inner: string) => {
184
+ if (inner.includes(':') || inner.includes('...')) return match
185
+ const keys = inner
186
+ .split(',')
187
+ .map((k: string) => k.trim())
188
+ .filter(Boolean)
189
+ const wrapped = keys.map((k: string) => `${k}: toValue(${k})`).join(', ')
190
+ return `{ ${wrapped} }`
191
+ })
192
+
193
+ // Step 2: Handle standalone identifiers like `data, params`
194
+ result = result.replace(/(?<![{.:?])\b(\w+)\b(?=\s*,)/g, (match, name: string) => {
195
+ if (name === 'config' || name === 'signal' || name === 'undefined') return match
196
+ if (match.includes('toValue(')) return match
197
+ return `toValue(${name})`
198
+ })
199
+
200
+ return result
201
+ }
@@ -1,81 +1,77 @@
1
- import { isOptional, type Operation } from '@kubb/oas'
2
- import { Client } from '@kubb/plugin-client/components'
3
- import type { OperationSchemas } from '@kubb/plugin-oas'
4
- import { getComments, getPathParams } from '@kubb/plugin-oas/utils'
5
- import { File, Function, FunctionParams } from '@kubb/react-fabric'
6
- import type { FabricReactNode, Params } 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'
7
6
  import type { PluginVueQuery } from '../types.ts'
8
- import { MutationKey } from './MutationKey.tsx'
7
+ import { buildRequestConfigType, getComments, resolveErrorNames, wrapWithMaybeRefOrGetter } from '../utils.ts'
9
8
 
10
9
  type Props = {
11
- /**
12
- * Name of the function
13
- */
14
10
  name: string
15
11
  typeName: string
16
12
  clientName: string
17
13
  mutationKeyName: string
18
- typeSchemas: OperationSchemas
19
- operation: Operation
14
+ node: ast.OperationNode
15
+ tsResolver: ResolverTs
20
16
  paramsCasing: PluginVueQuery['resolvedOptions']['paramsCasing']
21
17
  paramsType: PluginVueQuery['resolvedOptions']['paramsType']
22
18
  dataReturnType: PluginVueQuery['resolvedOptions']['client']['dataReturnType']
23
19
  pathParamsType: PluginVueQuery['resolvedOptions']['pathParamsType']
24
20
  }
25
21
 
26
- type GetParamsProps = {
27
- paramsCasing: PluginVueQuery['resolvedOptions']['paramsCasing']
28
- pathParamsType: PluginVueQuery['resolvedOptions']['pathParamsType']
29
- dataReturnType: PluginVueQuery['resolvedOptions']['client']['dataReturnType']
30
- typeSchemas: OperationSchemas
31
- }
22
+ const declarationPrinter = functionPrinter({ mode: 'declaration' })
23
+ const callPrinter = functionPrinter({ mode: 'call' })
24
+ const keysPrinter = functionPrinter({ mode: 'keys' })
32
25
 
33
- function getParams({ paramsCasing, dataReturnType, typeSchemas }: GetParamsProps) {
34
- const TData = dataReturnType === 'data' ? typeSchemas.response.name : `ResponseConfig<${typeSchemas.response.name}>`
35
- const TError = `ResponseErrorConfig<${typeSchemas.errors?.map((item) => item.name).join(' | ') || 'Error'}>`
36
-
37
- const mutationParams = FunctionParams.factory({
38
- ...getPathParams(typeSchemas.pathParams, {
39
- typed: true,
40
- casing: paramsCasing,
41
- override(item) {
42
- return {
43
- ...item,
44
- type: `MaybeRefOrGetter<${item.type}>`,
45
- }
46
- },
47
- }),
48
- data: typeSchemas.request?.name
49
- ? {
50
- type: `MaybeRefOrGetter<${typeSchemas.request?.name}>`,
51
- optional: isOptional(typeSchemas.request?.schema),
52
- }
53
- : undefined,
54
- params: typeSchemas.queryParams?.name
55
- ? {
56
- type: `MaybeRefOrGetter<${typeSchemas.queryParams?.name}>`,
57
- optional: isOptional(typeSchemas.queryParams?.schema),
58
- }
59
- : undefined,
60
- headers: typeSchemas.headerParams?.name
61
- ? {
62
- type: `MaybeRefOrGetter<${typeSchemas.headerParams?.name}>`,
63
- optional: isOptional(typeSchemas.headerParams?.schema),
64
- }
65
- : undefined,
26
+ function createMutationArgParams(
27
+ node: ast.OperationNode,
28
+ options: {
29
+ paramsCasing: PluginVueQuery['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,
66
38
  })
67
- const TRequest = mutationParams.toConstructor()
68
-
69
- return FunctionParams.factory({
70
- options: {
71
- type: `
72
- {
73
- mutation?: MutationObserverOptions<${[TData, TError, TRequest ? `{${TRequest}}` : 'void', 'TContext'].join(', ')}> & { client?: QueryClient },
74
- client?: ${typeSchemas.request?.name ? `Partial<RequestConfig<${typeSchemas.request?.name}>> & { client?: Client }` : 'Partial<RequestConfig> & { client?: Client }'},
75
39
  }
76
- `,
77
- default: '{}',
78
- },
40
+
41
+ function buildMutationParamsNode(
42
+ node: ast.OperationNode,
43
+ options: {
44
+ paramsCasing: PluginVueQuery['resolvedOptions']['paramsCasing']
45
+ dataReturnType: PluginVueQuery['resolvedOptions']['client']['dataReturnType']
46
+ resolver: ResolverTs
47
+ },
48
+ ): ast.FunctionParametersNode {
49
+ const { paramsCasing, dataReturnType, resolver } = options
50
+ const responseName = resolver.resolveResponseName(node)
51
+ const errorNames = resolveErrorNames(node, resolver)
52
+
53
+ const TData = dataReturnType === 'data' ? responseName : `ResponseConfig<${responseName}>`
54
+ const TError = `ResponseErrorConfig<${errorNames.length > 0 ? errorNames.join(' | ') : 'Error'}>`
55
+
56
+ const mutationArgParamsNode = createMutationArgParams(node, { paramsCasing, resolver })
57
+
58
+ const wrappedParamsNode = wrapWithMaybeRefOrGetter(mutationArgParamsNode)
59
+ const TRequestWrapped = wrappedParamsNode.params.length > 0 ? (declarationPrinter.print(wrappedParamsNode) ?? '') : ''
60
+
61
+ return ast.createFunctionParameters({
62
+ params: [
63
+ ast.createFunctionParameter({
64
+ name: 'options',
65
+ type: ast.createParamsType({
66
+ variant: 'reference',
67
+ name: `{
68
+ mutation?: MutationObserverOptions<${[TData, TError, TRequestWrapped ? `{${TRequestWrapped}}` : 'void', 'TContext'].join(', ')}> & { client?: QueryClient },
69
+ client?: ${buildRequestConfigType(node, resolver)},
70
+ }`,
71
+ }),
72
+ default: '{}',
73
+ }),
74
+ ],
79
75
  })
80
76
  }
81
77
 
@@ -86,94 +82,61 @@ export function Mutation({
86
82
  paramsType,
87
83
  pathParamsType,
88
84
  dataReturnType,
89
- typeSchemas,
90
- operation,
85
+ node,
86
+ tsResolver,
91
87
  mutationKeyName,
92
- }: Props): FabricReactNode {
93
- const mutationKeyParams = MutationKey.getParams({
94
- pathParamsType,
95
- typeSchemas,
96
- })
88
+ }: Props): KubbReactNode {
89
+ const responseName = tsResolver.resolveResponseName(node)
90
+ const errorNames = resolveErrorNames(node, tsResolver)
97
91
 
98
- const params = getParams({
99
- paramsCasing,
100
- pathParamsType,
101
- dataReturnType,
102
- typeSchemas,
103
- })
92
+ const TData = dataReturnType === 'data' ? responseName : `ResponseConfig<${responseName}>`
93
+ const TError = `ResponseErrorConfig<${errorNames.length > 0 ? errorNames.join(' | ') : 'Error'}>`
104
94
 
105
- const clientParams = Client.getParams({
95
+ const mutationArgParamsNode = createMutationArgParams(node, {
106
96
  paramsCasing,
107
- paramsType,
108
- typeSchemas,
109
- pathParamsType,
110
- isConfigurable: true,
97
+ resolver: tsResolver,
111
98
  })
99
+ const hasMutationParams = mutationArgParamsNode.params.length > 0
100
+ const TRequest = hasMutationParams ? (declarationPrinter.print(mutationArgParamsNode) ?? '') : ''
101
+ const argKeysStr = hasMutationParams ? (keysPrinter.print(mutationArgParamsNode) ?? '') : ''
112
102
 
113
- const mutationParams = FunctionParams.factory({
114
- ...getPathParams(typeSchemas.pathParams, { typed: true, casing: paramsCasing }),
115
- data: typeSchemas.request?.name
116
- ? {
117
- type: typeSchemas.request?.name,
118
- optional: isOptional(typeSchemas.request?.schema),
119
- }
120
- : undefined,
121
- params: typeSchemas.queryParams?.name
122
- ? {
123
- type: typeSchemas.queryParams?.name,
124
- optional: isOptional(typeSchemas.queryParams?.schema),
125
- }
126
- : undefined,
127
- headers: typeSchemas.headerParams?.name
128
- ? {
129
- type: typeSchemas.headerParams?.name,
130
- optional: isOptional(typeSchemas.headerParams?.schema),
131
- }
132
- : undefined,
133
- })
134
- const dataParams = FunctionParams.factory({
135
- data: {
136
- // No use of pathParams because useMutation can only take one argument in object form,
137
- // see https://tanstack.com/query/latest/docs/framework/react/reference/useMutation#usemutation
138
- mode: 'object',
139
- children: Object.entries(mutationParams.params).reduce((acc, [key, value]) => {
140
- if (value) {
141
- acc[key] = {
142
- ...value,
143
- type: undefined,
144
- }
145
- }
146
-
147
- return acc
148
- }, {} as Params),
149
- },
150
- })
103
+ const generics = [TData, TError, TRequest ? `{${TRequest}}` : 'void', 'TContext'].join(', ')
151
104
 
152
- const TRequest = mutationParams.toConstructor()
153
- const TData = dataReturnType === 'data' ? typeSchemas.response.name : `ResponseConfig<${typeSchemas.response.name}>`
154
- const TError = `ResponseErrorConfig<${typeSchemas.errors?.map((item) => item.name).join(' | ') || 'Error'}>`
105
+ const mutationKeyParamsNode = ast.createFunctionParameters({ params: [] })
106
+ const mutationKeyParamsCall = callPrinter.print(mutationKeyParamsNode) ?? ''
155
107
 
156
- const generics = [TData, TError, TRequest ? `{${TRequest}}` : 'void', 'TContext'].join(', ')
108
+ const clientCallParamsNode = ast.createOperationParams(node, {
109
+ paramsType,
110
+ pathParamsType: paramsType === 'object' ? 'object' : pathParamsType === 'object' ? 'object' : 'inline',
111
+ paramsCasing,
112
+ resolver: tsResolver,
113
+ extraParams: [
114
+ ast.createFunctionParameter({
115
+ name: 'config',
116
+ type: ast.createParamsType({
117
+ variant: 'reference',
118
+ name: buildRequestConfigType(node, tsResolver),
119
+ }),
120
+ default: '{}',
121
+ }),
122
+ ],
123
+ })
124
+ const clientCallStr = callPrinter.print(clientCallParamsNode) ?? ''
125
+
126
+ const paramsNode = buildMutationParamsNode(node, { paramsCasing, dataReturnType, resolver: tsResolver })
127
+ const paramsSignature = declarationPrinter.print(paramsNode) ?? ''
157
128
 
158
129
  return (
159
130
  <File.Source name={name} isExportable isIndexable>
160
- <Function
161
- name={name}
162
- export
163
- params={params.toConstructor()}
164
- JSDoc={{
165
- comments: getComments(operation),
166
- }}
167
- generics={['TContext']}
168
- >
131
+ <Function name={name} export params={paramsSignature} JSDoc={{ comments: getComments(node) }} generics={['TContext']}>
169
132
  {`
170
133
  const { mutation = {}, client: config = {} } = options ?? {}
171
134
  const { client: queryClient, ...mutationOptions } = mutation;
172
- const mutationKey = mutationOptions?.mutationKey ?? ${mutationKeyName}(${mutationKeyParams.toCall()})
135
+ const mutationKey = mutationOptions?.mutationKey ?? ${mutationKeyName}(${mutationKeyParamsCall})
173
136
 
174
137
  return useMutation<${generics}>({
175
- mutationFn: async(${dataParams.toConstructor()}) => {
176
- return ${clientName}(${clientParams.toCall()})
138
+ mutationFn: async(${hasMutationParams ? `{ ${argKeysStr} }` : ''}) => {
139
+ return ${clientName}(${clientCallStr})
177
140
  },
178
141
  mutationKey,
179
142
  ...mutationOptions