@kubb/plugin-vue-query 5.0.0-beta.3 → 5.0.0-beta.30

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 (41) hide show
  1. package/README.md +26 -5
  2. package/dist/{components-D1UhYFgY.js → components-B4IlVmNa.js} +244 -353
  3. package/dist/components-B4IlVmNa.js.map +1 -0
  4. package/dist/{components-qfOFRSoM.cjs → components-CIedagno.cjs} +269 -354
  5. package/dist/components-CIedagno.cjs.map +1 -0
  6. package/dist/components.cjs +1 -1
  7. package/dist/components.d.ts +3 -67
  8. package/dist/components.js +1 -1
  9. package/dist/{generators-CbnIVBgY.js → generators-ClYptnDj.js} +144 -132
  10. package/dist/generators-ClYptnDj.js.map +1 -0
  11. package/dist/{generators-C4gs_P1i.cjs → generators-D7kNtBBo.cjs} +142 -130
  12. package/dist/generators-D7kNtBBo.cjs.map +1 -0
  13. package/dist/generators.cjs +1 -1
  14. package/dist/generators.d.ts +17 -1
  15. package/dist/generators.js +1 -1
  16. package/dist/index.cjs +100 -17
  17. package/dist/index.cjs.map +1 -1
  18. package/dist/index.d.ts +29 -1
  19. package/dist/index.js +100 -17
  20. package/dist/index.js.map +1 -1
  21. package/dist/types-D-LjzI_Q.d.ts +270 -0
  22. package/extension.yaml +1273 -0
  23. package/package.json +16 -18
  24. package/src/components/InfiniteQuery.tsx +11 -48
  25. package/src/components/InfiniteQueryOptions.tsx +38 -50
  26. package/src/components/Mutation.tsx +33 -42
  27. package/src/components/Query.tsx +11 -49
  28. package/src/components/QueryKey.tsx +8 -61
  29. package/src/components/QueryOptions.tsx +14 -67
  30. package/src/generators/infiniteQueryGenerator.tsx +46 -51
  31. package/src/generators/mutationGenerator.tsx +41 -49
  32. package/src/generators/queryGenerator.tsx +43 -49
  33. package/src/plugin.ts +43 -15
  34. package/src/resolvers/resolverVueQuery.ts +61 -4
  35. package/src/types.ts +129 -53
  36. package/src/utils.ts +44 -25
  37. package/dist/components-D1UhYFgY.js.map +0 -1
  38. package/dist/components-qfOFRSoM.cjs.map +0 -1
  39. package/dist/generators-C4gs_P1i.cjs.map +0 -1
  40. package/dist/generators-CbnIVBgY.js.map +0 -1
  41. package/dist/types-nVDTfuS1.d.ts +0 -194
