@kubb/plugin-react-query 3.0.0-alpha.0

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 (45) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +114 -0
  3. package/dist/chunk-5IL6M74X.js +1504 -0
  4. package/dist/chunk-5IL6M74X.js.map +1 -0
  5. package/dist/chunk-JFX7DCS7.cjs +1504 -0
  6. package/dist/chunk-JFX7DCS7.cjs.map +1 -0
  7. package/dist/components.cjs +15 -0
  8. package/dist/components.cjs.map +1 -0
  9. package/dist/components.d.cts +8 -0
  10. package/dist/components.d.ts +8 -0
  11. package/dist/components.js +15 -0
  12. package/dist/components.js.map +1 -0
  13. package/dist/index-yXskx3Td.d.cts +584 -0
  14. package/dist/index-yXskx3Td.d.ts +584 -0
  15. package/dist/index.cjs +223 -0
  16. package/dist/index.cjs.map +1 -0
  17. package/dist/index.d.cts +13 -0
  18. package/dist/index.d.ts +13 -0
  19. package/dist/index.js +223 -0
  20. package/dist/index.js.map +1 -0
  21. package/package.json +97 -0
  22. package/src/OperationGenerator.tsx +86 -0
  23. package/src/__snapshots__/mutateAsQuery/updatePetWithForm.ts +64 -0
  24. package/src/__snapshots__/pathParamsTypeInline/getPetById.ts +57 -0
  25. package/src/__snapshots__/pathParamsTypeObject/getPetById.ts +63 -0
  26. package/src/__snapshots__/queryOptions/getPetById.ts +37 -0
  27. package/src/__snapshots__/queryWithoutQueryOptions/getPetById.ts +47 -0
  28. package/src/__snapshots__/upload/UploadFile.ts +67 -0
  29. package/src/__snapshots__/uploadMutation/UploadFile.ts +44 -0
  30. package/src/__snapshots__/variablesTypeMutate/deletePet.ts +21 -0
  31. package/src/components/Mutation.tsx +341 -0
  32. package/src/components/Operations.tsx +74 -0
  33. package/src/components/Query.tsx +627 -0
  34. package/src/components/QueryImports.tsx +167 -0
  35. package/src/components/QueryKey.tsx +200 -0
  36. package/src/components/QueryOptions.tsx +487 -0
  37. package/src/components/SchemaType.tsx +55 -0
  38. package/src/components/__snapshots__/gen/showPetById.ts +57 -0
  39. package/src/components/__snapshots__/gen/useCreatePets.ts +46 -0
  40. package/src/components/__snapshots__/gen/useCreatePetsMutate.ts +47 -0
  41. package/src/components/index.ts +5 -0
  42. package/src/index.ts +2 -0
  43. package/src/plugin.ts +183 -0
  44. package/src/types.ts +240 -0
  45. package/src/utils.ts +96 -0
