@kubb/plugin-vue-query 5.0.0-alpha.8 → 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 -472
  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,212 +1,193 @@
1
1
  import path from 'node:path'
2
- import { usePluginDriver } from '@kubb/core/hooks'
3
- import { pluginClientName } from '@kubb/plugin-client'
4
- import { Client } from '@kubb/plugin-client/components'
5
- import { createReactGenerator } from '@kubb/plugin-oas/generators'
6
- import { useOas, useOperationManager } from '@kubb/plugin-oas/hooks'
7
- import { getBanner, getFooter } from '@kubb/plugin-oas/utils'
2
+ import { getOperationParameters, resolveOperationTypeNames } from '@internals/shared'
3
+ import { resolveZodSchemaNames } from '@internals/tanstack-query'
4
+ import { defineGenerator } from '@kubb/core'
5
+ import { Client, pluginClientName } from '@kubb/plugin-client'
8
6
  import { pluginTsName } from '@kubb/plugin-ts'
9
7
  import { pluginZodName } from '@kubb/plugin-zod'
10
- import { File } from '@kubb/react-fabric'
8
+ import { File, jsxRenderer } from '@kubb/renderer-jsx'
11
9
  import { difference } from 'remeda'
12
10
  import { InfiniteQuery, InfiniteQueryOptions, QueryKey } from '../components'
13
11
  import type { PluginVueQuery } from '../types'
14
12
 
