@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.
- package/LICENSE +21 -0
- package/README.md +114 -0
- package/dist/chunk-5IL6M74X.js +1504 -0
- package/dist/chunk-5IL6M74X.js.map +1 -0
- package/dist/chunk-JFX7DCS7.cjs +1504 -0
- package/dist/chunk-JFX7DCS7.cjs.map +1 -0
- package/dist/components.cjs +15 -0
- package/dist/components.cjs.map +1 -0
- package/dist/components.d.cts +8 -0
- package/dist/components.d.ts +8 -0
- package/dist/components.js +15 -0
- package/dist/components.js.map +1 -0
- package/dist/index-yXskx3Td.d.cts +584 -0
- package/dist/index-yXskx3Td.d.ts +584 -0
- package/dist/index.cjs +223 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +13 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.js +223 -0
- package/dist/index.js.map +1 -0
- package/package.json +97 -0
- package/src/OperationGenerator.tsx +86 -0
- package/src/__snapshots__/mutateAsQuery/updatePetWithForm.ts +64 -0
- package/src/__snapshots__/pathParamsTypeInline/getPetById.ts +57 -0
- package/src/__snapshots__/pathParamsTypeObject/getPetById.ts +63 -0
- package/src/__snapshots__/queryOptions/getPetById.ts +37 -0
- package/src/__snapshots__/queryWithoutQueryOptions/getPetById.ts +47 -0
- package/src/__snapshots__/upload/UploadFile.ts +67 -0
- package/src/__snapshots__/uploadMutation/UploadFile.ts +44 -0
- package/src/__snapshots__/variablesTypeMutate/deletePet.ts +21 -0
- package/src/components/Mutation.tsx +341 -0
- package/src/components/Operations.tsx +74 -0
- package/src/components/Query.tsx +627 -0
- package/src/components/QueryImports.tsx +167 -0
- package/src/components/QueryKey.tsx +200 -0
- package/src/components/QueryOptions.tsx +487 -0
- package/src/components/SchemaType.tsx +55 -0
- package/src/components/__snapshots__/gen/showPetById.ts +57 -0
- package/src/components/__snapshots__/gen/useCreatePets.ts +46 -0
- package/src/components/__snapshots__/gen/useCreatePetsMutate.ts +47 -0
- package/src/components/index.ts +5 -0
- package/src/index.ts +2 -0
- package/src/plugin.ts +183 -0
- package/src/types.ts +240 -0
- 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
|