@kubb/plugin-vue-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 (43) hide show
  1. package/README.md +39 -22
  2. package/dist/{components-D1UhYFgY.js → components-B79Gljyl.js} +483 -565
  3. package/dist/components-B79Gljyl.js.map +1 -0
  4. package/dist/{components-qfOFRSoM.cjs → components-D3xIZ9FA.cjs} +513 -565
  5. package/dist/components-D3xIZ9FA.cjs.map +1 -0
  6. package/dist/components.cjs +1 -1
  7. package/dist/components.d.ts +4 -68
  8. package/dist/components.js +1 -1
  9. package/dist/{generators-C4gs_P1i.cjs → generators-BTtcGtUY.cjs} +225 -314
  10. package/dist/generators-BTtcGtUY.cjs.map +1 -0
  11. package/dist/generators-D95ddIFV.js +620 -0
  12. package/dist/generators-D95ddIFV.js.map +1 -0
  13. package/dist/generators.cjs +1 -1
  14. package/dist/generators.d.ts +21 -6
  15. package/dist/generators.js +1 -1
  16. package/dist/index.cjs +158 -25
  17. package/dist/index.cjs.map +1 -1
  18. package/dist/index.d.ts +31 -4
  19. package/dist/index.js +160 -27
  20. package/dist/index.js.map +1 -1
  21. package/dist/types-CwabLiFK.d.ts +266 -0
  22. package/package.json +18 -27
  23. package/src/components/InfiniteQuery.tsx +18 -50
  24. package/src/components/InfiniteQueryOptions.tsx +64 -82
  25. package/src/components/Mutation.tsx +35 -44
  26. package/src/components/Query.tsx +18 -51
  27. package/src/components/QueryKey.tsx +9 -61
  28. package/src/components/QueryOptions.tsx +22 -99
  29. package/src/generators/infiniteQueryGenerator.tsx +55 -67
  30. package/src/generators/mutationGenerator.tsx +53 -65
  31. package/src/generators/queryGenerator.tsx +52 -65
  32. package/src/plugin.ts +48 -32
  33. package/src/resolvers/resolverVueQuery.ts +63 -6
  34. package/src/types.ts +132 -60
  35. package/src/utils.ts +45 -25
  36. package/dist/components-D1UhYFgY.js.map +0 -1
  37. package/dist/components-qfOFRSoM.cjs.map +0 -1
  38. package/dist/generators-C4gs_P1i.cjs.map +0 -1
  39. package/dist/generators-CbnIVBgY.js +0 -709
  40. package/dist/generators-CbnIVBgY.js.map +0 -1
  41. package/dist/types-nVDTfuS1.d.ts +0 -194
  42. package/extension.yaml +0 -793
  43. /package/dist/{chunk--u3MIqq1.js → chunk-C0LytTxp.js} +0 -0
@@ -4,8 +4,9 @@ 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 { Infinite, PluginVueQuery } 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 { buildStatusUnionType, getComments, resolveErrorNames, resolveSuccessNames, wrapWithMaybeRefOrGetter } from '../utils.ts'
9
+ import { buildQueryKeyParamsNode } from './QueryKey.tsx'
9
10
  import { getQueryOptionsParams } from './QueryOptions.tsx'
10
11
 