15
- export const infiniteQueryGenerator = createReactGenerator<PluginVueQuery>({
16
- name: 'vue-infinite-query',
17
- Operation({ config, operation, generator, plugin }) {
18
- const {
19
- options,
20
- options: { output },
21
- } = plugin
22
- const driver = usePluginDriver()
23
-
24
- const oas = useOas()
25
- const { getSchemas, getName, getFile } = useOperationManager(generator)
26
-
27
- const isQuery = typeof options.query === 'boolean' ? true : options.query?.methods.some((method) => operation.method === method)
28
- const isMutation = difference(options.mutation ? options.mutation.methods : [], options.query ? options.query.methods : []).some(
29
- (method) => operation.method === method,
30
- )
31
- const isInfinite = isQuery && !!options.infinite
32
- const importPath = options.query ? options.query.importPath : '@tanstack/vue-query'
33
-
34
- const query = {
35
- name: getName(operation, {
36
- type: 'function',
37
- prefix: 'use',
38
- suffix: 'infinite',
39
- }),
40
- typeName: getName(operation, { type: 'type' }),
41
- file: getFile(operation, { prefix: 'use', suffix: 'infinite' }),
42
- }
13
+ export const infiniteQueryGenerator = defineGenerator<PluginVueQuery>({
14
+ name: 'vue-query-infinite',
15
+ renderer: jsxRenderer,
16
+ operation(node, ctx) {
17
+ const { adapter, config, driver, resolver, root } = ctx
18
+ const { output, query, mutation, infinite, paramsCasing, paramsType, pathParamsType, parser, client: clientOptions, group } = ctx.options
43
19
 
44
- const hasClientPlugin = !!driver.getPluginByName(pluginClientName)
45
- // Class-based clients are not compatible with query hooks, so we generate inline clients
46
- const shouldUseClientPlugin = hasClientPlugin && options.client.clientType !== 'class'
47
- const client = {
48
- name: shouldUseClientPlugin
49
- ? getName(operation, {
50
- type: 'function',
51
- pluginName: pluginClientName,
52
- })
53
- : getName(operation, {
54
- type: 'function',
55
- suffix: 'infinite',
56
- }),
57
- file: getFile(operation, { pluginName: pluginClientName }),
58
- }
20
+ const pluginTs = driver.getPlugin(pluginTsName)
21
+ if (!pluginTs) return null
22
+ const tsResolver = driver.getResolver(pluginTsName)
59
23
 
60
- const queryOptions = {
61
- name: getName(operation, {
62
- type: 'function',
63
- suffix: 'InfiniteQueryOptions',
64
- }),
65
- }
24
+ const isQuery = query === false || (!!query && query.methods.some((method) => node.method.toLowerCase() === method.toLowerCase()))
25
+ const isMutation =
26
+ mutation !== false &&
27
+ !isQuery &&
28
+ difference(mutation ? mutation.methods : [], query ? query.methods : []).some((method) => node.method.toLowerCase() === method.toLowerCase())
29
+ const infiniteOptions = infinite && typeof infinite === 'object' ? infinite : undefined
66
30
 
67
- const queryKey = {
68
- name: getName(operation, { type: 'const', suffix: 'InfiniteQueryKey' }),
69
- typeName: getName(operation, {
70
- type: 'type',
71
- suffix: 'InfiniteQueryKey',
72
- }),
73
- }
31
+ if (!isQuery || isMutation || !infiniteOptions) return null
74
32
 
75
- const type = {
76
- file: getFile(operation, { pluginName: pluginTsName }),
77
- //todo remove type?
78
- schemas: getSchemas(operation, {
79
- pluginName: pluginTsName,
80
- type: 'type',
81
- }),
82
- }
33
+ // Validate queryParam exists in operation's query parameters
34
+ const normalizeKey = (key: string) => key.replace(/\?$/, '')
35
+ const queryParamKeys = getOperationParameters(node).query.map((p) => p.name)
36
+ const hasQueryParam = infiniteOptions.queryParam ? queryParamKeys.some((k) => normalizeKey(k) === infiniteOptions.queryParam) : false
37
+ // cursorParam validation against response schema keys is skipped in v5 (complex schema inspection)
38
+ const hasCursorParam = !infiniteOptions.cursorParam || true
83
39
 
84
- const zod = {
85
- file: getFile(operation, { pluginName: pluginZodName }),
86
- schemas: getSchemas(operation, {
87
- pluginName: pluginZodName,
88
- type: 'function',
89
- }),
90
- }
40
+ if (!hasQueryParam || !hasCursorParam) return null
41
+
42
+ const importPath = query ? query.importPath : '@tanstack/vue-query'
43
+
44
+ const queryName = resolver.resolveInfiniteQueryName(node)
45
+ const queryOptionsName = resolver.resolveInfiniteQueryOptionsName(node)
46
+ const queryKeyName = resolver.resolveInfiniteQueryKeyName(node)
47
+ const queryKeyTypeName = resolver.resolveInfiniteQueryKeyTypeName(node)
48
+ const clientBaseName = resolver.resolveInfiniteClientName(node)
91
49
 
92
- if (!isQuery || isMutation || !isInfinite) {
93
- return null
50
+ const meta = {
51
+ file: resolver.resolveFile({ name: queryName, extname: '.ts', tag: node.tags[0] ?? 'default', path: node.path }, { root, output, group }),
52
+ fileTs: tsResolver.resolveFile(
53
+ { name: node.operationId, extname: '.ts', tag: node.tags[0] ?? 'default', path: node.path },
54
+ { root, output: pluginTs.options?.output ?? output, group: pluginTs.options?.group },
55
+ ),
94
56
  }
95
57
 
58
+ const importedTypeNames = resolveOperationTypeNames(node, tsResolver, {
59
+ paramsCasing,
60
+ exclude: [queryKeyTypeName],
61
+ order: 'body-response-first',
62
+ })
63
+
64
+ const pluginZod = parser === 'zod' ? driver.getPlugin(pluginZodName) : undefined
65
+ const zodResolver = pluginZod ? driver.getResolver(pluginZodName) : undefined
66
+ const fileZod = zodResolver
67
+ ? zodResolver.resolveFile(
68
+ { name: node.operationId, extname: '.ts', tag: node.tags[0] ?? 'default', path: node.path },
69
+ { root, output: pluginZod?.options?.output ?? output, group: pluginZod?.options?.group },
70
+ )
71
+ : undefined
72
+ const zodSchemaNames = resolveZodSchemaNames(node, zodResolver)
73
+
74
+ const clientPlugin = driver.getPlugin(pluginClientName)
75
+ const hasClientPlugin = clientPlugin?.name === pluginClientName
76
+ const shouldUseClientPlugin = hasClientPlugin && clientOptions.clientType !== 'class'
77
+ const clientResolver = shouldUseClientPlugin ? driver.getResolver(pluginClientName) : undefined
78
+
79
+ const clientFile = shouldUseClientPlugin
80
+ ? clientResolver?.resolveFile(
81
+ { name: node.operationId, extname: '.ts', tag: node.tags[0] ?? 'default', path: node.path },
82
+ {
83
+ root,
84
+ output: clientPlugin?.options?.output ?? output,
85
+ group: clientPlugin?.options?.group,
86
+ },
87
+ )
88
+ : undefined
89
+
90
+ const resolvedClientName = shouldUseClientPlugin ? (clientResolver?.resolveName(node.operationId) ?? clientBaseName) : clientBaseName
91
+
96
92
  return (
97
93
  <File
98
- baseName={query.file.baseName}
99
- path={query.file.path}
100
- meta={query.file.meta}
101
- banner={getBanner({ oas, output, config: driver.config })}
102
- footer={getFooter({ oas, output })}
94
+ baseName={meta.file.baseName}
95
+ path={meta.file.path}
96
+ meta={meta.file.meta}
97
+ banner={resolver.resolveBanner(adapter.inputNode, { output, config })}
98
+ footer={resolver.resolveFooter(adapter.inputNode, { output, config })}
103
99
  >
104
- {options.parser === 'zod' && (
105
- <File.Import name={[zod.schemas.response.name, zod.schemas.request?.name].filter(Boolean)} root={query.file.path} path={zod.file.path} />
106
- )}
107
- {options.client.importPath ? (
100
+ {fileZod && zodSchemaNames.length > 0 && <File.Import name={zodSchemaNames} root={meta.file.path} path={fileZod.path} />}
101
+ {clientOptions.importPath ? (
108
102
  <>
109
- {!shouldUseClientPlugin && <File.Import name={'fetch'} path={options.client.importPath} />}
110
- <File.Import name={['Client', 'RequestConfig', 'ResponseErrorConfig']} path={options.client.importPath} isTypeOnly />
111
- {options.client.dataReturnType === 'full' && <File.Import name={['ResponseConfig']} path={options.client.importPath} isTypeOnly />}
103
+ {!shouldUseClientPlugin && <File.Import name={'fetch'} path={clientOptions.importPath} />}
104
+ <File.Import name={['Client', 'RequestConfig', 'ResponseErrorConfig']} path={clientOptions.importPath} isTypeOnly />
105
+ {clientOptions.dataReturnType === 'full' && <File.Import name={['ResponseConfig']} path={clientOptions.importPath} isTypeOnly />}
112
106
  </>
113
107
  ) : (
114
108
  <>
115
- {!shouldUseClientPlugin && (
116
- <File.Import name={['fetch']} root={query.file.path} path={path.resolve(config.root, config.output.path, '.kubb/fetch.ts')} />
117
- )}
109
+ {!shouldUseClientPlugin && <File.Import name={['fetch']} root={meta.file.path} path={path.resolve(root, '.kubb/fetch.ts')} />}
118
110
  <File.Import
119
111
  name={['Client', 'RequestConfig', 'ResponseErrorConfig']}
120
- root={query.file.path}
121
- path={path.resolve(config.root, config.output.path, '.kubb/fetch.ts')}
112
+ root={meta.file.path}
113
+ path={path.resolve(root, '.kubb/fetch.ts')}
122
114
  isTypeOnly
123
115
  />
124
- {options.client.dataReturnType === 'full' && (
125
- <File.Import name={['ResponseConfig']} root={query.file.path} path={path.resolve(config.root, config.output.path, '.kubb/fetch.ts')} isTypeOnly />
116
+ {clientOptions.dataReturnType === 'full' && (
117
+ <File.Import name={['ResponseConfig']} root={meta.file.path} path={path.resolve(root, '.kubb/fetch.ts')} isTypeOnly />
126
118
  )}
127
119
  </>
128
120
  )}
129
121
  <File.Import name={['toValue']} path="vue" />
130
122
  <File.Import name={['MaybeRefOrGetter']} path="vue" isTypeOnly />
131
- {shouldUseClientPlugin && <File.Import name={[client.name]} root={query.file.path} path={client.file.path} />}
132
- {!shouldUseClientPlugin && (
133
- <File.Import name={['buildFormData']} root={query.file.path} path={path.resolve(config.root, config.output.path, '.kubb/config.ts')} />
123
+ {shouldUseClientPlugin && clientFile && <File.Import name={[resolvedClientName]} root={meta.file.path} path={clientFile.path} />}
124
+ {!shouldUseClientPlugin && <File.Import name={['buildFormData']} root={meta.file.path} path={path.resolve(root, '.kubb/config.ts')} />}
125
+ {meta.fileTs && importedTypeNames.length > 0 && (
126
+ <File.Import name={Array.from(new Set(importedTypeNames))} root={meta.file.path} path={meta.fileTs.path} isTypeOnly />
134
127
  )}
135
- <File.Import
136
- name={[
137
- type.schemas.request?.name,
138
- type.schemas.response.name,
139
- type.schemas.pathParams?.name,
140
- type.schemas.queryParams?.name,
141
- type.schemas.headerParams?.name,
142
- ...(type.schemas.statusCodes?.map((item) => item.name) || []),
143
- ].filter(Boolean)}
144
- root={query.file.path}
145
- path={type.file.path}
146
- isTypeOnly
147
- />
128
+
148
129
  <QueryKey
149
- name={queryKey.name}
150
- typeName={queryKey.typeName}
151
- operation={operation}
152
- paramsCasing={options.paramsCasing}
153
- pathParamsType={options.pathParamsType}
154
- typeSchemas={type.schemas}
155
- transformer={options.queryKey}
130
+ name={queryKeyName}
131
+ typeName={queryKeyTypeName}
132
+ node={node}
133
+ tsResolver={tsResolver}
134
+ pathParamsType={pathParamsType}
135
+ paramsCasing={paramsCasing}
136
+ transformer={ctx.options.queryKey}
156
137
  />
138
+
157
139
  {!shouldUseClientPlugin && (
158
140
  <Client
159
- name={client.name}
160
- baseURL={options.client.baseURL}
161
- operation={operation}
162
- typeSchemas={type.schemas}
163
- zodSchemas={zod.schemas}
164
- dataReturnType={options.client.dataReturnType || 'data'}
165
- paramsCasing={options.client?.paramsCasing || options.paramsCasing}
166
- paramsType={options.paramsType}
167
- pathParamsType={options.pathParamsType}
168
- parser={options.parser}
141
+ name={resolvedClientName}
142
+ baseURL={clientOptions.baseURL}
143
+ dataReturnType={clientOptions.dataReturnType || 'data'}
144
+ paramsCasing={clientOptions.paramsCasing || paramsCasing}
145
+ paramsType={paramsType}
146
+ pathParamsType={pathParamsType}
147
+ parser={parser}
148
+ node={node}
149
+ tsResolver={tsResolver}
150
+ zodResolver={zodResolver}
169
151
  />
170
152
  )}
171
- {options.infinite && (
172
- <>
173
- <File.Import name={['InfiniteData']} isTypeOnly path={importPath} />
174
- <File.Import name={['infiniteQueryOptions']} path={importPath} />
175
- <InfiniteQueryOptions
176
- name={queryOptions.name}
177
- clientName={client.name}
178
- queryKeyName={queryKey.name}
179
- typeSchemas={type.schemas}
180
- paramsType={options.paramsType}
181
- paramsCasing={options.paramsCasing}
182
- pathParamsType={options.pathParamsType}
183
- dataReturnType={options.client.dataReturnType || 'data'}
184
- cursorParam={options.infinite.cursorParam}
185
- nextParam={options.infinite.nextParam}
186
- previousParam={options.infinite.previousParam}
187
- initialPageParam={options.infinite.initialPageParam}
188
- queryParam={options.infinite.queryParam}
189
- />
190
- </>
191
- )}
192
- {options.infinite && (
193
- <>
194
- <File.Import name={['useInfiniteQuery']} path={importPath} />
195
- <File.Import name={['QueryKey', 'QueryClient', 'UseInfiniteQueryOptions', 'UseInfiniteQueryReturnType']} path={importPath} isTypeOnly />
196
- <InfiniteQuery
197
- name={query.name}
198
- queryOptionsName={queryOptions.name}
199
- typeSchemas={type.schemas}
200
- paramsCasing={options.paramsCasing}
201
- paramsType={options.paramsType}
202
- pathParamsType={options.pathParamsType}
203
- operation={operation}
204
- dataReturnType={options.client.dataReturnType || 'data'}
205
- queryKeyName={queryKey.name}
206
- queryKeyTypeName={queryKey.typeName}
207
- />
208
- </>
209
- )}
153
+
154
+ <File.Import name={['InfiniteData']} isTypeOnly path={importPath} />
155
+ <File.Import name={['infiniteQueryOptions']} path={importPath} />
156
+
157
+ <InfiniteQueryOptions
158
+ name={queryOptionsName}
159
+ clientName={resolvedClientName}
160
+ queryKeyName={queryKeyName}
161
+ node={node}
162
+ tsResolver={tsResolver}
163
+ paramsCasing={paramsCasing}
164
+ paramsType={paramsType}
165
+ pathParamsType={pathParamsType}
166
+ dataReturnType={clientOptions.dataReturnType || 'data'}
167
+ cursorParam={infiniteOptions.cursorParam}
168
+ nextParam={infiniteOptions.nextParam}
169
+ previousParam={infiniteOptions.previousParam}
170
+ initialPageParam={infiniteOptions.initialPageParam}
171
+ queryParam={infiniteOptions.queryParam}
172
+ />
173
+
174
+ <File.Import name={['useInfiniteQuery']} path={importPath} />
175
+ <File.Import name={['QueryKey', 'QueryClient', 'UseInfiniteQueryOptions', 'UseInfiniteQueryReturnType']} path={importPath} isTypeOnly />
176
+
177
+ <InfiniteQuery
178
+ name={queryName}
179
+ queryOptionsName={queryOptionsName}
180
+ queryKeyName={queryKeyName}
181
+ queryKeyTypeName={queryKeyTypeName}
182
+ node={node}
183
+ tsResolver={tsResolver}
184
+ paramsCasing={paramsCasing}
185
+ paramsType={paramsType}
186
+ pathParamsType={pathParamsType}
187
+ dataReturnType={clientOptions.dataReturnType || 'data'}
188
+ initialPageParam={infiniteOptions.initialPageParam}
189
+ queryParam={infiniteOptions.queryParam}
190
+ />
210
191
  </File>
211
192
  )
212
193
  },
@@ -1,172 +1,149 @@
1
1
  import path from 'node:path'
2
- import { usePluginDriver } from '@kubb/core/hooks'
3
- import { pluginClientName } from '@kubb/plugin-client'
4
- import { Client } from '@kubb/plugin-client/components'
5
- import { createReactGenerator } from '@kubb/plugin-oas/generators'
6
- import { useOas, useOperationManager } from '@kubb/plugin-oas/hooks'
7
- import { getBanner, getFooter } from '@kubb/plugin-oas/utils'
2
+ import { resolveOperationTypeNames } from '@internals/shared'
3
+ import { resolveZodSchemaNames } from '@internals/tanstack-query'
4
+ import { defineGenerator } from '@kubb/core'
5
+ import { Client, pluginClientName } from '@kubb/plugin-client'
8
6
  import { pluginTsName } from '@kubb/plugin-ts'
9
7
  import { pluginZodName } from '@kubb/plugin-zod'
10
- import { File } from '@kubb/react-fabric'
8
+ import { File, jsxRenderer } from '@kubb/renderer-jsx'
11
9
  import { difference } from 'remeda'
12
10
  import { Mutation, MutationKey } from '../components'
13
11
  import type { PluginVueQuery } from '../types'
14
12
 
15
- export const mutationGenerator = createReactGenerator<PluginVueQuery>({
16
- name: 'vue-query',
17
- Operation({ config, operation, generator, plugin }) {
18
- const {
19
- options,
20
- options: { output },
21
- } = plugin
22
- const driver = usePluginDriver()
13
+ export const mutationGenerator = defineGenerator<PluginVueQuery>({
14
+ name: 'vue-query-mutation',
15
+ renderer: jsxRenderer,
16
+ operation(node, ctx) {
17
+ const { adapter, config, driver, resolver, root } = ctx
18
+ const { output, query, mutation, paramsCasing, paramsType, pathParamsType, parser, client: clientOptions, group } = ctx.options
23
19
 
24
- const oas = useOas()
25
- const { getSchemas, getName, getFile } = useOperationManager(generator)
20
+ const pluginTs = driver.getPlugin(pluginTsName)
21
+ if (!pluginTs) return null
22
+ const tsResolver = driver.getResolver(pluginTsName)
26
23
 
27
- const isQuery = !!options.query && options.query?.methods.some((method) => operation.method === method)
24
+ const isQuery = query === false || (!!query && query.methods.some((method) => node.method.toLowerCase() === method.toLowerCase()))
28
25
  const isMutation =
29
- options.mutation !== false &&
26
+ mutation !== false &&
30
27
  !isQuery &&
31
- difference(options.mutation ? options.mutation.methods : [], options.query ? options.query.methods : []).some((method) => operation.method === method)
28
+ difference(mutation ? mutation.methods : [], query ? query.methods : []).some((method) => node.method.toLowerCase() === method.toLowerCase())
32
29
 
33
- const importPath = options.mutation ? options.mutation.importPath : '@tanstack/vue-query'
30
+ if (!isMutation) return null
34
31
 
35
- const mutation = {
36
- name: getName(operation, { type: 'function', prefix: 'use' }),
37
- typeName: getName(operation, { type: 'type' }),
38
- file: getFile(operation, { prefix: 'use' }),
39
- }
32
+ const importPath = mutation ? mutation.importPath : '@tanstack/vue-query'
40
33
 
41
- const type = {
42
- file: getFile(operation, { pluginName: pluginTsName }),
43
- //todo remove type?
44
- schemas: getSchemas(operation, { pluginName: pluginTsName, type: 'type' }),
45
- }
34
+ const mutationHookName = resolver.resolveMutationName(node)
35
+ const mutationTypeName = resolver.resolveMutationTypeName(node)
36
+ const mutationKeyName = resolver.resolveMutationKeyName(node)
37
+ const clientName = resolver.resolveClientName(node)
46
38
 
47
- const zod = {
48
- file: getFile(operation, { pluginName: pluginZodName }),
49
- schemas: getSchemas(operation, { pluginName: pluginZodName, type: 'function' }),
39
+ const meta = {
40
+ file: resolver.resolveFile({ name: mutationHookName, extname: '.ts', tag: node.tags[0] ?? 'default', path: node.path }, { root, output, group }),
41
+ fileTs: tsResolver.resolveFile(
42
+ { name: node.operationId, extname: '.ts', tag: node.tags[0] ?? 'default', path: node.path },
43
+ { root, output: pluginTs.options?.output ?? output, group: pluginTs.options?.group },
44
+ ),
50
45
  }
51
46
 
52
- const hasClientPlugin = !!driver.getPluginByName(pluginClientName)
53
- // Class-based clients are not compatible with query hooks, so we generate inline clients
54
- const shouldUseClientPlugin = hasClientPlugin && options.client.clientType !== 'class'
55
- const client = {
56
- name: shouldUseClientPlugin
57
- ? getName(operation, {
58
- type: 'function',
59
- pluginName: pluginClientName,
60
- })
61
- : getName(operation, {
62
- type: 'function',
63
- }),
64
- file: getFile(operation, { pluginName: pluginClientName }),
65
- }
47
+ const importedTypeNames = resolveOperationTypeNames(node, tsResolver, { paramsCasing, order: 'body-response-first' })
66
48
 
67
- const mutationKey = {
68
- name: getName(operation, { type: 'const', suffix: 'MutationKey' }),
69
- typeName: getName(operation, { type: 'type', suffix: 'MutationKey' }),
70
- }
49
+ const pluginZod = parser === 'zod' ? driver.getPlugin(pluginZodName) : undefined
50
+ const zodResolver = pluginZod ? driver.getResolver(pluginZodName) : undefined
51
+ const fileZod = zodResolver
52
+ ? zodResolver.resolveFile(
53
+ { name: node.operationId, extname: '.ts', tag: node.tags[0] ?? 'default', path: node.path },
54
+ { root, output: pluginZod?.options?.output ?? output, group: pluginZod?.options?.group },
55
+ )
56
+ : undefined
57
+ const zodSchemaNames = resolveZodSchemaNames(node, zodResolver)
71
58
 
72
- if (!isMutation) {
73
- return null
74
- }
59
+ const clientPlugin = driver.getPlugin(pluginClientName)
60
+ const hasClientPlugin = clientPlugin?.name === pluginClientName
61
+ const shouldUseClientPlugin = hasClientPlugin && clientOptions.clientType !== 'class'
62
+ const clientResolver = shouldUseClientPlugin ? driver.getResolver(pluginClientName) : undefined
63
+
64
+ const clientFile = shouldUseClientPlugin
65
+ ? clientResolver?.resolveFile(
66
+ { name: node.operationId, extname: '.ts', tag: node.tags[0] ?? 'default', path: node.path },
67
+ {
68
+ root,
69
+ output: clientPlugin?.options?.output ?? output,
70
+ group: clientPlugin?.options?.group,
71
+ },
72
+ )
73
+ : undefined
74
+
75
+ const resolvedClientName = shouldUseClientPlugin ? (clientResolver?.resolveName(node.operationId) ?? clientName) : clientName
75
76
 
76
77
  return (
77
78
  <File
78
- baseName={mutation.file.baseName}
79
- path={mutation.file.path}
80
- meta={mutation.file.meta}
81
- banner={getBanner({ oas, output, config: driver.config })}
82
- footer={getFooter({ oas, output })}
79
+ baseName={meta.file.baseName}
80
+ path={meta.file.path}
81
+ meta={meta.file.meta}
82
+ banner={resolver.resolveBanner(adapter.inputNode, { output, config })}
83
+ footer={resolver.resolveFooter(adapter.inputNode, { output, config })}
83
84
  >
84
- {options.parser === 'zod' && (
85
- <File.Import name={[zod.schemas.response.name, zod.schemas.request?.name].filter(Boolean)} root={mutation.file.path} path={zod.file.path} />
86
- )}
87
- {options.client.importPath ? (
85
+ {fileZod && zodSchemaNames.length > 0 && <File.Import name={zodSchemaNames} root={meta.file.path} path={fileZod.path} />}
86
+ {clientOptions.importPath ? (
88
87
  <>
89
- {!shouldUseClientPlugin && <File.Import name={'fetch'} path={options.client.importPath} />}
90
- <File.Import name={['Client', 'RequestConfig', 'ResponseErrorConfig']} path={options.client.importPath} isTypeOnly />
91
- {options.client.dataReturnType === 'full' && <File.Import name={['ResponseConfig']} path={options.client.importPath} isTypeOnly />}
88
+ {!shouldUseClientPlugin && <File.Import name={'fetch'} path={clientOptions.importPath} />}
89
+ <File.Import name={['Client', 'RequestConfig', 'ResponseErrorConfig']} path={clientOptions.importPath} isTypeOnly />
90
+ {clientOptions.dataReturnType === 'full' && <File.Import name={['ResponseConfig']} path={clientOptions.importPath} isTypeOnly />}
92
91
  </>
93
92
  ) : (
94
93
  <>
95
- {!shouldUseClientPlugin && (
96
- <File.Import name={['fetch']} root={mutation.file.path} path={path.resolve(config.root, config.output.path, '.kubb/fetch.ts')} />
97
- )}
94
+ {!shouldUseClientPlugin && <File.Import name={['fetch']} root={meta.file.path} path={path.resolve(root, '.kubb/fetch.ts')} />}
98
95
  <File.Import
99
96
  name={['Client', 'RequestConfig', 'ResponseErrorConfig']}
100
- root={mutation.file.path}
101
- path={path.resolve(config.root, config.output.path, '.kubb/fetch.ts')}
97
+ root={meta.file.path}
98
+ path={path.resolve(root, '.kubb/fetch.ts')}
102
99
  isTypeOnly
103
100
  />
104
- {options.client.dataReturnType === 'full' && (
105
- <File.Import
106
- name={['ResponseConfig']}
107
- root={mutation.file.path}
108
- path={path.resolve(config.root, config.output.path, '.kubb/fetch.ts')}
109
- isTypeOnly
110
- />
101
+ {clientOptions.dataReturnType === 'full' && (
102
+ <File.Import name={['ResponseConfig']} root={meta.file.path} path={path.resolve(root, '.kubb/fetch.ts')} isTypeOnly />
111
103
  )}
112
104
  </>
113
105
  )}
114
106
  <File.Import name={['MaybeRefOrGetter']} path="vue" isTypeOnly />
115
- {shouldUseClientPlugin && <File.Import name={[client.name]} root={mutation.file.path} path={client.file.path} />}
116
- {!shouldUseClientPlugin && (
117
- <File.Import name={['buildFormData']} root={mutation.file.path} path={path.resolve(config.root, config.output.path, '.kubb/config.ts')} />
107
+ {shouldUseClientPlugin && clientFile && <File.Import name={[resolvedClientName]} root={meta.file.path} path={clientFile.path} />}
108
+ {!shouldUseClientPlugin && node.requestBody?.content?.some((e) => e.contentType === 'multipart/form-data') && (
109
+ <File.Import name={['buildFormData']} root={meta.file.path} path={path.resolve(root, '.kubb/config.ts')} />
110
+ )}
111
+ {meta.fileTs && importedTypeNames.length > 0 && (
112
+ <File.Import name={Array.from(new Set(importedTypeNames))} root={meta.file.path} path={meta.fileTs.path} isTypeOnly />
118
113
  )}
119
- <File.Import
120
- name={[
121
- type.schemas.request?.name,
122
- type.schemas.response.name,
123
- type.schemas.pathParams?.name,
124
- type.schemas.queryParams?.name,
125
- type.schemas.headerParams?.name,
126
- ...(type.schemas.statusCodes?.map((item) => item.name) || []),
127
- ].filter(Boolean)}
128
- root={mutation.file.path}
129
- path={type.file.path}
130
- isTypeOnly
131
- />
132
- <MutationKey
133
- name={mutationKey.name}
134
- typeName={mutationKey.typeName}
135
- operation={operation}
136
- pathParamsType={options.pathParamsType}
137
- paramsCasing={options.paramsCasing}
138
- typeSchemas={type.schemas}
139
- transformer={options.mutationKey}
140
- />
114
+
115
+ <MutationKey name={mutationKeyName} node={node} pathParamsType={pathParamsType} paramsCasing={paramsCasing} transformer={ctx.options.mutationKey} />
116
+
141
117
  {!shouldUseClientPlugin && (
142
118
  <Client
143
- name={client.name}
144
- baseURL={options.client.baseURL}
145
- operation={operation}
146
- typeSchemas={type.schemas}
147
- zodSchemas={zod.schemas}
148
- dataReturnType={options.client.dataReturnType || 'data'}
149
- paramsCasing={options.client?.paramsCasing || options.paramsCasing}
150
- paramsType={options.paramsType}
151
- pathParamsType={options.pathParamsType}
152
- parser={options.parser}
119
+ name={resolvedClientName}
120
+ baseURL={clientOptions.baseURL}
121
+ dataReturnType={clientOptions.dataReturnType || 'data'}
122
+ paramsCasing={clientOptions.paramsCasing || paramsCasing}
123
+ paramsType={paramsType}
124
+ pathParamsType={pathParamsType}
125
+ parser={parser}
126
+ node={node}
127
+ tsResolver={tsResolver}
128
+ zodResolver={zodResolver}
153
129
  />
154
130
  )}
155
- {options.mutation && (
131
+
132
+ {mutation && (
156
133
  <>
157
134
  <File.Import name={['useMutation']} path={importPath} />
158
135
  <File.Import name={['MutationObserverOptions', 'QueryClient']} path={importPath} isTypeOnly />
159
136
  <Mutation
160
- name={mutation.name}
161
- clientName={client.name}
162
- typeName={mutation.typeName}
163
- typeSchemas={type.schemas}
164
- operation={operation}
165
- paramsCasing={options.paramsCasing}
166
- dataReturnType={options.client.dataReturnType || 'data'}
167
- paramsType={options.paramsType}
168
- pathParamsType={options.pathParamsType}
169
- mutationKeyName={mutationKey.name}
137
+ name={mutationHookName}
138
+ clientName={resolvedClientName}
139
+ typeName={mutationTypeName}
140
+ node={node}
141
+ tsResolver={tsResolver}
142
+ paramsCasing={paramsCasing}
143
+ dataReturnType={clientOptions.dataReturnType || 'data'}
144
+ paramsType={paramsType}
145
+ pathParamsType={pathParamsType}
146
+ mutationKeyName={mutationKeyName}
170
147
  />
171
148
  </>
172
149
  )}