@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,139 +1,69 @@
1
- import { getDefaultValue, isOptional, type Operation } from '@kubb/oas'
2
- import type { OperationSchemas } from '@kubb/plugin-oas'
3
- import { getComments, getPathParams } from '@kubb/plugin-oas/utils'
4
- import { File, Function, FunctionParams } from '@kubb/react-fabric'
5
- import type { FabricReactNode } from '@kubb/react-fabric/types'
1
+ import { ast } from '@kubb/core'
2
+ import type { ResolverTs } from '@kubb/plugin-ts'
3
+ import { functionPrinter } from '@kubb/plugin-ts'
4
+ import { File, Function } from '@kubb/renderer-jsx'
5
+ import type { KubbReactNode } from '@kubb/renderer-jsx/types'
6
6
  import type { PluginVueQuery } from '../types.ts'
7
- import { QueryKey } from './QueryKey.tsx'
8
- import { QueryOptions } from './QueryOptions.tsx'
7
+ import { getComments, resolveErrorNames, wrapWithMaybeRefOrGetter } from '../utils.ts'
8
+ import { buildQueryKeyParamsNode } from './QueryKey.tsx'
9
+ import { getQueryOptionsParams } from './QueryOptions.tsx'
9
10
 
10
11
  type Props = {
11
- /**
12
- * Name of the function
13
- */
14
12
  name: string
15
13
  queryOptionsName: string
16
14
  queryKeyName: string
17
15
  queryKeyTypeName: string
18
- typeSchemas: OperationSchemas
19
- operation: Operation
16
+ node: ast.OperationNode
17
+ tsResolver: ResolverTs
20
18
  paramsCasing: PluginVueQuery['resolvedOptions']['paramsCasing']
21
19
  paramsType: PluginVueQuery['resolvedOptions']['paramsType']
22
20
  pathParamsType: PluginVueQuery['resolvedOptions']['pathParamsType']
23
21
  dataReturnType: PluginVueQuery['resolvedOptions']['client']['dataReturnType']
24
22
  }
25
23
 
26
- type GetParamsProps = {
27
- paramsCasing: PluginVueQuery['resolvedOptions']['paramsCasing']
28
- paramsType: PluginVueQuery['resolvedOptions']['paramsType']
29
- pathParamsType: PluginVueQuery['resolvedOptions']['pathParamsType']
30
- dataReturnType: PluginVueQuery['resolvedOptions']['client']['dataReturnType']
31
- typeSchemas: OperationSchemas
32
- }
24
+ const declarationPrinter = functionPrinter({ mode: 'declaration' })
25
+ const callPrinter = functionPrinter({ mode: 'call' })
33
26
 