package/package.json CHANGED
@@ -1,26 +1,23 @@
1
1
  {
2
2
  "name": "@kubb/plugin-vue-query",
3
- "version": "5.0.0-beta.3",
4
- "description": "Vue Query hooks generator plugin for Kubb, creating type-safe API client hooks from OpenAPI specifications for Vue.js applications.",
3
+ "version": "5.0.0-beta.30",
4
+ "description": "Generate type-safe TanStack Query (Vue Query) composables from your OpenAPI specification. Covers useQuery, useMutation, useInfiniteQuery, and queryOptions with Vue 3 Composition API support.",
5
5
  "keywords": [
6
- "api-client",
7
- "code-generator",
6
+ "code-generation",
8
7
  "codegen",
9
8
  "composables",
9
+ "composition-api",
10
10
  "data-fetching",
11
- "hooks",
12
11
  "kubb",
13
- "oas",
14
12
  "openapi",
15
- "plugins",
16
- "sdk-generator",
17
13
  "swagger",
14
+ "tanstack",
18
15
  "tanstack-query",
19
- "type-safe",
20
16
  "typescript",
17
+ "use-mutation",
18
+ "use-query",
21
19
  "vue",
22
20
  "vue-query",
23
- "vue.js",
24
21
  "vue3"
25
22
  ],
26
23
  "license": "MIT",
@@ -33,7 +30,7 @@
33
30
  "files": [
34
31
  "src",
35
32
  "dist",
36
- "plugin.json",
33
+ "extension.yaml",
37
34
  "!/**/**.test.**",
38
35
  "!/**/__tests__/**",
39
36
  "!/**/__snapshots__/**"
@@ -73,19 +70,20 @@
73
70
  "registry": "https://registry.npmjs.org/"
74
71
  },
75
72
  "dependencies": {
76
- "@kubb/core": "5.0.0-beta.3",
77
- "@kubb/renderer-jsx": "5.0.0-beta.3",
78
- "remeda": "^2.34.0",
79
- "@kubb/plugin-client": "5.0.0-beta.3",
80
- "@kubb/plugin-ts": "5.0.0-beta.3",
81
- "@kubb/plugin-zod": "5.0.0-beta.3"
73
+ "@kubb/core": "5.0.0-beta.29",
74
+ "@kubb/renderer-jsx": "5.0.0-beta.29",
75
+ "remeda": "^2.34.1",
76
+ "@kubb/plugin-client": "5.0.0-beta.30",
77
+ "@kubb/plugin-ts": "5.0.0-beta.30",
78
+ "@kubb/plugin-zod": "5.0.0-beta.30"
82
79
  },
83
80
  "devDependencies": {
81
+ "@internals/shared": "0.0.0",
84
82
  "@internals/tanstack-query": "0.0.0",
85
83
  "@internals/utils": "0.0.0"
86
84
  },
87
85
  "peerDependencies": {
88
- "@kubb/renderer-jsx": "5.0.0-beta.3"
86
+ "@kubb/renderer-jsx": "5.0.0-beta.29"
89
87
  },
90
88
  "size-limit": [
91
89
  {
@@ -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 { Infinite, PluginVueQuery } from '../types.ts'
7
- import { getComments, resolveErrorNames } from '../utils.ts'
8
- import { QueryKey } from './QueryKey.tsx'
7
+ import { getComments, resolveErrorNames, resolveSuccessNames, wrapWithMaybeRefOrGetter } from '../utils.ts'
8
+ import { buildQueryKeyParamsNode } from './QueryKey.tsx'
9
9
  import { getQueryOptionsParams } from './QueryOptions.tsx'
10
10
 
11
11
  type Props = {
@@ -26,7 +26,7 @@ type Props = {
26
26
  const declarationPrinter = functionPrinter({ mode: 'declaration' })
27
27
  const callPrinter = functionPrinter({ mode: 'call' })
28
28
 
29
- function getParams(
29
+ function buildInfiniteQueryParamsNode(
30
30
  node: ast.OperationNode,
31
31
  options: {
32
32
  paramsType: PluginVueQuery['resolvedOptions']['paramsType']
@@ -37,8 +37,9 @@ function getParams(
37
37
  },
38
38
  ): ast.FunctionParametersNode {
39
39
  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
40
+ const successNames = resolveSuccessNames(node, resolver)
41
+ const responseName = successNames.length > 0 ? successNames.join(' | ') : resolver.resolveResponseName(node)
42
+ const requestName = node.requestBody?.content?.[0]?.schema ? resolver.resolveDataName(node) : null
42
43
  const errorNames = resolveErrorNames(node, resolver)
43
44
 
44
45
  const TData = dataReturnType === 'data' ? responseName : `ResponseConfig<${responseName}>`
@@ -64,44 +65,7 @@ function getParams(
64
65
  extraParams: [optionsParam],
65
66
  })
66
67
 
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'
68
+ return wrapWithMaybeRefOrGetter(baseParams, (name) => name === 'options')
105
69
  }
106
70
 
107
71
  export function InfiniteQuery({
@@ -116,7 +80,8 @@ export function InfiniteQuery({
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
87
  const TData = dataReturnType === 'data' ? responseName : `ResponseConfig<${responseName}>`
@@ -124,13 +89,13 @@ export function InfiniteQuery({
124
89
  const returnType = `UseInfiniteQueryReturnType<${['TData', TError].join(', ')}> & { queryKey: TQueryKey }`
125
90
  const generics = [`TData = InfiniteData<${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) ?? ''
129
94
 
130
95
  const queryOptionsParamsNode = getQueryOptionsParams(node, { paramsType, paramsCasing, pathParamsType, resolver: tsResolver })
131
96
  const queryOptionsParamsCall = callPrinter.print(queryOptionsParamsNode) ?? ''
132
97
 
133
- const paramsNode = getParams(node, { paramsType, paramsCasing, pathParamsType, dataReturnType, resolver: tsResolver })
98
+ const paramsNode = buildInfiniteQueryParamsNode(node, { paramsType, paramsCasing, pathParamsType, dataReturnType, resolver: tsResolver })
134
99
  const paramsSignature = declarationPrinter.print(paramsNode) ?? ''
135
100
 
136
101
  return (
@@ -155,5 +120,3 @@ export function InfiniteQuery({
155
120
  </File.Source>
156
121
  )
157
122
  }
158
-
159
- InfiniteQuery.getParams = getParams
@@ -1,3 +1,4 @@
1
+ import { getOperationParameters } from '@internals/shared'
1
2
  import { getNestedAccessor } from '@internals/utils'
2
3
  import type { ast } from '@kubb/core'
3
4
  import type { ResolverTs } from '@kubb/plugin-ts'
@@ -5,9 +6,10 @@ 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 { resolveErrorNames, resolveSuccessNames } from '../utils.ts'
10
+ import { buildQueryKeyParamsNode } from './QueryKey.tsx'
11
+ import { buildEnabledCheck } from '@internals/tanstack-query'
12
+ import { getQueryOptionsParams } from './QueryOptions.tsx'
11
13
 
12
14
  type Props = {
13
15
  name: string
@@ -45,7 +47,8 @@ export function InfiniteQueryOptions({
45
47
  queryParam,
46
48
  queryKeyName,
47
49
  }: Props): KubbReactNode {
48
- const responseName = tsResolver.resolveResponseName(node)
50
+ const successNames = resolveSuccessNames(node, tsResolver)
51
+ const responseName = successNames.length > 0 ? successNames.join(' | ') : tsResolver.resolveResponseName(node)
49
52
  const queryFnDataType = dataReturnType === 'data' ? responseName : `ResponseConfig<${responseName}>`
50
53
  const errorNames = resolveErrorNames(node, tsResolver)
51
54
  const errorType = `ResponseErrorConfig<${errorNames.length > 0 ? errorNames.join(' | ') : 'Error'}>`
@@ -65,17 +68,17 @@ 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
84
  const paramsNode = getQueryOptionsParams(node, { paramsType, paramsCasing, pathParamsType, resolver: tsResolver })
@@ -83,43 +86,38 @@ export function InfiniteQueryOptions({
83
86
  const rawParamsCall = callPrinter.print(paramsNode) ?? ''
84
87
  const clientCallStr = rawParamsCall.replace(/\bconfig\b(?=[^,]*$)/, '{ ...config, signal: config.signal ?? signal }')
85
88
 
86
- const queryKeyParamsNode = QueryKey.getParams(node, { pathParamsType, paramsCasing, resolver: tsResolver })
89
+ const queryKeyParamsNode = buildQueryKeyParamsNode(node, { pathParamsType, paramsCasing, resolver: tsResolver })
87
90
  const queryKeyParamsCall = callPrinter.print(queryKeyParamsNode) ?? ''
88
91
 
89
92
  const enabledSource = buildEnabledCheck(queryKeyParamsNode)
90
- const enabledText = enabledSource ? `enabled: () => !!(${enabledSource}),` : ''
91
-
92
- const hasNewParams = nextParam !== undefined || previousParam !== undefined
93
-
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
- }
93
+ const enabledText = enabledSource
94
+ ? `enabled: () => ${enabledSource
95
+ .split(' && ')
96
+ .map((n) => `!!toValue(${n.trim()})`)
97
+ .join(' && ')},`
98
+ : ''
99
+
100
+ const hasNewParams = nextParam != null || previousParam != null
101
+
102
+ const [getNextPageParamExpr, getPreviousPageParamExpr] = (() => {
103
+ if (hasNewParams) {
104
+ const nextAccessor = nextParam ? getNestedAccessor(nextParam, 'lastPage') : null
105
+ const prevAccessor = previousParam ? getNestedAccessor(previousParam, 'firstPage') : null
106
+ return [
107
+ nextAccessor ? `getNextPageParam: (lastPage) => ${nextAccessor}` : null,
108
+ prevAccessor ? `getPreviousPageParam: (firstPage) => ${prevAccessor}` : null,
109
+ ] as const
103
110
  }
104
- if (previousParam) {
105
- const accessor = getNestedAccessor(previousParam, 'firstPage')
106
- if (accessor) {
107
- getPreviousPageParamExpr = `getPreviousPageParam: (firstPage) => ${accessor}`
108
- }
111
+ if (cursorParam) {
112
+ return [`getNextPageParam: (lastPage) => lastPage['${cursorParam}']`, `getPreviousPageParam: (firstPage) => firstPage['${cursorParam}']`] as const
109
113
  }
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
- }
114
+ return [
115
+ dataReturnType === 'full'
116
+ ? 'getNextPageParam: (lastPage, _allPages, lastPageParam) => Array.isArray(lastPage.data) && lastPage.data.length === 0 ? undefined : lastPageParam + 1'
117
+ : 'getNextPageParam: (lastPage, _allPages, lastPageParam) => Array.isArray(lastPage) && lastPage.length === 0 ? undefined : lastPageParam + 1',
118
+ 'getPreviousPageParam: (_firstPage, _allPages, firstPageParam) => firstPageParam <= 1 ? undefined : firstPageParam - 1',
119
+ ] as const
120
+ })()
123
121
 
124
122
  const queryOptionsArr = [
125
123
  `initialPageParam: ${typeof initialPageParam === 'string' ? JSON.stringify(initialPageParam) : initialPageParam}`,
@@ -197,13 +195,3 @@ function addToValueCalls(callStr: string): string {
197
195
 
198
196
  return result
199
197
  }
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, 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
54
  const TData = dataReturnType === 'data' ? responseName : `ResponseConfig<${responseName}>`
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
94
  const TData = dataReturnType === 'data' ? responseName : `ResponseConfig<${responseName}>`
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,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 { PluginVueQuery } from '../types.ts'
7
- import { getComments, resolveErrorNames } from '../utils.ts'
8
- import { QueryKey } from './QueryKey.tsx'
7
+ import { getComments, resolveErrorNames, resolveSuccessNames, wrapWithMaybeRefOrGetter } from '../utils.ts'
8
+ import { buildQueryKeyParamsNode } from './QueryKey.tsx'
9
9
  import { getQueryOptionsParams } from './QueryOptions.tsx'
10
10
 
11
11
  type Props = {
@@ -24,7 +24,7 @@ type Props = {
24
24
  const declarationPrinter = functionPrinter({ mode: 'declaration' })
25
25
  const callPrinter = functionPrinter({ mode: 'call' })
26
26
 
27
- function getParams(
27
+ function buildQueryParamsNode(
28
28
  node: ast.OperationNode,
29
29
  options: {
30
30
  paramsType: PluginVueQuery['resolvedOptions']['paramsType']
@@ -35,8 +35,9 @@ function getParams(
35
35
  },
36
36
  ): ast.FunctionParametersNode {
37
37
  const { paramsType, paramsCasing, pathParamsType, dataReturnType, resolver } = options
38
- const responseName = resolver.resolveResponseName(node)
39
- const requestName = node.requestBody?.content?.[0]?.schema ? resolver.resolveDataName(node) : undefined
38
+ const successNames = resolveSuccessNames(node, resolver)
39
+ const responseName = successNames.length > 0 ? successNames.join(' | ') : resolver.resolveResponseName(node)
40
+ const requestName = node.requestBody?.content?.[0]?.schema ? resolver.resolveDataName(node) : null
40
41
  const errorNames = resolveErrorNames(node, resolver)
41
42
 
42
43
  const TData = dataReturnType === 'data' ? responseName : `ResponseConfig<${responseName}>`
@@ -63,45 +64,7 @@ function getParams(
63
64
  extraParams: [optionsParam],
64
65
  })
65
66
 
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'
67
+ return wrapWithMaybeRefOrGetter(baseParams, (name) => name === 'options')
105
68
  }
106
69
 
107
70
  export function Query({
@@ -116,7 +79,8 @@ export function Query({
116
79
  node,
117
80
  tsResolver,
118
81
  }: Props): KubbReactNode {
119
- const responseName = tsResolver.resolveResponseName(node)
82
+ const successNames = resolveSuccessNames(node, tsResolver)
83
+ const responseName = successNames.length > 0 ? successNames.join(' | ') : tsResolver.resolveResponseName(node)
120
84
  const errorNames = resolveErrorNames(node, tsResolver)
121
85
 
122
86
  const TData = dataReturnType === 'data' ? responseName : `ResponseConfig<${responseName}>`
@@ -124,13 +88,13 @@ export function Query({
124
88
  const returnType = `UseQueryReturnType<${['TData', TError].join(', ')}> & { queryKey: TQueryKey }`
125
89
  const generics = [`TData = ${TData}`, `TQueryData = ${TData}`, `TQueryKey extends QueryKey = ${queryKeyTypeName}`]
126
90
 
127
- const queryKeyParamsNode = QueryKey.getParams(node, { pathParamsType, paramsCasing, resolver: tsResolver })
91
+ const queryKeyParamsNode = buildQueryKeyParamsNode(node, { pathParamsType, paramsCasing, resolver: tsResolver })
128
92
  const queryKeyParamsCall = callPrinter.print(queryKeyParamsNode) ?? ''
129
93
 
130
94
  const queryOptionsParamsNode = getQueryOptionsParams(node, { paramsType, paramsCasing, pathParamsType, resolver: tsResolver })
131
95
  const queryOptionsParamsCall = callPrinter.print(queryOptionsParamsNode) ?? ''
132
96
 
133
- const paramsNode = getParams(node, { paramsType, paramsCasing, pathParamsType, dataReturnType, resolver: tsResolver })
97
+ const paramsNode = buildQueryParamsNode(node, { paramsType, paramsCasing, pathParamsType, dataReturnType, resolver: tsResolver })
134
98
  const paramsSignature = declarationPrinter.print(paramsNode) ?? ''
135
99
 
136
100
  return (
@@ -155,5 +119,3 @@ export function Query({
155
119
  </File.Source>
156
120
  )
157
121
  }
158
-
159
- Query.getParams = getParams