@kubb/plugin-react-query 3.0.0-alpha.9 → 3.0.0-beta.2

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 (78) hide show
  1. package/README.md +14 -5
  2. package/dist/chunk-37VO6QXJ.cjs +669 -0
  3. package/dist/chunk-37VO6QXJ.cjs.map +1 -0
  4. package/dist/chunk-C2H3KPHM.cjs +658 -0
  5. package/dist/chunk-C2H3KPHM.cjs.map +1 -0
  6. package/dist/chunk-IRW2Y3EC.js +660 -0
  7. package/dist/chunk-IRW2Y3EC.js.map +1 -0
  8. package/dist/chunk-Y3DM2P6L.js +647 -0
  9. package/dist/chunk-Y3DM2P6L.js.map +1 -0
  10. package/dist/components.cjs +39 -12
  11. package/dist/components.cjs.map +1 -1
  12. package/dist/components.d.cts +161 -6
  13. package/dist/components.d.ts +161 -6
  14. package/dist/components.js +2 -12
  15. package/dist/components.js.map +1 -1
  16. package/dist/generators.cjs +25 -0
  17. package/dist/generators.cjs.map +1 -0
  18. package/dist/generators.d.cts +14 -0
  19. package/dist/generators.d.ts +14 -0
  20. package/dist/generators.js +4 -0
  21. package/dist/generators.js.map +1 -0
  22. package/dist/index.cjs +78 -130
  23. package/dist/index.cjs.map +1 -1
  24. package/dist/index.d.cts +1 -4
  25. package/dist/index.d.ts +1 -4
  26. package/dist/index.js +61 -120
  27. package/dist/index.js.map +1 -1
  28. package/dist/types-5pnOmDmM.d.cts +231 -0
  29. package/dist/types-5pnOmDmM.d.ts +231 -0
  30. package/package.json +22 -17
  31. package/src/components/InfiniteQuery.tsx +129 -0
  32. package/src/components/InfiniteQueryOptions.tsx +130 -0
  33. package/src/components/Mutation.tsx +137 -321
  34. package/src/components/MutationKey.tsx +48 -0
  35. package/src/components/Query.tsx +91 -594
  36. package/src/components/QueryKey.tsx +51 -182
  37. package/src/components/QueryOptions.tsx +71 -473
  38. package/src/components/SuspenseQuery.tsx +129 -0
  39. package/src/components/index.ts +4 -0
  40. package/src/generators/__snapshots__/clientDataReturnTypeFull.ts +51 -0
  41. package/src/generators/__snapshots__/clientGetImportPath.ts +51 -0
  42. package/src/generators/__snapshots__/clientPostImportPath.ts +44 -0
  43. package/src/generators/__snapshots__/findByTags.ts +51 -0
  44. package/src/generators/__snapshots__/findByTagsPathParamsObject.ts +51 -0
  45. package/src/generators/__snapshots__/findByTagsWithCustomQueryKey.ts +51 -0
  46. package/src/generators/__snapshots__/findByTagsWithZod.ts +51 -0
  47. package/src/generators/__snapshots__/findInfiniteByTags.ts +57 -0
  48. package/src/generators/__snapshots__/findInfiniteByTagsCursor.ts +57 -0
  49. package/src/generators/__snapshots__/getAsMutation.ts +31 -0
  50. package/src/generators/__snapshots__/postAsQuery.ts +50 -0
  51. package/src/generators/__snapshots__/updatePetById.ts +44 -0
  52. package/src/generators/__snapshots__/updatePetByIdPathParamsObject.ts +46 -0
  53. package/src/generators/index.ts +4 -0
  54. package/src/generators/infiniteQueryGenerator.tsx +124 -0
  55. package/src/generators/mutationGenerator.tsx +108 -0
  56. package/src/generators/queryGenerator.tsx +121 -0
  57. package/src/generators/suspenseQueryGenerator.tsx +120 -0
  58. package/src/plugin.ts +60 -76
  59. package/src/types.ts +42 -115
  60. package/dist/chunk-7ZODZVKP.cjs +0 -1470
  61. package/dist/chunk-7ZODZVKP.cjs.map +0 -1
  62. package/dist/chunk-ZYTZV43V.js +0 -1470
  63. package/dist/chunk-ZYTZV43V.js.map +0 -1
  64. package/dist/index-5kpkk-7M.d.cts +0 -545
  65. package/dist/index-5kpkk-7M.d.ts +0 -545
  66. package/src/OperationGenerator.tsx +0 -57
  67. package/src/__snapshots__/mutateAsQuery/updatePetWithForm.ts +0 -69
  68. package/src/__snapshots__/pathParamsTypeInline/getPetById.ts +0 -62
  69. package/src/__snapshots__/pathParamsTypeObject/getPetById.ts +0 -68
  70. package/src/__snapshots__/queryOptions/getPetById.ts +0 -41
  71. package/src/__snapshots__/queryWithoutQueryOptions/getPetById.ts +0 -51
  72. package/src/__snapshots__/variablesTypeMutate/deletePet.ts +0 -24
  73. package/src/components/QueryImports.tsx +0 -167
  74. package/src/components/SchemaType.tsx +0 -59
  75. package/src/components/__snapshots__/gen/showPetById.ts +0 -67
  76. package/src/components/__snapshots__/gen/useCreatePets.ts +0 -46
  77. package/src/components/__snapshots__/gen/useCreatePetsMutate.ts +0 -46
  78. package/src/utils.ts +0 -96