34
- function getParams({ paramsCasing, paramsType, pathParamsType, dataReturnType, typeSchemas }: GetParamsProps) {
35
- const TData = dataReturnType === 'data' ? typeSchemas.response.name : `ResponseConfig<${typeSchemas.response.name}>`
36
- const TError = `ResponseErrorConfig<${typeSchemas.errors?.map((item) => item.name).join(' | ') || 'Error'}>`
37
-
38
- if (paramsType === 'object') {
39
- const pathParams = getPathParams(typeSchemas.pathParams, {
40
- typed: true,
41
- casing: paramsCasing,
42
- override(item) {
43
- return {
44
- ...item,
45
- type: `MaybeRefOrGetter<${item.type}>`,
46
- }
47
- },
48
- })
49
- const children = {
50
- ...pathParams,
51
- data: typeSchemas.request?.name
52
- ? {
53
- type: `MaybeRefOrGetter<${typeSchemas.request?.name}>`,
54
- optional: isOptional(typeSchemas.request?.schema),
55
- }
56
- : undefined,
57
- params: typeSchemas.queryParams?.name
58
- ? {
59
- type: `MaybeRefOrGetter<${typeSchemas.queryParams?.name}>`,
60
- optional: isOptional(typeSchemas.queryParams?.schema),
61
- }
62
- : undefined,
63
- headers: typeSchemas.headerParams?.name
64
- ? {
65
- type: `MaybeRefOrGetter<${typeSchemas.headerParams?.name}>`,
66
- optional: isOptional(typeSchemas.headerParams?.schema),
67
- }
68
- : undefined,
69
- }
70
-
71
- // Check if all children are optional or undefined
72
- const allChildrenAreOptional = Object.values(children).every((child) => !child || child.optional)
73
-
74
- return FunctionParams.factory({
75
- data: {
76
- mode: 'object',
77
- children,
78
- default: allChildrenAreOptional ? '{}' : undefined,
79
- },
80
- options: {
81
- type: `
82
- {
83
- query?: Partial<UseQueryOptions<${[TData, TError, 'TData', 'TQueryData', 'TQueryKey'].join(', ')}>> & { client?: QueryClient },
84
- client?: ${typeSchemas.request?.name ? `Partial<RequestConfig<${typeSchemas.request?.name}>> & { client?: Client }` : 'Partial<RequestConfig> & { client?: Client }'}
85
- }
86
- `,
87
- default: '{}',
88
- },
89
- })
90
- }
91
-
92
- return FunctionParams.factory({
93
- pathParams: typeSchemas.pathParams?.name
94
- ? {
95
- mode: pathParamsType === 'object' ? 'object' : 'inlineSpread',
96
- children: getPathParams(typeSchemas.pathParams, {
97
- typed: true,
98
- casing: paramsCasing,
99
- override(item) {
100
- return {
101
- ...item,
102
- type: `MaybeRefOrGetter<${item.type}>`,
103
- }
104
- },
105
- }),
106
- default: getDefaultValue(typeSchemas.pathParams?.schema),
107
- }
108
- : undefined,
109
- data: typeSchemas.request?.name
110
- ? {
111
- type: `MaybeRefOrGetter<${typeSchemas.request?.name}>`,
112
- optional: isOptional(typeSchemas.request?.schema),
113
- }
114
- : undefined,
115
- params: typeSchemas.queryParams?.name
116
- ? {
117
- type: `MaybeRefOrGetter<${typeSchemas.queryParams?.name}>`,
118
- optional: isOptional(typeSchemas.queryParams?.schema),
119
- }
120
- : undefined,
121
- headers: typeSchemas.headerParams?.name
122
- ? {
123
- type: `MaybeRefOrGetter<${typeSchemas.headerParams?.name}>`,
124
- optional: isOptional(typeSchemas.headerParams?.schema),
125
- }
126
- : undefined,
127
- options: {
128
- type: `
129
- {
27
+ function buildQueryParamsNode(
28
+ node: ast.OperationNode,
29
+ options: {
30
+ paramsType: PluginVueQuery['resolvedOptions']['paramsType']
31
+ paramsCasing: PluginVueQuery['resolvedOptions']['paramsCasing']
32
+ pathParamsType: PluginVueQuery['resolvedOptions']['pathParamsType']
33
+ dataReturnType: PluginVueQuery['resolvedOptions']['client']['dataReturnType']
34
+ resolver: ResolverTs
35
+ },
36
+ ): ast.FunctionParametersNode {
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
40
+ const errorNames = resolveErrorNames(node, resolver)
41
+
42
+ const TData = dataReturnType === 'data' ? responseName : `ResponseConfig<${responseName}>`
43
+ const TError = `ResponseErrorConfig<${errorNames.length > 0 ? errorNames.join(' | ') : 'Error'}>`
44
+
45
+ const optionsParam = ast.createFunctionParameter({
46
+ name: 'options',
47
+ type: ast.createParamsType({
48
+ variant: 'reference',
49
+ name: `{
130
50
  query?: Partial<UseQueryOptions<${[TData, TError, 'TData', 'TQueryData', 'TQueryKey'].join(', ')}>> & { client?: QueryClient },
131
- client?: ${typeSchemas.request?.name ? `Partial<RequestConfig<${typeSchemas.request?.name}>> & { client?: Client }` : 'Partial<RequestConfig> & { client?: Client }'}
132
- }
133
- `,
134
- default: '{}',
135
- },
51
+ client?: ${requestName ? `Partial<RequestConfig<${requestName}>> & { client?: Client }` : 'Partial<RequestConfig> & { client?: Client }'}
52
+ }`,
53
+ }),
54
+ default: '{}',
55
+ })
56
+
57
+ // Vue-query wraps operation params with MaybeRefOrGetter
58
+ const baseParams = ast.createOperationParams(node, {
59
+ paramsType,
60
+ pathParamsType: paramsType === 'object' ? 'object' : pathParamsType === 'object' ? 'object' : 'inline',
61
+ paramsCasing,
62
+ resolver,
63
+ extraParams: [optionsParam],
136
64
  })