11
12
  type Props = {
@@ -26,7 +27,7 @@ type Props = {
26
27
  const declarationPrinter = functionPrinter({ mode: 'declaration' })
27
28
  const callPrinter = functionPrinter({ mode: 'call' })
28
29
 
29
- function getParams(
30
+ function buildInfiniteQueryParamsNode(
30
31
  node: ast.OperationNode,
31
32
  options: {
32
33
  paramsType: PluginVueQuery['resolvedOptions']['paramsType']
@@ -37,11 +38,12 @@ function getParams(
37
38
  },
38
39
  ): ast.FunctionParametersNode {
39
40
  const { paramsType, paramsCasing, pathParamsType, dataReturnType, resolver } = options
40
- const responseName = resolver.resolveResponseName(node)
41
- const requestName = node.requestBody?.content?.[0]?.schema ? resolver.resolveDataName(node) : undefined
41
+ const successNames = resolveSuccessNames(node, resolver)
42
+ const responseName = successNames.length > 0 ? successNames.join(' | ') : resolver.resolveResponseName(node)
43
+ const requestName = node.requestBody?.content?.[0]?.schema ? resolver.resolveDataName(node) : null
42
44
  const errorNames = resolveErrorNames(node, resolver)
43
45
 
44
- const TData = dataReturnType === 'data' ? responseName : `ResponseConfig<${responseName}>`
46
+ const TData = dataReturnType === 'data' ? responseName : buildStatusUnionType(node, resolver)
45
47
  const TError = `ResponseErrorConfig<${errorNames.length > 0 ? errorNames.join(' | ') : 'Error'}>`
46
48
 
47
49
  const optionsParam = ast.createFunctionParameter({
@@ -64,44 +66,7 @@ function getParams(
64
66
  extraParams: [optionsParam],
65
67
  })
66
68
 
67
- return wrapOperationParamsWithMaybeRef(baseParams)
68
- }
69
-
70
- function wrapOperationParamsWithMaybeRef(paramsNode: ast.FunctionParametersNode): ast.FunctionParametersNode {
71
- const wrappedParams = paramsNode.params.map((param) => {
72
- if ('kind' in param && (param as ast.ParameterGroupNode).kind === 'ParameterGroup') {
73
- const group = param as ast.ParameterGroupNode
74
- return {
75
- ...group,
76
- properties: group.properties.map((p) => ({
77
- ...p,
78
- type: p.type ? ast.createParamsType({ variant: 'reference', name: `MaybeRefOrGetter<${printType(p.type)}>` }) : p.type,
79
- })),
80
- }
81
- }
82
- const fp = param as ast.FunctionParameterNode
83
- if (fp.name === 'options') return fp
84
- return {
85
- ...fp,
86
- type: fp.type ? ast.createParamsType({ variant: 'reference', name: `MaybeRefOrGetter<${printType(fp.type)}>` }) : fp.type,
87
- }
88
- })
89
- return ast.createFunctionParameters({ params: wrappedParams })
90
- }
91
-
92
- function printType(typeNode: ast.ParamsTypeNode | undefined): string {
93
- if (!typeNode) return 'unknown'
94
- if (typeNode.variant === 'reference') return typeNode.name
95
- if (typeNode.variant === 'member') return `${typeNode.base}['${typeNode.key}']`
96
- if (typeNode.variant === 'struct') {
97
- const parts = typeNode.properties.map((p) => {
98
- const typeStr = printType(p.type)
99
- const key = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(p.name) ? p.name : JSON.stringify(p.name)
100
- return p.optional ? `${key}?: ${typeStr}` : `${key}: ${typeStr}`
101
- })
102
- return `{ ${parts.join('; ')} }`
103
- }
104
- return 'unknown'
69
+ return wrapWithMaybeRefOrGetter(baseParams, (name) => name === 'options')
105
70
  }
106
71
 
107
72
  export function InfiniteQuery({
@@ -116,21 +81,26 @@ export function InfiniteQuery({
116
81
  node,
117
82
  tsResolver,
118
83
  }: Props): KubbReactNode {
119
- const responseName = tsResolver.resolveResponseName(node)
84
+ const successNames = resolveSuccessNames(node, tsResolver)
85
+ const responseName = successNames.length > 0 ? successNames.join(' | ') : tsResolver.resolveResponseName(node)
120
86
  const errorNames = resolveErrorNames(node, tsResolver)
121
87
 
122
- const TData = dataReturnType === 'data' ? responseName : `ResponseConfig<${responseName}>`
88
+ const TData = dataReturnType === 'data' ? responseName : buildStatusUnionType(node, tsResolver)
123
89
  const TError = `ResponseErrorConfig<${errorNames.length > 0 ? errorNames.join(' | ') : 'Error'}>`
124
90
  const returnType = `UseInfiniteQueryReturnType<${['TData', TError].join(', ')}> & { queryKey: TQueryKey }`
125
91
  const generics = [`TData = InfiniteData<${TData}>`, `TQueryData = ${TData}`, `TQueryKey extends QueryKey = ${queryKeyTypeName}`]
126
92
 
127
- const queryKeyParamsNode = QueryKey.getParams(node, { pathParamsType, paramsCasing, resolver: tsResolver })
93
+ const queryKeyParamsNode = buildQueryKeyParamsNode(node, { pathParamsType, paramsCasing, resolver: tsResolver })
128
94
  const queryKeyParamsCall = callPrinter.print(queryKeyParamsNode) ?? ''
95
+ const enabledNames = getEnabledParamNames(queryKeyParamsNode)
129
96
 
130
97
  const queryOptionsParamsNode = getQueryOptionsParams(node, { paramsType, paramsCasing, pathParamsType, resolver: tsResolver })
131
98
  const queryOptionsParamsCall = callPrinter.print(queryOptionsParamsNode) ?? ''
132
99
 
133
- const paramsNode = getParams(node, { paramsType, paramsCasing, pathParamsType, dataReturnType, resolver: tsResolver })
100
+ const paramsNode = markParamsOptional(
101
+ buildInfiniteQueryParamsNode(node, { paramsType, paramsCasing, pathParamsType, dataReturnType, resolver: tsResolver }),
102
+ enabledNames,
103
+ )
134
104
  const paramsSignature = declarationPrinter.print(paramsNode) ?? ''
135
105
 
136
106
  return (
@@ -155,5 +125,3 @@ export function InfiniteQuery({
155
125
  </File.Source>
156
126
  )
157
127
  }
158
-
159
- InfiniteQuery.getParams = getParams
@@ -1,13 +1,15 @@
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, PluginVueQuery } from '../types.ts'
8
- import { resolveErrorNames } from '../utils.ts'
9
- import { QueryKey } from './QueryKey.tsx'
10
- import { buildEnabledCheck, getQueryOptionsParams } from './QueryOptions.tsx'
9
+ import { buildStatusUnionType, resolveErrorNames, resolveSuccessNames } from '../utils.ts'
10
+ import { buildQueryKeyParamsNode } from './QueryKey.tsx'
11
+ import { getEnabledParamNames, markParamsOptional } from '@internals/tanstack-query'
12
+ import { getQueryOptionsParams } from './QueryOptions.tsx'
11
13
 
12
14
  type Props = {
13
15
  name: string
@@ -45,8 +47,9 @@ export function InfiniteQueryOptions({
45
47
  queryParam,
46
48
  queryKeyName,
47
49
  }: Props): KubbReactNode {
48
- const responseName = tsResolver.resolveResponseName(node)
49
- const queryFnDataType = dataReturnType === 'data' ? responseName : `ResponseConfig<${responseName}>`
50
+ const successNames = resolveSuccessNames(node, tsResolver)
51
+ const responseName = successNames.length > 0 ? successNames.join(' | ') : tsResolver.resolveResponseName(node)
52
+ const queryFnDataType = dataReturnType === 'data' ? responseName : buildStatusUnionType(node, tsResolver)
50
53
  const errorNames = resolveErrorNames(node, tsResolver)
51
54
  const errorType = `ResponseErrorConfig<${errorNames.length > 0 ? errorNames.join(' | ') : 'Error'}>`
52
55
 
@@ -65,61 +68,51 @@ export function InfiniteQueryOptions({
65
68
  ? 'boolean'
66
69
  : 'unknown'
67
70
 
68
- const rawQueryParams = node.parameters.filter((p) => p.in === 'query')
71
+ const rawQueryParams = getOperationParameters(node).query
69
72
  const queryParamsTypeName =
70
73
  rawQueryParams.length > 0
71
74
  ? (() => {
72
75
  const groupName = tsResolver.resolveQueryParamsName(node, rawQueryParams[0]!)
73
76
  const individualName = tsResolver.resolveParamName(node, rawQueryParams[0]!)
74
- return groupName !== individualName ? groupName : undefined
77
+ return groupName !== individualName ? groupName : null
75
78
  })()
76
- : undefined
79
+ : null
77
80
 
78
- const queryParamType = queryParam && queryParamsTypeName ? `${queryParamsTypeName}['${queryParam}']` : undefined
81
+ const queryParamType = queryParam && queryParamsTypeName ? `${queryParamsTypeName}['${queryParam}']` : null
79
82
  const pageParamType = queryParamType ? (isInitialPageParamDefined ? `NonNullable<${queryParamType}>` : queryParamType) : fallbackPageParamType
80
83
 
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 })
84
+ const queryKeyParamsNode = buildQueryKeyParamsNode(node, { pathParamsType, paramsCasing, resolver: tsResolver })
87
85
  const queryKeyParamsCall = callPrinter.print(queryKeyParamsNode) ?? ''
88
86
 
89
- const enabledSource = buildEnabledCheck(queryKeyParamsNode)
90
- const enabledText = enabledSource ? `enabled: () => !!(${enabledSource}),` : ''
87
+ const enabledNames = getEnabledParamNames(queryKeyParamsNode)
88
+ const enabledText = enabledNames.length ? `enabled: () => ${enabledNames.map((n) => `!!toValue(${n})`).join(' && ')},` : ''
91
89
 
92
- const hasNewParams = nextParam !== undefined || previousParam !== undefined
90
+ const paramsNode = markParamsOptional(getQueryOptionsParams(node, { paramsType, paramsCasing, pathParamsType, resolver: tsResolver }), enabledNames)
91
+ const paramsSignature = declarationPrinter.print(paramsNode) ?? ''
92
+ const rawParamsCall = callPrinter.print(paramsNode) ?? ''
93
+ const clientCallStr = rawParamsCall.replace(/\bconfig\b(?=[^,]*$)/, '{ ...config, signal: config.signal ?? signal }')
93
94
 
94
- let getNextPageParamExpr: string | undefined
95
- let getPreviousPageParamExpr: string | undefined
95
+ const hasNewParams = nextParam != null || previousParam != null
96
96
 
97
- if (hasNewParams) {
98
- if (nextParam) {
99
- const accessor = getNestedAccessor(nextParam, 'lastPage')
100
- if (accessor) {
101
- getNextPageParamExpr = `getNextPageParam: (lastPage) => ${accessor}`
102
- }
97
+ const [getNextPageParamExpr, getPreviousPageParamExpr] = (() => {
98
+ if (hasNewParams) {
99
+ const nextAccessor = nextParam ? getNestedAccessor(nextParam, 'lastPage') : null
100
+ const prevAccessor = previousParam ? getNestedAccessor(previousParam, 'firstPage') : null
101
+ return [
102
+ nextAccessor ? `getNextPageParam: (lastPage) => ${nextAccessor}` : null,
103
+ prevAccessor ? `getPreviousPageParam: (firstPage) => ${prevAccessor}` : null,
104
+ ] as const
103
105
  }
104
- if (previousParam) {
105
- const accessor = getNestedAccessor(previousParam, 'firstPage')
106
- if (accessor) {
107
- getPreviousPageParamExpr = `getPreviousPageParam: (firstPage) => ${accessor}`
108
- }
106
+ if (cursorParam) {
107
+ return [`getNextPageParam: (lastPage) => lastPage['${cursorParam}']`, `getPreviousPageParam: (firstPage) => firstPage['${cursorParam}']`] as const
109
108
  }
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'
120
- }
121
- getPreviousPageParamExpr = 'getPreviousPageParam: (_firstPage, _allPages, firstPageParam) => firstPageParam <= 1 ? undefined : firstPageParam - 1'
122
- }
109
+ return [
110
+ dataReturnType === 'full'
111
+ ? 'getNextPageParam: (lastPage, _allPages, lastPageParam) => Array.isArray(lastPage.data) && lastPage.data.length === 0 ? undefined : lastPageParam + 1'
112
+ : 'getNextPageParam: (lastPage, _allPages, lastPageParam) => Array.isArray(lastPage) && lastPage.length === 0 ? undefined : lastPageParam + 1',
113
+ 'getPreviousPageParam: (_firstPage, _allPages, firstPageParam) => firstPageParam <= 1 ? undefined : firstPageParam - 1',
114
+ ] as const
115
+ })()
123
116
 
124
117
  const queryOptionsArr = [
125
118
  `initialPageParam: ${typeof initialPageParam === 'string' ? JSON.stringify(initialPageParam) : initialPageParam}`,
@@ -129,11 +122,10 @@ export function InfiniteQueryOptions({
129
122
 
130
123
  const infiniteOverrideParams =
131
124
  queryParam && queryParamsTypeName
132
- ? `
133
- params = {
134
- ...(params ?? {}),
135
- ['${queryParam}']: pageParam as unknown as ${queryParamsTypeName}['${queryParam}'],
136
- } as ${queryParamsTypeName}`
125
+ ? `params = {
126
+ ...(params ?? {}),
127
+ ['${queryParam}']: pageParam as unknown as ${queryParamsTypeName}['${queryParam}'],
128
+ } as ${queryParamsTypeName}`
137
129
  : ''
138
130
 
139
131
  if (infiniteOverrideParams) {
@@ -141,16 +133,15 @@ export function InfiniteQueryOptions({
141
133
  <File.Source name={name} isExportable isIndexable>
142
134
  <Function name={name} export params={paramsSignature}>
143
135
  {`
144
- const queryKey = ${queryKeyName}(${queryKeyParamsCall})
145
- return infiniteQueryOptions<${queryFnDataType}, ${errorType}, InfiniteData<${queryFnDataType}>, QueryKey, ${pageParamType}>({
146
- ${enabledText}
147
- queryKey,
148
- queryFn: async ({ signal, pageParam }) => {
149
- ${infiniteOverrideParams}
150
- return ${clientName}(${addToValueCalls(clientCallStr)})
151
- },
152
- ${queryOptionsArr.join(',\n')}
153
- })
136
+ const queryKey = ${queryKeyName}(${queryKeyParamsCall})
137
+ return infiniteQueryOptions<${queryFnDataType}, ${errorType}, InfiniteData<${queryFnDataType}>, QueryKey, ${pageParamType}>({${enabledText ? `\n ${enabledText}` : ''}
138
+ queryKey,
139
+ queryFn: async ({ signal, pageParam }) => {
140
+ ${infiniteOverrideParams}
141
+ return ${clientName}(${addToValueCalls(clientCallStr, enabledNames)})
142
+ },
143
+ ${queryOptionsArr.join(',\n ')}
144
+ })
154
145
  `}
155
146
  </Function>
156
147
  </File.Source>
@@ -161,30 +152,31 @@ export function InfiniteQueryOptions({
161
152
  <File.Source name={name} isExportable isIndexable>
162
153
  <Function name={name} export params={paramsSignature}>
163
154
  {`
164
- const queryKey = ${queryKeyName}(${queryKeyParamsCall})
165
- return infiniteQueryOptions<${queryFnDataType}, ${errorType}, InfiniteData<${queryFnDataType}>, QueryKey, ${pageParamType}>({
166
- ${enabledText}
167
- queryKey,
168
- queryFn: async ({ signal }) => {
169
- return ${clientName}(${addToValueCalls(clientCallStr)})
170
- },
171
- ${queryOptionsArr.join(',\n')}
172
- })
155
+ const queryKey = ${queryKeyName}(${queryKeyParamsCall})
156
+ return infiniteQueryOptions<${queryFnDataType}, ${errorType}, InfiniteData<${queryFnDataType}>, QueryKey, ${pageParamType}>({${enabledText ? `\n ${enabledText}` : ''}
157
+ queryKey,
158
+ queryFn: async ({ signal }) => {
159
+ return ${clientName}(${addToValueCalls(clientCallStr, enabledNames)})
160
+ },
161
+ ${queryOptionsArr.join(',\n ')}
162
+ })
173
163
  `}
174
164
  </Function>
175
165
  </File.Source>
176
166
  )
177
167
  }
178
168
 
179
- function addToValueCalls(callStr: string): string {
169
+ function addToValueCalls(callStr: string, enabledNames: ReadonlyArray<string> = []): string {
170
+ const optional = new Set(enabledNames)
180
171
  // Step 1: Transform shorthand object params like { petId } → { petId: toValue(petId) }
172
+ // Params that drive the `enabled` guard are optional, so assert non-null: toValue(petId!)
181
173
  let result = callStr.replace(/\{\s*([\w,\s]+)\s*\}(?=\s*,)/g, (match, inner: string) => {
182
174
  if (inner.includes(':') || inner.includes('...')) return match
183
175
  const keys = inner
184
176
  .split(',')
185
177
  .map((k: string) => k.trim())
186
178
  .filter(Boolean)
187
- const wrapped = keys.map((k: string) => `${k}: toValue(${k})`).join(', ')
179
+ const wrapped = keys.map((k: string) => `${k}: toValue(${optional.has(k) ? `${k}!` : k})`).join(', ')
188
180
  return `{ ${wrapped} }`
189
181
  })
190
182
 
@@ -192,18 +184,8 @@ function addToValueCalls(callStr: string): string {
192
184
  result = result.replace(/(?<![{.:?])\b(\w+)\b(?=\s*,)/g, (match, name: string) => {
193
185
  if (name === 'config' || name === 'signal' || name === 'undefined') return match
194
186
  if (match.includes('toValue(')) return match
195
- return `toValue(${name})`
187
+ return `toValue(${optional.has(name) ? `${name}!` : name})`
196
188
  })
197
189
 
198
190
  return result
199
191
  }
200
-
201
- InfiniteQueryOptions.getParams = (
202
- node: ast.OperationNode,
203
- options: {
204
- paramsType: PluginVueQuery['resolvedOptions']['paramsType']
205
- paramsCasing: PluginVueQuery['resolvedOptions']['paramsCasing']
206
- pathParamsType: PluginVueQuery['resolvedOptions']['pathParamsType']
207
- resolver: ResolverTs
208
- },
209
- ) => getQueryOptionsParams(node, options)
@@ -4,8 +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 { PluginVueQuery } from '../types.ts'
7
- import { buildMutationArgParams, getComments, resolveErrorNames } from '../utils.ts'
8
- import { MutationKey } from './MutationKey.tsx'
7
+ import { buildRequestConfigType, buildStatusUnionType, getComments, resolveErrorNames, resolveSuccessNames, wrapWithMaybeRefOrGetter } from '../utils.ts'
9
8
 
10
9
  type Props = {
11
10
  name: string
@@ -24,7 +23,22 @@ const declarationPrinter = functionPrinter({ mode: 'declaration' })
24
23
  const callPrinter = functionPrinter({ mode: 'call' })
25
24
  const keysPrinter = functionPrinter({ mode: 'keys' })
26
25
 
27
- function getParams(
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,
38
+ })
39
+ }
40
+
41
+ function buildMutationParamsNode(
28
42
  node: ast.OperationNode,
29
43
  options: {
30
44
  paramsCasing: PluginVueQuery['resolvedOptions']['paramsCasing']
@@ -33,24 +47,16 @@ function getParams(
33
47
  },
34
48
  ): ast.FunctionParametersNode {
35
49
  const { paramsCasing, dataReturnType, resolver } = options
36
- const responseName = resolver.resolveResponseName(node)
37
- 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)
38
52
  const errorNames = resolveErrorNames(node, resolver)
39
53
 
40
- const TData = dataReturnType === 'data' ? responseName : `ResponseConfig<${responseName}>`
54
+ const TData = dataReturnType === 'data' ? responseName : buildStatusUnionType(node, resolver)
41
55
  const TError = `ResponseErrorConfig<${errorNames.length > 0 ? errorNames.join(' | ') : 'Error'}>`
42
56
 
43
- const mutationArgParamsNode = buildMutationArgParams(node, { paramsCasing, resolver })
57
+ const mutationArgParamsNode = createMutationArgParams(node, { paramsCasing, resolver })
44
58
 
45
- // Vue-query uses MutationObserverOptions instead of UseMutationOptions, and wraps params with MaybeRefOrGetter
46
- const mutationArgWrapped = mutationArgParamsNode.params.map((param) => {
47
- const fp = param as ast.FunctionParameterNode
48
- return {
49
- ...fp,
50
- type: fp.type ? ast.createParamsType({ variant: 'reference', name: `MaybeRefOrGetter<${printType(fp.type)}>` }) : fp.type,
51
- }
52
- })
53
- const wrappedParamsNode = ast.createFunctionParameters({ params: mutationArgWrapped })
59
+ const wrappedParamsNode = wrapWithMaybeRefOrGetter(mutationArgParamsNode)
54
60
  const TRequestWrapped = wrappedParamsNode.params.length > 0 ? (declarationPrinter.print(wrappedParamsNode) ?? '') : ''
55
61
 
56
62
  return ast.createFunctionParameters({
@@ -60,8 +66,8 @@ function getParams(
60
66
  type: ast.createParamsType({
61
67
  variant: 'reference',
62
68
  name: `{
63
- mutation?: MutationObserverOptions<${[TData, TError, TRequestWrapped ? `{${TRequestWrapped}}` : 'void', 'TContext'].join(', ')}> & { client?: QueryClient },
64
- client?: ${requestName ? `Partial<RequestConfig<${requestName}>> & { client?: Client }` : 'Partial<RequestConfig> & { client?: Client }'},
69
+ mutation?: MutationObserverOptions<${[TData, TError, TRequestWrapped ? `{${TRequestWrapped}}` : 'undefined', 'TContext'].join(', ')}> & { client?: QueryClient },
70
+ client?: ${buildRequestConfigType(node, resolver)},
65
71
  }`,
66
72
  }),
67
73
  default: '{}',
@@ -70,21 +76,6 @@ function getParams(
70
76
  })
71
77
  }
72
78
 
73
- function printType(typeNode: ast.ParamsTypeNode | undefined): string {
74
- if (!typeNode) return 'unknown'
75
- if (typeNode.variant === 'reference') return typeNode.name
76
- if (typeNode.variant === 'member') return `${typeNode.base}['${typeNode.key}']`
77
- if (typeNode.variant === 'struct') {
78
- const parts = typeNode.properties.map((p) => {
79
- const typeStr = printType(p.type)
80
- const key = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(p.name) ? p.name : JSON.stringify(p.name)
81
- return p.optional ? `${key}?: ${typeStr}` : `${key}: ${typeStr}`
82
- })
83
- return `{ ${parts.join('; ')} }`
84
- }
85
- return 'unknown'
86
- }
87
-
88
79
  export function Mutation({
89
80
  name,
90
81
  clientName,
@@ -96,20 +87,24 @@ export function Mutation({
96
87
  tsResolver,
97
88
  mutationKeyName,
98
89
  }: Props): KubbReactNode {
99
- const responseName = tsResolver.resolveResponseName(node)
90
+ const successNames = resolveSuccessNames(node, tsResolver)
91
+ const responseName = successNames.length > 0 ? successNames.join(' | ') : tsResolver.resolveResponseName(node)
100
92
  const errorNames = resolveErrorNames(node, tsResolver)
101
93
 
102
- const TData = dataReturnType === 'data' ? responseName : `ResponseConfig<${responseName}>`
94
+ const TData = dataReturnType === 'data' ? responseName : buildStatusUnionType(node, tsResolver)
103
95
  const TError = `ResponseErrorConfig<${errorNames.length > 0 ? errorNames.join(' | ') : 'Error'}>`
104
96
 
105
- const mutationArgParamsNode = buildMutationArgParams(node, { paramsCasing, resolver: tsResolver })
97
+ const mutationArgParamsNode = createMutationArgParams(node, {
98
+ paramsCasing,
99
+ resolver: tsResolver,
100
+ })
106
101
  const hasMutationParams = mutationArgParamsNode.params.length > 0
107
102
  const TRequest = hasMutationParams ? (declarationPrinter.print(mutationArgParamsNode) ?? '') : ''
108
103
  const argKeysStr = hasMutationParams ? (keysPrinter.print(mutationArgParamsNode) ?? '') : ''
109
104
 
110
- const generics = [TData, TError, TRequest ? `{${TRequest}}` : 'void', 'TContext'].join(', ')
105
+ const generics = [TData, TError, TRequest ? `{${TRequest}}` : 'undefined', 'TContext'].join(', ')
111
106
 
112
- const mutationKeyParamsNode = MutationKey.getParams()
107
+ const mutationKeyParamsNode = ast.createFunctionParameters({ params: [] })
113
108
  const mutationKeyParamsCall = callPrinter.print(mutationKeyParamsNode) ?? ''
114
109
 
115
110
  const clientCallParamsNode = ast.createOperationParams(node, {
@@ -122,9 +117,7 @@ export function Mutation({
122
117
  name: 'config',
123
118
  type: ast.createParamsType({
124
119
  variant: 'reference',
125
- name: node.requestBody?.content?.[0]?.schema
126
- ? `Partial<RequestConfig<${tsResolver.resolveDataName(node)}>> & { client?: Client }`
127
- : 'Partial<RequestConfig> & { client?: Client }',
120
+ name: buildRequestConfigType(node, tsResolver),
128
121
  }),
129
122
  default: '{}',
130
123
  }),
@@ -132,7 +125,7 @@ export function Mutation({
132
125
  })
133
126
  const clientCallStr = callPrinter.print(clientCallParamsNode) ?? ''
134
127
 
135
- const paramsNode = getParams(node, { paramsCasing, dataReturnType, resolver: tsResolver })
128
+ const paramsNode = buildMutationParamsNode(node, { paramsCasing, dataReturnType, resolver: tsResolver })
136
129
  const paramsSignature = declarationPrinter.print(paramsNode) ?? ''
137
130
 
138
131
  return (
@@ -155,5 +148,3 @@ export function Mutation({
155
148
  </File.Source>
156
149
  )
157
150
  }
158
-
159
- Mutation.getParams = getParams
@@ -4,8 +4,9 @@ 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 { PluginVueQuery } 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 { buildStatusUnionType, getComments, resolveErrorNames, resolveSuccessNames, wrapWithMaybeRefOrGetter } from '../utils.ts'
9
+ import { buildQueryKeyParamsNode } from './QueryKey.tsx'
9
10
  import { getQueryOptionsParams } from './QueryOptions.tsx'
10
11
 
11
12
  type Props = {
@@ -24,7 +25,7 @@ type Props = {
24
25
  const declarationPrinter = functionPrinter({ mode: 'declaration' })
25
26
  const callPrinter = functionPrinter({ mode: 'call' })
26
27
 
27
- function getParams(
28
+ function buildQueryParamsNode(
28
29
  node: ast.OperationNode,
29
30
  options: {
30
31
  paramsType: PluginVueQuery['resolvedOptions']['paramsType']
@@ -35,11 +36,12 @@ function getParams(
35
36
  },
36
37
  ): ast.FunctionParametersNode {
37
38
  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
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
40
42
  const errorNames = resolveErrorNames(node, resolver)
41
43
 
42
- const TData = dataReturnType === 'data' ? responseName : `ResponseConfig<${responseName}>`
44
+ const TData = dataReturnType === 'data' ? responseName : buildStatusUnionType(node, resolver)
43
45
  const TError = `ResponseErrorConfig<${errorNames.length > 0 ? errorNames.join(' | ') : 'Error'}>`
44
46
 
45
47
  const optionsParam = ast.createFunctionParameter({
@@ -63,45 +65,7 @@ function getParams(
63
65
  extraParams: [optionsParam],
64
66
  })
65
67
 
66
- return wrapOperationParamsWithMaybeRef(baseParams)
67
- }
68
-
69
- function wrapOperationParamsWithMaybeRef(paramsNode: ast.FunctionParametersNode): ast.FunctionParametersNode {
70
- const wrappedParams = paramsNode.params.map((param) => {
71
- if ('kind' in param && (param as ast.ParameterGroupNode).kind === 'ParameterGroup') {
72
- const group = param as ast.ParameterGroupNode
73
- return {
74
- ...group,
75
- properties: group.properties.map((p) => ({
76
- ...p,
77
- type: p.type ? ast.createParamsType({ variant: 'reference', name: `MaybeRefOrGetter<${printType(p.type)}>` }) : p.type,
78
- })),
79
- }
80
- }
81
- const fp = param as ast.FunctionParameterNode
82
- // Don't wrap 'options' param — it's not a reactive value
83
- if (fp.name === 'options') return fp
84
- return {
85
- ...fp,
86
- type: fp.type ? ast.createParamsType({ variant: 'reference', name: `MaybeRefOrGetter<${printType(fp.type)}>` }) : fp.type,
87
- }
88
- })
89
- return ast.createFunctionParameters({ params: wrappedParams })
90
- }
91
-
92
- function printType(typeNode: ast.ParamsTypeNode | undefined): string {
93
- if (!typeNode) return 'unknown'
94
- if (typeNode.variant === 'reference') return typeNode.name
95
- if (typeNode.variant === 'member') return `${typeNode.base}['${typeNode.key}']`
96
- if (typeNode.variant === 'struct') {
97
- const parts = typeNode.properties.map((p) => {
98
- const typeStr = printType(p.type)
99
- const key = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(p.name) ? p.name : JSON.stringify(p.name)
100
- return p.optional ? `${key}?: ${typeStr}` : `${key}: ${typeStr}`
101
- })
102
- return `{ ${parts.join('; ')} }`
103
- }
104
- return 'unknown'
68
+ return wrapWithMaybeRefOrGetter(baseParams, (name) => name === 'options')
105
69
  }
106
70
 
107
71
  export function Query({
@@ -116,21 +80,26 @@ export function Query({
116
80
  node,
117
81
  tsResolver,
118
82
  }: Props): KubbReactNode {
119
- const responseName = tsResolver.resolveResponseName(node)
83
+ const successNames = resolveSuccessNames(node, tsResolver)
84
+ const responseName = successNames.length > 0 ? successNames.join(' | ') : tsResolver.resolveResponseName(node)
120
85
  const errorNames = resolveErrorNames(node, tsResolver)
121
86
 
122
- const TData = dataReturnType === 'data' ? responseName : `ResponseConfig<${responseName}>`
87
+ const TData = dataReturnType === 'data' ? responseName : buildStatusUnionType(node, tsResolver)
123
88
  const TError = `ResponseErrorConfig<${errorNames.length > 0 ? errorNames.join(' | ') : 'Error'}>`
124
89
  const returnType = `UseQueryReturnType<${['TData', TError].join(', ')}> & { queryKey: TQueryKey }`
125
90
  const generics = [`TData = ${TData}`, `TQueryData = ${TData}`, `TQueryKey extends QueryKey = ${queryKeyTypeName}`]
126
91
 
127
- const queryKeyParamsNode = QueryKey.getParams(node, { pathParamsType, paramsCasing, resolver: tsResolver })
92
+ const queryKeyParamsNode = buildQueryKeyParamsNode(node, { pathParamsType, paramsCasing, resolver: tsResolver })
128
93
  const queryKeyParamsCall = callPrinter.print(queryKeyParamsNode) ?? ''
94
+ const enabledNames = getEnabledParamNames(queryKeyParamsNode)
129
95
 
130
96
  const queryOptionsParamsNode = getQueryOptionsParams(node, { paramsType, paramsCasing, pathParamsType, resolver: tsResolver })
131
97
  const queryOptionsParamsCall = callPrinter.print(queryOptionsParamsNode) ?? ''
132
98
 
133
- const paramsNode = getParams(node, { paramsType, paramsCasing, pathParamsType, dataReturnType, resolver: tsResolver })
99
+ const paramsNode = markParamsOptional(
100
+ buildQueryParamsNode(node, { paramsType, paramsCasing, pathParamsType, dataReturnType, resolver: tsResolver }),
101
+ enabledNames,
102
+ )
134
103
  const paramsSignature = declarationPrinter.print(paramsNode) ?? ''
135
104
 
136
105
  return (
@@ -155,5 +124,3 @@ export function Query({
155
124
  </File.Source>
156
125
  )
157
126
  }
158
-
159
- Query.getParams = getParams