@@ -0,0 +1,341 @@
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, Parser, 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 = {
16
+ /**
17
+ * Name of the function
18
+ */
19
+ 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']>
47
+ }
48
+
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
+ <Function export name={name} params={params} JSDoc={JSDoc}>
86
+ {`
87
+ const { mutation: mutationOptions, client: clientOptions = {} } = options ?? {}
88
+
89
+ return ${hook.name}({
90
+ mutationFn: async(${mutateParams}) => {
91
+ ${hook.children || ''}
92
+ ${formData || ''}
93
+ const res = await client<${client.generics}>({
94
+ ${resolvedClientOptions}
95
+ })
96
+
97
+ return ${dataReturnType === 'data' ? 'res.data' : 'res'}
98
+ },
99
+ ...mutationOptions
100
+ })`}
101
+ </Function>
102
+ )
103
+ }
104
+
105
+ type RootTemplateProps = {
106
+ children?: React.ReactNode
107
+ }
108
+
109
+ function RootTemplate({ children }: RootTemplateProps) {
110
+ const {
111
+ plugin: {
112
+ options: {
113
+ client: { importPath },
114
+ mutate,
115
+ },
116
+ },
117
+ } = useApp<PluginReactQuery>()
118
+
119
+ const { getSchemas, getFile } = useOperationManager()
120
+ const operation = useOperation()
121
+
122
+ const schemas = getSchemas(operation, { pluginKey: [pluginTsName], type: 'type' })
123
+ const file = getFile(operation)
124
+ const fileType = getFile(operation, { pluginKey: [pluginTsName] })
125
+
126
+ return (
127
+ <Parser language="typescript">
128
+ <File<FileMeta> baseName={file.baseName} path={file.path} meta={file.meta}>
129
+ <File.Import name={'client'} path={importPath} />
130
+ <File.Import name={['ResponseConfig']} path={importPath} isTypeOnly />
131
+ <File.Import
132
+ name={[
133
+ schemas.request?.name,
134
+ schemas.response.name,
135
+ schemas.pathParams?.name,
136
+ schemas.queryParams?.name,
137
+ schemas.headerParams?.name,
138
+ ...(schemas.errors?.map((error) => error.name) || []),
139
+ ].filter(Boolean)}
140
+ root={file.path}
141
+ path={fileType.path}
142
+ isTypeOnly
143
+ />
144
+ <File.Import
145
+ name={['UseMutationOptions', 'UseMutationResult']}
146
+ path={typeof mutate !== 'boolean' && mutate.importPath ? mutate.importPath : '@tanstack/react-query'}
147
+ isTypeOnly
148
+ />
149
+ <File.Import name={['useMutation']} path={typeof mutate !== 'boolean' && mutate.importPath ? mutate.importPath : '@tanstack/react-query'} />
150
+ <File.Source>{children}</File.Source>
151
+ </File>
152
+ </Parser>
153
+ )
154
+ }
155
+
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 },
173
+ },
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()
182
+
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
+ }
304
+
305
+ return (
306
+ <>
307
+ <Template
308
+ 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
332
+
333
+ return (
334
+ <RootTemplate>
335
+ <SchemaType />
336
+ <Mutation Template={Template} />
337
+ </RootTemplate>
338
+ )
339
+ }
340
+
341
+ Mutation.templates = defaultTemplates
@@ -0,0 +1,74 @@
1
+ import { Parser, File, useApp } from '@kubb/react'
2
+
3
+ import type { KubbNode } from '@kubb/react'
4
+ import type { ComponentProps, ComponentType } from 'react'
5
+ import type { FileMeta, PluginReactQuery } from '../types.ts'
6
+
7
+ type TemplateProps = {}
8
+
9
+ function Template({}: TemplateProps): KubbNode {
10
+ return null
11
+ }
12
+
13
+ type RootTemplateProps = {
14
+ children?: React.ReactNode
15
+ }
16
+
17
+ function RootTemplate({ children }: RootTemplateProps) {
18
+ const {
19
+ pluginManager,
20
+ plugin: { key: pluginKey },
21
+ } = useApp<PluginReactQuery>()
22
+
23
+ const file = pluginManager.getFile({
24
+ name: 'operations',
25
+ mode: 'split',
26
+ extName: '.ts',
27
+ pluginKey,
28
+ })
29
+
30
+ return (
31
+ <Parser language="typescript">
32
+ <File<FileMeta> baseName={file.baseName} path={file.path} meta={file.meta}>
33
+ <File.Source>{children}</File.Source>
34
+ </File>
35
+ </Parser>
36
+ )
37
+ }
38
+
39
+ const defaultTemplates = { default: Template, root: RootTemplate } as const
40
+
41
+ type Templates = Partial<typeof defaultTemplates>
42
+
43
+ type Props = {
44
+ /**
45
+ * This will make it possible to override the default behaviour.
46
+ */
47
+ Template?: ComponentType<ComponentProps<typeof Template>>
48
+ }
49
+
50
+ export function Operations({ Template = defaultTemplates.default }: Props): KubbNode {
51
+ return <Template />
52
+ }
53
+
54
+ type FileProps = {
55
+ /**
56
+ * This will make it possible to override the default behaviour.
57
+ */
58
+ templates?: Templates
59
+ }
60
+
61
+ Operations.File = function (props: FileProps): KubbNode {
62
+ const templates = { ...defaultTemplates, ...props.templates }
63
+
64
+ const Template = templates.default
65
+ const RootTemplate = templates.root
66
+
67
+ return (
68
+ <RootTemplate>
69
+ <Operations Template={Template} />
70
+ </RootTemplate>
71
+ )
72
+ }
73
+
74
+ Operations.templates = defaultTemplates