65
+
66
+ return wrapWithMaybeRefOrGetter(baseParams, (name) => name === 'options')
137
67
  }
138
68
 
139
69
  export function Query({
@@ -145,53 +75,36 @@ export function Query({
145
75
  paramsCasing,
146
76
  pathParamsType,
147
77
  dataReturnType,
148
- typeSchemas,
149
- operation,
150
- }: Props): FabricReactNode {
151
- const TData = dataReturnType === 'data' ? typeSchemas.response.name : `ResponseConfig<${typeSchemas.response.name}>`
152
- const TError = `ResponseErrorConfig<${typeSchemas.errors?.map((item) => item.name).join(' | ') || 'Error'}>`
78
+ node,
79
+ tsResolver,
80
+ }: Props): KubbReactNode {
81
+ const responseName = tsResolver.resolveResponseName(node)
82
+ const errorNames = resolveErrorNames(node, tsResolver)
83
+
84
+ const TData = dataReturnType === 'data' ? responseName : `ResponseConfig<${responseName}>`
85
+ const TError = `ResponseErrorConfig<${errorNames.length > 0 ? errorNames.join(' | ') : 'Error'}>`
153
86
  const returnType = `UseQueryReturnType<${['TData', TError].join(', ')}> & { queryKey: TQueryKey }`
154
87
  const generics = [`TData = ${TData}`, `TQueryData = ${TData}`, `TQueryKey extends QueryKey = ${queryKeyTypeName}`]
155
88
 
156
- const queryKeyParams = QueryKey.getParams({
157
- pathParamsType,
158
- typeSchemas,
159
- paramsCasing,
160
- })
161
- const queryOptionsParams = QueryOptions.getParams({
162
- paramsType,
163
- pathParamsType,
164
- typeSchemas,
165
- paramsCasing,
166
- })
167
- const params = getParams({
168
- paramsCasing,
169
- paramsType,
170
- pathParamsType,
171
- dataReturnType,
172
- typeSchemas,
173
- })
89
+ const queryKeyParamsNode = buildQueryKeyParamsNode(node, { pathParamsType, paramsCasing, resolver: tsResolver })
90
+ const queryKeyParamsCall = callPrinter.print(queryKeyParamsNode) ?? ''
91
+
92
+ const queryOptionsParamsNode = getQueryOptionsParams(node, { paramsType, paramsCasing, pathParamsType, resolver: tsResolver })
93
+ const queryOptionsParamsCall = callPrinter.print(queryOptionsParamsNode) ?? ''
174
94
 
175
- const queryOptions = `${queryOptionsName}(${queryOptionsParams.toCall()})`
95
+ const paramsNode = buildQueryParamsNode(node, { paramsType, paramsCasing, pathParamsType, dataReturnType, resolver: tsResolver })
96
+ const paramsSignature = declarationPrinter.print(paramsNode) ?? ''
176
97
 
177
98
  return (
178
99
  <File.Source name={name} isExportable isIndexable>
179
- <Function
180
- name={name}
181
- export
182
- generics={generics.join(', ')}
183
- params={params.toConstructor()}
184
- JSDoc={{
185
- comments: getComments(operation),
186
- }}
187
- >
100
+ <Function name={name} export generics={generics.join(', ')} params={paramsSignature} JSDoc={{ comments: getComments(node) }}>
188
101
  {`
189
102
  const { query: queryConfig = {}, client: config = {} } = options ?? {}
190
103
  const { client: queryClient, ...resolvedOptions } = queryConfig
191
- const queryKey = (resolvedOptions && 'queryKey' in resolvedOptions ? toValue(resolvedOptions.queryKey) : undefined) ?? ${queryKeyName}(${queryKeyParams.toCall()})
104
+ const queryKey = (resolvedOptions && 'queryKey' in resolvedOptions ? toValue(resolvedOptions.queryKey) : undefined) ?? ${queryKeyName}(${queryKeyParamsCall})
192
105
 
193
106
  const query = useQuery({
194
- ...${queryOptions},
107
+ ...${queryOptionsName}(${queryOptionsParamsCall}),
195
108
  ...resolvedOptions,
196
109
  queryKey
197
110
  } as unknown as UseQueryOptions<${TData}, ${TError}, TData, ${TData}, TQueryKey>, toValue(queryClient)) as ${returnType}
@@ -204,5 +117,3 @@ export function Query({
204
117
  </File.Source>
205
118
  )
206
119
  }
207
-
208
- Query.getParams = getParams
@@ -1,83 +1,43 @@
1
- import { URLPath } from '@internals/utils'
2
- import { isOptional, type Operation } from '@kubb/oas'
3
- import type { OperationSchemas } from '@kubb/plugin-oas'
4
- import { getPathParams } from '@kubb/plugin-oas/utils'
5
- import { File, Function, FunctionParams, Type } from '@kubb/react-fabric'
6
- import type { FabricReactNode } from '@kubb/react-fabric/types'
7
- import type { PluginVueQuery, Transformer } from '../types'
1
+ import type { ast } from '@kubb/core'
2
+ import type { ResolverTs } from '@kubb/plugin-ts'
3
+ import { functionPrinter } from '@kubb/plugin-ts'
4
+ import { File, Function, Type } from '@kubb/renderer-jsx'
5
+ import type { KubbReactNode } from '@kubb/renderer-jsx/types'
6
+ import { queryKeyTransformer } from '@internals/tanstack-query'
7
+ import type { Transformer } from '../types.ts'
8
+ import { buildQueryKeyParams, wrapWithMaybeRefOrGetter } from '../utils.ts'
8
9
 
9
10
  type Props = {
10
11
  name: string
11
12
  typeName: string
12
- typeSchemas: OperationSchemas
13
- operation: Operation
14
- paramsCasing: PluginVueQuery['resolvedOptions']['paramsCasing']
15
- pathParamsType: PluginVueQuery['resolvedOptions']['pathParamsType']
13
+ node: ast.OperationNode
14
+ tsResolver: ResolverTs
15
+ paramsCasing: 'camelcase' | undefined
16
+ pathParamsType: 'object' | 'inline'
16
17
  transformer: Transformer | undefined
17
18
  }
18
19
 
19
- type GetParamsProps = {
20
- paramsCasing: PluginVueQuery['resolvedOptions']['paramsCasing']
21
- pathParamsType: PluginVueQuery['resolvedOptions']['pathParamsType']
22
- typeSchemas: OperationSchemas
23
- }
24
-
25
- function getParams({ pathParamsType, paramsCasing, typeSchemas }: GetParamsProps) {
26
- return FunctionParams.factory({
27
- pathParams: {
28
- mode: pathParamsType === 'object' ? 'object' : 'inlineSpread',
29
- children: getPathParams(typeSchemas.pathParams, {
30
- typed: true,
31
- casing: paramsCasing,
32
- override(item) {
33
- return {
34
- ...item,
35
- type: `MaybeRefOrGetter<${item.type}>`,
36
- }
37
- },
38
- }),
39
- },
40
- data: typeSchemas.request?.name
41
- ? {
42
- type: `MaybeRefOrGetter<${typeSchemas.request?.name}>`,
43
- optional: isOptional(typeSchemas.request?.schema),
44
- }
45
- : undefined,
46
- params: typeSchemas.queryParams?.name
47
- ? {
48
- type: `MaybeRefOrGetter<${typeSchemas.queryParams?.name}>`,
49
- optional: isOptional(typeSchemas.queryParams?.schema),
50
- }
51
- : undefined,
52
- })
53
- }
54
-
55
- const getTransformer: Transformer = ({ operation, schemas, casing }) => {
56
- const path = new URLPath(operation.path, { casing })
57
- const keys = [
58
- path.toObject({
59
- type: 'path',
60
- stringify: true,
61
- }),
62
- schemas.queryParams?.name ? '...(params ? [params] : [])' : undefined,
63
- schemas.request?.name ? '...(data ? [data] : [])' : undefined,
64
- ].filter(Boolean)
20
+ const declarationPrinter = functionPrinter({ mode: 'declaration' })
65
21
 
66
- return keys
22
+ export function buildQueryKeyParamsNode(
23
+ node: ast.OperationNode,
24
+ options: { pathParamsType: 'object' | 'inline'; paramsCasing: 'camelcase' | undefined; resolver: ResolverTs },
25
+ ): ast.FunctionParametersNode {
26
+ return wrapWithMaybeRefOrGetter(buildQueryKeyParams(node, options))
67
27
  }
68
28
 
69
- export function QueryKey({ name, typeSchemas, paramsCasing, pathParamsType, operation, typeName, transformer = getTransformer }: Props): FabricReactNode {
70
- const params = getParams({ pathParamsType, typeSchemas, paramsCasing })
29
+ export function QueryKey({ name, node, tsResolver, paramsCasing, pathParamsType, typeName, transformer = queryKeyTransformer }: Props): KubbReactNode {
30
+ const paramsNode = buildQueryKeyParamsNode(node, { pathParamsType, paramsCasing, resolver: tsResolver })
31
+ const paramsSignature = declarationPrinter.print(paramsNode) ?? ''
71
32
  const keys = transformer({
72
- operation,
73
- schemas: typeSchemas,
33
+ node,
74
34
  casing: paramsCasing,
75
35
  })
76
36
 
77
37
  return (
78
38
  <>
79
39
  <File.Source name={name} isExportable isIndexable>
80
- <Function.Arrow name={name} export params={params.toConstructor()} singleLine>
40
+ <Function.Arrow name={name} export params={paramsSignature} singleLine>
81
41
  {`[${keys.join(', ')}] as const`}
82
42
  </Function.Arrow>
83
43
  </File.Source>
@@ -89,6 +49,3 @@ export function QueryKey({ name, typeSchemas, paramsCasing, pathParamsType, oper
89
49
  </>
90
50
  )
91
51
  }
92
-
93
- QueryKey.getParams = getParams
94
- QueryKey.getTransformer = getTransformer
@@ -1,179 +1,100 @@
1
- import { getDefaultValue, isOptional } from '@kubb/oas'
2
- import { Client } from '@kubb/plugin-client/components'
3
- import type { OperationSchemas } from '@kubb/plugin-oas'
4
- import { getPathParams } from '@kubb/plugin-oas/utils'
5
- import { File, Function, FunctionParams } from '@kubb/react-fabric'
6
- import type { FabricReactNode } from '@kubb/react-fabric/types'
1
+ import { ast } from '@kubb/core'
2
+ import type { ResolverTs } from '@kubb/plugin-ts'
3
+ import { functionPrinter } from '@kubb/plugin-ts'
4
+ import { File, Function } from '@kubb/renderer-jsx'
5
+ import type { KubbReactNode } from '@kubb/renderer-jsx/types'
6
+ import { buildEnabledCheck } from '@internals/tanstack-query'
7
7
  import type { PluginVueQuery } from '../types.ts'
8
- import { QueryKey } from './QueryKey.tsx'
8
+ import { resolveErrorNames, wrapWithMaybeRefOrGetter } from '../utils.ts'
9
+ import { buildQueryKeyParamsNode } from './QueryKey.tsx'
9
10
 
10
11
  type Props = {
11
12
  name: string
12
13
  clientName: string
13
14
  queryKeyName: string
14
- typeSchemas: OperationSchemas
15
+ node: ast.OperationNode
16
+ tsResolver: ResolverTs
15
17
  paramsCasing: PluginVueQuery['resolvedOptions']['paramsCasing']
16
18
  paramsType: PluginVueQuery['resolvedOptions']['paramsType']
17
19
  pathParamsType: PluginVueQuery['resolvedOptions']['pathParamsType']
18
20
  dataReturnType: PluginVueQuery['resolvedOptions']['client']['dataReturnType']
19
21
  }
20
22
 
21
- type GetParamsProps = {
22
- paramsCasing: PluginVueQuery['resolvedOptions']['paramsCasing']
23
- paramsType: PluginVueQuery['resolvedOptions']['paramsType']
24
- pathParamsType: PluginVueQuery['resolvedOptions']['pathParamsType']
25
- typeSchemas: OperationSchemas
26
- }
27
-
28
- function getParams({ paramsType, paramsCasing, pathParamsType, typeSchemas }: GetParamsProps) {
29
- if (paramsType === 'object') {
30
- const children = {
31
- ...getPathParams(typeSchemas.pathParams, {
32
- typed: true,
33
- casing: paramsCasing,
34
- override(item) {
35
- return {
36
- ...item,
37
- type: `MaybeRefOrGetter<${item.type}>`,
38
- }
39
- },
40
- }),
41
- data: typeSchemas.request?.name
42
- ? {
43
- type: `MaybeRefOrGetter<${typeSchemas.request?.name}>`,
44
- optional: isOptional(typeSchemas.request?.schema),
45
- }
46
- : undefined,
47
- params: typeSchemas.queryParams?.name
48
- ? {
49
- type: `MaybeRefOrGetter<${typeSchemas.queryParams?.name}>`,
50
- optional: isOptional(typeSchemas.queryParams?.schema),
51
- }
52
- : undefined,
53
- headers: typeSchemas.headerParams?.name
54
- ? {
55
- type: `MaybeRefOrGetter<${typeSchemas.queryParams?.name}>`,
56
- optional: isOptional(typeSchemas.headerParams?.schema),
57
- }
58
- : undefined,
59
- }
23
+ const declarationPrinter = functionPrinter({ mode: 'declaration' })
24
+ const callPrinter = functionPrinter({ mode: 'call' })
60
25
 
61
- // Check if all children are optional or undefined
62
- const allChildrenAreOptional = Object.values(children).every((child) => !child || child.optional)
26
+ export function getQueryOptionsParams(
27
+ node: ast.OperationNode,
28
+ options: {
29
+ paramsType: PluginVueQuery['resolvedOptions']['paramsType']
30
+ paramsCasing: PluginVueQuery['resolvedOptions']['paramsCasing']
31
+ pathParamsType: PluginVueQuery['resolvedOptions']['pathParamsType']
32
+ resolver: ResolverTs
33
+ },
34
+ ): ast.FunctionParametersNode {
35
+ const { paramsType, paramsCasing, pathParamsType, resolver } = options
36
+ const requestName = node.requestBody?.content?.[0]?.schema ? resolver.resolveDataName(node) : undefined
63
37
 
64
- return FunctionParams.factory({
65
- data: {
66
- mode: 'object',
67
- children,
68
- default: allChildrenAreOptional ? '{}' : undefined,
69
- },
70
- config: {
71
- type: typeSchemas.request?.name
72
- ? `Partial<RequestConfig<${typeSchemas.request?.name}>> & { client?: Client }`
73
- : 'Partial<RequestConfig> & { client?: Client }',
38
+ const baseParams = ast.createOperationParams(node, {
39
+ paramsType,
40
+ pathParamsType: paramsType === 'object' ? 'object' : pathParamsType === 'object' ? 'object' : 'inline',
41
+ paramsCasing,
42
+ resolver,
43
+ extraParams: [
44
+ ast.createFunctionParameter({
45
+ name: 'config',
46
+ type: ast.createParamsType({
47
+ variant: 'reference',
48
+ name: requestName ? `Partial<RequestConfig<${requestName}>> & { client?: Client }` : 'Partial<RequestConfig> & { client?: Client }',
49
+ }),
74
50
  default: '{}',
75
- },
76
- })
77
- }
78
-
79
- return FunctionParams.factory({
80
- pathParams: {
81
- mode: pathParamsType === 'object' ? 'object' : 'inlineSpread',
82
- children: getPathParams(typeSchemas.pathParams, {
83
- typed: true,
84
- casing: paramsCasing,
85
- override(item) {
86
- return {
87
- ...item,
88
- type: `MaybeRefOrGetter<${item.type}>`,
89
- }
90
- },
91
51
  }),
92
- default: getDefaultValue(typeSchemas.pathParams?.schema),
93
- },
94
- data: typeSchemas.request?.name
95
- ? {
96
- type: `MaybeRefOrGetter<${typeSchemas.request?.name}>`,
97
- optional: isOptional(typeSchemas.request?.schema),
98
- }
99
- : undefined,
100
- params: typeSchemas.queryParams?.name
101
- ? {
102
- type: `MaybeRefOrGetter<${typeSchemas.queryParams?.name}>`,
103
- optional: isOptional(typeSchemas.queryParams?.schema),
104
- }
105
- : undefined,
106
- headers: typeSchemas.headerParams?.name
107
- ? {
108
- type: `MaybeRefOrGetter<${typeSchemas.queryParams?.name}>`,
109
- optional: isOptional(typeSchemas.headerParams?.schema),
110
- }
111
- : undefined,
112
- config: {
113
- type: typeSchemas.request?.name
114
- ? `Partial<RequestConfig<${typeSchemas.request?.name}>> & { client?: Client }`
115
- : 'Partial<RequestConfig> & { client?: Client }',
116
- default: '{}',
117
- },
52
+ ],
118
53
  })
54
+
55
+ return wrapWithMaybeRefOrGetter(baseParams, (name) => name === 'config')
119
56
  }
120
57
 
121
58
  export function QueryOptions({
122
59
  name,
123
60
  clientName,
124
61
  dataReturnType,
125
- typeSchemas,
62
+ node,
63
+ tsResolver,
126
64
  paramsCasing,
127
65
  paramsType,
128
66
  pathParamsType,
129
67
  queryKeyName,
130
- }: Props): FabricReactNode {
131
- const TData = dataReturnType === 'data' ? typeSchemas.response.name : `ResponseConfig<${typeSchemas.response.name}>`
132
- const TError = `ResponseErrorConfig<${typeSchemas.errors?.map((item) => item.name).join(' | ') || 'Error'}>`
68
+ }: Props): KubbReactNode {
69
+ const responseName = tsResolver.resolveResponseName(node)
70
+ const errorNames = resolveErrorNames(node, tsResolver)
133
71
 
134
- const params = getParams({ paramsType, paramsCasing, pathParamsType, typeSchemas })
135
- const clientParams = Client.getParams({
136
- paramsType,
137
- paramsCasing,
138
- typeSchemas,
139
- pathParamsType,
140
- isConfigurable: true,
141
- })
142
- const queryKeyParams = QueryKey.getParams({
143
- pathParamsType,
144
- typeSchemas,
145
- paramsCasing,
146
- })
72
+ const TData = dataReturnType === 'data' ? responseName : `ResponseConfig<${responseName}>`
73
+ const TError = `ResponseErrorConfig<${errorNames.length > 0 ? errorNames.join(' | ') : 'Error'}>`
147
74
 
148
- const enabled = Object.entries(queryKeyParams.flatParams)
149
- .map(([key, item]) => {
150
- // Only include if the parameter exists and is NOT optional
151
- // This ensures we only check required parameters
152
- return item && !item.optional && !item.default ? key : undefined
153
- })
154
- .filter(Boolean)
155
- .join('&& ')
75
+ const paramsNode = getQueryOptionsParams(node, { paramsType, paramsCasing, pathParamsType, resolver: tsResolver })
76
+ const paramsSignature = declarationPrinter.print(paramsNode) ?? ''
77
+ const rawParamsCall = callPrinter.print(paramsNode) ?? ''
156
78
 
157
- const enabledText = enabled ? `enabled: !!(${enabled}),` : ''
79
+ // Transform: wrap non-config params with toValue(), add signal to config
80
+ const clientCallStr = rawParamsCall.replace(/\bconfig\b(?=[^,]*$)/, '{ ...config, signal: config.signal ?? signal }')
81
+
82
+ const queryKeyParamsNode = buildQueryKeyParamsNode(node, { pathParamsType, paramsCasing, resolver: tsResolver })
83
+ const queryKeyParamsCall = callPrinter.print(queryKeyParamsNode) ?? ''
84
+
85
+ const enabledSource = buildEnabledCheck(queryKeyParamsNode)
86
+ const enabledText = enabledSource ? `enabled: () => !!(${enabledSource}),` : ''
158
87
 
159
88
  return (
160
89
  <File.Source name={name} isExportable isIndexable>
161
- <Function name={name} export params={params.toConstructor()}>
90
+ <Function name={name} export params={paramsSignature}>
162
91
  {`
163
- const queryKey = ${queryKeyName}(${queryKeyParams.toCall()})
164
- return queryOptions<${TData}, ${TError}, ${TData}, typeof queryKey>({
165
- ${enabledText}
166
- queryKey,
167
- queryFn: async ({ signal }) => {
168
- return ${clientName}(${clientParams.toCall({
169
- transformName(name) {
170
- if (name === 'config') {
171
- return '{ ...config, signal: config.signal ?? signal }'
172
- }
173
-
174
- return `toValue(${name})`
175
- },
176
- })})
92
+ const queryKey = ${queryKeyName}(${queryKeyParamsCall})
93
+ return queryOptions<${TData}, ${TError}, ${TData}>({
94
+ ${enabledText}
95
+ queryKey,
96
+ queryFn: async ({ signal }) => {
97
+ return ${clientName}(${addToValueCalls(clientCallStr)})
177
98
  },
178
99
  })
179
100
  `}
@@ -182,4 +103,32 @@ export function QueryOptions({
182
103
  )
183
104
  }
184
105
 
185
- QueryOptions.getParams = getParams
106
+ /**
107
+ * Wraps parameter names with `toValue()` in the client call string,
108
+ * except for 'config'-related params (which are already plain objects).
109
+ *
110
+ * Handles both inline params (`petId, config`) and object shorthand
111
+ * params (`{ petId }, config`) by expanding to `{ petId: toValue(petId) }`.
112
+ */
113
+ function addToValueCalls(callStr: string): string {
114
+ // Step 1: Transform shorthand object params like { petId } → { petId: toValue(petId) }
115
+ let result = callStr.replace(/\{\s*([\w,\s]+)\s*\}(?=\s*,)/g, (match, inner: string) => {
116
+ // Only transform simple shorthand (no colons, no spread)
117
+ if (inner.includes(':') || inner.includes('...')) return match
118
+ const keys = inner
119
+ .split(',')
120
+ .map((k: string) => k.trim())
121
+ .filter(Boolean)
122
+ const wrapped = keys.map((k: string) => `${k}: toValue(${k})`).join(', ')
123
+ return `{ ${wrapped} }`
124
+ })
125
+
126
+ // Step 2: Handle standalone identifiers like `data, params`
127
+ result = result.replace(/(?<![{.:?])\b(\w+)\b(?=\s*,)/g, (match, name: string) => {
128
+ if (name === 'config' || name === 'signal' || name === 'undefined') return match
129
+ if (match.includes('toValue(')) return match
130
+ return `toValue(${name})`
131
+ })
132
+
133
+ return result
134
+ }