@@ -0,0 +1,130 @@
1
+ import { getPathParams } from '@kubb/plugin-oas/utils'
2
+ import { File, Function, FunctionParams } from '@kubb/react'
3
+
4
+ import type { ReactNode } from 'react'
5
+
6
+ import { isOptional } from '@kubb/oas'
7
+ import { Client } from '@kubb/plugin-client/components'
8
+ import type { OperationSchemas } from '@kubb/plugin-oas'
9
+ import type { Infinite, PluginReactQuery } from '../types.ts'
10
+ import { QueryKey } from './QueryKey.tsx'
11
+
12
+ type Props = {
13
+ name: string
14
+ clientName: string
15
+ queryKeyName: string
16
+ typeSchemas: OperationSchemas
17
+ pathParamsType: PluginReactQuery['resolvedOptions']['pathParamsType']
18
+ dataReturnType: PluginReactQuery['resolvedOptions']['client']['dataReturnType']
19
+ initialPageParam: Infinite['initialPageParam']
20
+ cursorParam: Infinite['cursorParam']
21
+ queryParam: Infinite['queryParam']
22
+ }
23
+
24
+ type GetParamsProps = {
25
+ pathParamsType: PluginReactQuery['resolvedOptions']['pathParamsType']
26
+ typeSchemas: OperationSchemas
27
+ }
28
+
29
+ function getParams({ pathParamsType, typeSchemas }: GetParamsProps) {
30
+ return FunctionParams.factory({
31
+ pathParams: {
32
+ mode: pathParamsType === 'object' ? 'object' : 'inlineSpread',
33
+ children: getPathParams(typeSchemas.pathParams, { typed: true }),
34
+ },
35
+ data: typeSchemas.request?.name
36
+ ? {
37
+ type: typeSchemas.request?.name,
38
+ optional: isOptional(typeSchemas.request?.schema),
39
+ }
40
+ : undefined,
41
+ params: typeSchemas.queryParams?.name
42
+ ? {
43
+ type: typeSchemas.queryParams?.name,
44
+ optional: isOptional(typeSchemas.queryParams?.schema),
45
+ }
46
+ : undefined,
47
+ headers: typeSchemas.headerParams?.name
48
+ ? {
49
+ type: typeSchemas.headerParams?.name,
50
+ optional: isOptional(typeSchemas.headerParams?.schema),
51
+ }
52
+ : undefined,
53
+ config: {
54
+ type: typeSchemas.request?.name ? `Partial<RequestConfig<${typeSchemas.request?.name}>>` : 'Partial<RequestConfig>',
55
+ default: '{}',
56
+ },
57
+ })
58
+ }
59
+
60
+ export function InfiniteQueryOptions({
61
+ name,
62
+ clientName,
63
+ initialPageParam,
64
+ cursorParam,
65
+ typeSchemas,
66
+ dataReturnType,
67
+ pathParamsType,
68
+ queryParam,
69
+ queryKeyName,
70
+ }: Props): ReactNode {
71
+ const params = getParams({ pathParamsType, typeSchemas })
72
+ const clientParams = Client.getParams({
73
+ typeSchemas,
74
+ pathParamsType,
75
+ })
76
+ const queryKeyParams = QueryKey.getParams({
77
+ pathParamsType,
78
+ typeSchemas,
79
+ })
80
+
81
+ const queryOptions = [
82
+ `initialPageParam: ${typeof initialPageParam === 'string' ? JSON.stringify(initialPageParam) : initialPageParam}`,
83
+ cursorParam ? `getNextPageParam: (lastPage) => lastPage['${cursorParam}']` : undefined,
84
+ cursorParam ? `getPreviousPageParam: (firstPage) => firstPage['${cursorParam}']` : undefined,
85
+ !cursorParam && dataReturnType === 'full'
86
+ ? 'getNextPageParam: (lastPage, _allPages, lastPageParam) => Array.isArray(lastPage.data) && lastPage.data.length === 0 ? undefined : lastPageParam + 1'
87
+ : undefined,
88
+ !cursorParam && dataReturnType === 'data'
89
+ ? 'getNextPageParam: (lastPage, _allPages, lastPageParam) => Array.isArray(lastPage) && lastPage.length === 0 ? undefined : lastPageParam + 1'
90
+ : undefined,
91
+ !cursorParam ? 'getPreviousPageParam: (_firstPage, _allPages, firstPageParam) => firstPageParam <= 1 ? undefined : firstPageParam - 1' : undefined,
92
+ ].filter(Boolean)
93
+
94
+ const infiniteOverrideParams =
95
+ queryParam && typeSchemas.queryParams?.name
96
+ ? `
97
+ if(params) {
98
+ params['${queryParam}'] = pageParam as unknown as ${typeSchemas.queryParams?.name}['${queryParam}']
99
+ }`
100
+ : ''
101
+
102
+ const enabled = Object.entries(queryKeyParams.flatParams)
103
+ .map(([key, item]) => (item && !item.optional ? key : undefined))
104
+ .filter(Boolean)
105
+ .join('&& ')
106
+
107
+ const enabledText = enabled ? `enabled: !!(${enabled})` : ''
108
+
109
+ return (
110
+ <File.Source name={name} isExportable isIndexable>
111
+ <Function name={name} export params={params.toConstructor()}>
112
+ {`
113
+ const queryKey = ${queryKeyName}(${queryKeyParams.toCall()})
114
+ return infiniteQueryOptions({
115
+ ${enabledText}
116
+ queryKey,
117
+ queryFn: async ({ signal, pageParam }) => {
118
+ config.signal = signal
119
+ ${infiniteOverrideParams}
120
+ return ${clientName}(${clientParams.toCall()})
121
+ },
122
+ ${queryOptions.join('\n')}
123
+ })
124
+ `}
125
+ </Function>
126
+ </File.Source>
127
+ )
128
+ }
129
+
130
+ InfiniteQueryOptions.getParams = getParams
@@ -1,341 +1,157 @@
1
- import transformers from '@kubb/core/transformers'
2
- import { FunctionParams, URLPath } from '@kubb/core/utils'
3
- import { useOperation, useOperationManager } from '@kubb/plugin-oas/hooks'
4
- import { getASTParams, getComments } from '@kubb/plugin-oas/utils'
5
- import { File, Function, useApp } from '@kubb/react'
6
- import { pluginTsName } from '@kubb/plugin-ts'
7
-
8
- import { SchemaType } from './SchemaType.tsx'
9
-
10
- import { isRequired } from '@kubb/oas'
11
- import type { HttpMethod } from '@kubb/oas'
12
- import type { ComponentProps, ComponentType, ReactNode } from 'react'
13
- import type { FileMeta, PluginReactQuery } from '../types.ts'
14
-
15
- type TemplateProps = {
1
+ import { File, Function, FunctionParams } from '@kubb/react'
2
+
3
+ import { type Operation, isOptional } from '@kubb/oas'
4
+ import { Client } from '@kubb/plugin-client/components'
5
+ import type { OperationSchemas } from '@kubb/plugin-oas'
6
+ import { getComments, getPathParams } from '@kubb/plugin-oas/utils'
7
+ import type { Params } from '@kubb/react/types'
8
+ import type { ReactNode } from 'react'
9
+ import type { PluginReactQuery } from '../types.ts'
10
+ import { MutationKey } from './MutationKey.tsx'
11
+
12
+ type Props = {
16
13
  /**
17
14
  * Name of the function
18
15
  */
19
16
  name: string
20
- /**
21
- * Parameters/options/props that need to be used
22
- */
23
- params: string
24
- mutateParams: string
25
- /**
26
- * Options for JSdocs
27
- */
28
- JSDoc?: {
29
- comments: string[]
30
- }
31
- hook: {
32
- name: string
33
- generics?: string
34
- children?: string
35
- }
36
- client: {
37
- generics: string
38
- method: HttpMethod
39
- path: URLPath
40
- withQueryParams: boolean
41
- withPathParams: boolean
42
- withData: boolean
43
- withHeaders: boolean
44
- contentType: string
45
- }
46
- dataReturnType: NonNullable<PluginReactQuery['options']['dataReturnType']>
17
+ typeName: string
18
+ clientName: string
19
+ mutationKeyName: string
20
+ typeSchemas: OperationSchemas
21
+ operation: Operation
22
+ dataReturnType: PluginReactQuery['resolvedOptions']['client']['dataReturnType']
23
+ pathParamsType: PluginReactQuery['resolvedOptions']['pathParamsType']
47
24
  }
48
25
 
49
- function Template({ name, params, mutateParams, JSDoc, client, hook, dataReturnType }: TemplateProps): ReactNode {
50
- const isFormData = client.contentType === 'multipart/form-data'
51
- const headers = [
52
- client.contentType !== 'application/json' ? `'Content-Type': '${client.contentType}'` : undefined,
53
- client.withHeaders ? '...headers' : undefined,
54
- ]
55
- .filter(Boolean)
56
- .join(', ')
57
-
58
- const clientOptions = [
59
- `method: "${client.method}"`,
60
- `url: ${client.path.template}`,
61
- client.withQueryParams ? 'params' : undefined,
62
- client.withData && !isFormData ? 'data' : undefined,
63
- client.withData && isFormData ? 'data: formData' : undefined,
64
- headers.length ? `headers: { ${headers}, ...clientOptions.headers }` : undefined,
65
- '...clientOptions',
66
- ].filter(Boolean)
67
-
68
- const resolvedClientOptions = `${transformers.createIndent(4)}${clientOptions.join(`,\n${transformers.createIndent(4)}`)}`
69
-
70
- const formData = isFormData
71
- ? `
72
- const formData = new FormData()
73
- if(data) {
74
- Object.keys(data).forEach((key) => {
75
- const value = data[key];
76
- if (typeof key === "string" && (typeof value === "string" || value instanceof Blob)) {
77
- formData.append(key, value);
78
- }
79
- })
80
- }
81
- `
82
- : undefined
83
-
84
- return (
85
- <File.Source name={name} isExportable isIndexable>
86
- <Function export name={name} params={params} JSDoc={JSDoc}>
87
- {`
88
- const { mutation: mutationOptions, client: clientOptions = {} } = options ?? {}
89
-
90
- return ${hook.name}({
91
- mutationFn: async(${mutateParams}) => {
92
- ${hook.children || ''}
93
- ${formData || ''}
94
- const res = await client<${client.generics}>({
95
- ${resolvedClientOptions}
96
- })
97
-
98
- return ${dataReturnType === 'data' ? 'res.data' : 'res'}
99
- },
100
- ...mutationOptions
101
- })`}
102
- </Function>
103
- </File.Source>
104
- )
26
+ type GetParamsProps = {
27
+ pathParamsType: PluginReactQuery['resolvedOptions']['pathParamsType']
28
+ dataReturnType: PluginReactQuery['resolvedOptions']['client']['dataReturnType']
29
+ typeSchemas: OperationSchemas
105
30
  }
106
31
 
107
- type RootTemplateProps = {
108
- children?: React.ReactNode
32
+ function getParams({ dataReturnType, typeSchemas }: GetParamsProps) {
33
+ const TData = dataReturnType === 'data' ? typeSchemas.response.name : `ResponseConfig<${typeSchemas.response.name}>`
34
+ const mutationParams = FunctionParams.factory({
35
+ ...getPathParams(typeSchemas.pathParams, { typed: true }),
36
+ data: typeSchemas.request?.name
37
+ ? {
38
+ type: typeSchemas.request?.name,
39
+ optional: isOptional(typeSchemas.request?.schema),
40
+ }
41
+ : undefined,
42
+ params: typeSchemas.queryParams?.name
43
+ ? {
44
+ type: typeSchemas.queryParams?.name,
45
+ optional: isOptional(typeSchemas.queryParams?.schema),
46
+ }
47
+ : undefined,
48
+ headers: typeSchemas.headerParams?.name
49
+ ? {
50
+ type: typeSchemas.headerParams?.name,
51
+ optional: isOptional(typeSchemas.headerParams?.schema),
52
+ }
53
+ : undefined,
54
+ })
55
+ const TRequest = mutationParams.toConstructor({ valueAsType: true })
56
+ const generics = [TData, typeSchemas.errors?.map((item) => item.name).join(' | ') || 'Error', `{${TRequest}}`].join(', ')
57
+
58
+ return FunctionParams.factory({
59
+ options: {
60
+ type: `
61
+ {
62
+ mutation?: UseMutationOptions<${generics}>,
63
+ client?: ${typeSchemas.request?.name ? `Partial<RequestConfig<${typeSchemas.request?.name}>>` : 'Partial<RequestConfig>'},
109
64
  }
110
-
111
- function RootTemplate({ children }: RootTemplateProps) {
112
- const {
113
- plugin: {
114
- options: {
115
- client: { importPath },
116
- mutate,
117
- },
65
+ `,
66
+ default: '{}',
118
67
  },
119
- } = useApp<PluginReactQuery>()
120
-
121
- const { getSchemas, getFile } = useOperationManager()
122
- const operation = useOperation()
123
-
124
- const schemas = getSchemas(operation, { pluginKey: [pluginTsName], type: 'type' })
125
- const file = getFile(operation)
126
- const fileType = getFile(operation, { pluginKey: [pluginTsName] })
127
-
128
- return (
129
- <File<FileMeta> baseName={file.baseName} path={file.path} meta={file.meta}>
130
- <File.Import name={'client'} path={importPath} />
131
- <File.Import name={['ResponseConfig']} path={importPath} isTypeOnly />
132
- <File.Import
133
- name={[
134
- schemas.request?.name,
135
- schemas.response.name,
136
- schemas.pathParams?.name,
137
- schemas.queryParams?.name,
138
- schemas.headerParams?.name,
139
- ...(schemas.errors?.map((error) => error.name) || []),
140
- ].filter(Boolean)}
141
- root={file.path}
142
- path={fileType.path}
143
- isTypeOnly
144
- />
145
- <File.Import
146
- name={['UseMutationOptions', 'UseMutationResult']}
147
- path={typeof mutate !== 'boolean' && mutate.importPath ? mutate.importPath : '@tanstack/react-query'}
148
- isTypeOnly
149
- />
150
- <File.Import name={['useMutation']} path={typeof mutate !== 'boolean' && mutate.importPath ? mutate.importPath : '@tanstack/react-query'} />
151
- {children}
152
- </File>
153
- )
68
+ })
154
69
  }
155
70
 
156
- const defaultTemplates = { default: Template, root: RootTemplate } as const
157
-
158
- type Templates = Partial<typeof defaultTemplates>
159
-
160
- type MutationProps = {
161
- /**
162
- * This will make it possible to override the default behaviour.
163
- */
164
- Template?: ComponentType<ComponentProps<typeof Template>>
165
- }
166
-
167
- export function Mutation({ Template = defaultTemplates.default }: MutationProps): ReactNode {
168
- // TODO do checks on pathParamsType
169
-
170
- const {
171
- plugin: {
172
- options: { dataReturnType, mutate },
71
+ export function Mutation({ name, clientName, pathParamsType, dataReturnType, typeSchemas, operation, mutationKeyName }: Props): ReactNode {
72
+ const mutationKeyParams = MutationKey.getParams({
73
+ pathParamsType,
74
+ typeSchemas,
75
+ })
76
+
77
+ const params = getParams({
78
+ pathParamsType,
79
+ dataReturnType,
80
+ typeSchemas,
81
+ })
82
+
83
+ const clientParams = Client.getParams({
84
+ typeSchemas,
85
+ pathParamsType,
86
+ })
87
+
88
+ const mutationParams = FunctionParams.factory({
89
+ ...getPathParams(typeSchemas.pathParams, { typed: true }),
90
+ data: typeSchemas.request?.name
91
+ ? {
92
+ type: typeSchemas.request?.name,
93
+ optional: isOptional(typeSchemas.request?.schema),
94
+ }
95
+ : undefined,
96
+ params: typeSchemas.queryParams?.name
97
+ ? {
98
+ type: typeSchemas.queryParams?.name,
99
+ optional: isOptional(typeSchemas.queryParams?.schema),
100
+ }
101
+ : undefined,
102
+ headers: typeSchemas.headerParams?.name
103
+ ? {
104
+ type: typeSchemas.headerParams?.name,
105
+ optional: isOptional(typeSchemas.headerParams?.schema),
106
+ }
107
+ : undefined,
108
+ })
109
+
110
+ const dataParams = FunctionParams.factory({
111
+ data: {
112
+ // No use of pathParams because useMutation can only take one argument in object form,
113
+ // see https://tanstack.com/query/latest/docs/framework/react/reference/useMutation#usemutation
114
+ mode: 'object',
115
+ children: Object.entries(mutationParams.params).reduce((acc, [key, value]) => {
116
+ if (value) {
117
+ acc[key] = {
118
+ ...value,
119
+ type: undefined,
120
+ }
121
+ }
122
+
123
+ return acc
124
+ }, {} as Params),
173
125
  },
174
- } = useApp<PluginReactQuery>()
175
-
176
- const operation = useOperation()
177
- const { getSchemas, getName } = useOperationManager()
178
-
179
- const name = getName(operation, { type: 'function' })
180
- const schemas = getSchemas(operation, { pluginKey: [pluginTsName], type: 'type' })
181
- const contentType = operation.getContentType()
126
+ })
182
127
 
183
- const params = new FunctionParams()
184
- const mutateParams = new FunctionParams()
185
- const factoryName = getName(operation, { type: 'type' })
186
-
187
- const requestType =
188
- mutate && mutate.variablesType === 'mutate'
189
- ? FunctionParams.toObject([
190
- ...getASTParams(schemas.pathParams, { typed: true }),
191
- {
192
- name: 'params',
193
- type: `${factoryName}['queryParams']`,
194
- enabled: !!schemas.queryParams?.name,
195
- required: isRequired(schemas.queryParams?.schema),
196
- },
197
- {
198
- name: 'headers',
199
- type: `${factoryName}['headerParams']`,
200
- enabled: !!schemas.headerParams?.name,
201
- required: isRequired(schemas.headerParams?.schema),
202
- },
203
- {
204
- name: 'data',
205
- type: `${factoryName}['request']`,
206
- enabled: !!schemas.request?.name,
207
- required: isRequired(schemas.request?.schema),
208
- },
209
- ])?.type
210
- : schemas.request?.name
211
- ? `${factoryName}['request']`
212
- : 'never'
213
-
214
- const client = {
215
- method: operation.method,
216
- path: new URLPath(operation.path),
217
- generics: [`${factoryName}["data"]`, `${factoryName}["error"]`, requestType ? `${factoryName}["request"]` : 'void'].join(', '),
218
- withQueryParams: !!schemas.queryParams?.name,
219
- withData: !!schemas.request?.name,
220
- withPathParams: !!schemas.pathParams?.name,
221
- withHeaders: !!schemas.headerParams?.name,
222
- contentType,
223
- }
224
- const hook = {
225
- name: 'useMutation',
226
- generics: [`${factoryName}['response']`, `${factoryName}["error"]`, requestType ? `${requestType}` : 'void'].join(', '),
227
- }
228
-
229
- const resultGenerics = [
230
- `${factoryName}["response"]`,
231
- `${factoryName}["error"]`,
232
- mutate && mutate?.variablesType === 'mutate' ? requestType : `${factoryName}["request"]`,
233
- ]
234
-
235
- if (mutate && mutate?.variablesType === 'mutate') {
236
- params.add([
237
- {
238
- name: 'options',
239
- type: `{
240
- mutation?: UseMutationOptions<${resultGenerics.join(', ')}>,
241
- client?: ${factoryName}['client']['parameters']
242
- }`,
243
- default: '{}',
244
- },
245
- ])
246
-
247
- mutateParams.add([
248
- [
249
- ...getASTParams(schemas.pathParams, { typed: false }),
250
- {
251
- name: 'params',
252
- enabled: client.withQueryParams,
253
- required: isRequired(schemas.queryParams?.schema),
254
- },
255
- {
256
- name: 'headers',
257
- enabled: client.withHeaders,
258
- required: isRequired(schemas.headerParams?.schema),
259
- },
260
- {
261
- name: 'data',
262
- enabled: !!schemas.request?.name,
263
- required: isRequired(schemas.request?.schema),
264
- },
265
- ],
266
- ])
267
- } else {
268
- params.add([
269
- ...getASTParams(schemas.pathParams, { typed: true }),
270
- {
271
- name: 'params',
272
- type: `${factoryName}['queryParams']`,
273
- enabled: client.withQueryParams,
274
- required: isRequired(schemas.queryParams?.schema),
275
- },
276
- {
277
- name: 'headers',
278
- type: `${factoryName}['headerParams']`,
279
- enabled: client.withHeaders,
280
- required: isRequired(schemas.headerParams?.schema),
281
- },
282
- {
283
- name: 'options',
284
- type: `{
285
- mutation?: UseMutationOptions<${resultGenerics.join(', ')}>,
286
- client?: ${factoryName}['client']['parameters']
287
- }`,
288
- default: '{}',
289
- },
290
- ])
291
-
292
- mutateParams.add([
293
- {
294
- name: 'data',
295
- enabled: !!schemas.request?.name,
296
- required: isRequired(schemas.request?.schema),
297
- },
298
- ])
299
- }
300
-
301
- if (!mutate) {
302
- return null
303
- }
128
+ const TRequest = mutationParams.toConstructor({ valueAsType: true })
129
+ const TData = dataReturnType === 'data' ? typeSchemas.response.name : `ResponseConfig<${typeSchemas.response.name}>`
130
+ const generics = [TData, typeSchemas.errors?.map((item) => item.name).join(' | ') || 'Error', `{${TRequest}}`].join(', ')
304
131
 
305
132
  return (
306
- <>
307
- <Template
133
+ <File.Source name={name} isExportable isIndexable>
134
+ <Function
308
135
  name={name}
309
- JSDoc={{ comments: getComments(operation) }}
310
- client={client}
311
- hook={hook}
312
- params={params.toString()}
313
- mutateParams={mutateParams.toString()}
314
- dataReturnType={dataReturnType}
315
- />
316
- </>
317
- )
318
- }
319
-
320
- type FileProps = {
321
- /**
322
- * This will make it possible to override the default behaviour.
323
- */
324
- templates?: Templates
325
- }
326
-
327
- Mutation.File = function ({ ...props }: FileProps): ReactNode {
328
- const templates = { ...defaultTemplates, ...props.templates }
329
-
330
- const Template = templates.default
331
- const RootTemplate = templates.root
136
+ export
137
+ params={params.toConstructor()}
138
+ JSDoc={{
139
+ comments: getComments(operation),
140
+ }}
141
+ >
142
+ {`
143
+ const { mutation: mutationOptions, client: config = {} } = options ?? {}
144
+ const mutationKey = mutationOptions?.mutationKey ?? ${mutationKeyName}(${mutationKeyParams.toCall()})
332
145
 
333
- return (
334
- <RootTemplate>
335
- <SchemaType />
336
- <Mutation Template={Template} />
337
- </RootTemplate>
146
+ return useMutation<${generics}>({
147
+ mutationFn: async(${dataParams.toConstructor()}) => {
148
+ return ${clientName}(${clientParams.toCall()})
149
+ },
150
+ mutationKey,
151
+ ...mutationOptions
152
+ })
153
+ `}
154
+ </Function>
155
+ </File.Source>
338
156
  )
339
157
  }
340
-
341
- Mutation.templates = defaultTemplates
@@ -0,0 +1,48 @@
1
+ import { URLPath } from '@kubb/core/utils'
2
+ import { File, Function, FunctionParams, Type } from '@kubb/react'
3
+
4
+ import type { Operation } from '@kubb/oas'
5
+ import type { OperationSchemas } from '@kubb/plugin-oas'
6
+ import type { ReactNode } from 'react'
7
+ import type { PluginReactQuery } from '../types'
8
+
9
+ type Props = {
10
+ name: string
11
+ typeName: string
12
+ typeSchemas: OperationSchemas
13
+ operation: Operation
14
+ pathParamsType: PluginReactQuery['resolvedOptions']['pathParamsType']
15
+ keysFn: ((keys: unknown[]) => unknown[]) | undefined
16
+ }
17
+
18
+ type GetParamsProps = {
19
+ pathParamsType: PluginReactQuery['resolvedOptions']['pathParamsType']
20
+ typeSchemas: OperationSchemas
21
+ }
22
+
23
+ function getParams({}: GetParamsProps) {
24
+ return FunctionParams.factory({})
25
+ }
26
+
27
+ export function MutationKey({ name, typeSchemas, pathParamsType, operation, typeName, keysFn = (name) => name }: Props): ReactNode {
28
+ const path = new URLPath(operation.path)
29
+ const params = getParams({ pathParamsType, typeSchemas })
30
+ const keys = [JSON.stringify({ url: path.path })].filter(Boolean)
31
+
32
+ return (
33
+ <>
34
+ <File.Source name={name} isExportable isIndexable>
35
+ <Function.Arrow name={name} export params={params.toConstructor()} singleLine>
36
+ {`[${keysFn(keys).join(', ')}] as const`}
37
+ </Function.Arrow>
38
+ </File.Source>
39
+ <File.Source name={typeName} isExportable isIndexable isTypeOnly>
40
+ <Type name={typeName} export>
41
+ {`ReturnType<typeof ${name}>`}
42
+ </Type>
43
+ </File.Source>
44
+ </>
45
+ )
46
+ }
47
+
48
+ MutationKey.getParams = getParams