@kubb/plugin-react-query 3.0.0-alpha.14 → 3.0.0-alpha.16

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 (73) hide show
  1. package/dist/chunk-ESENIDWJ.js +608 -0
  2. package/dist/chunk-ESENIDWJ.js.map +1 -0
  3. package/dist/chunk-JQEH3UHY.cjs +618 -0
  4. package/dist/chunk-JQEH3UHY.cjs.map +1 -0
  5. package/dist/chunk-KRG2LWHM.cjs +606 -0
  6. package/dist/chunk-KRG2LWHM.cjs.map +1 -0
  7. package/dist/chunk-ME7ZFS5H.js +596 -0
  8. package/dist/chunk-ME7ZFS5H.js.map +1 -0
  9. package/dist/components.cjs +17 -5
  10. package/dist/components.d.cts +143 -5
  11. package/dist/components.d.ts +143 -5
  12. package/dist/components.js +1 -1
  13. package/dist/generators.cjs +25 -0
  14. package/dist/generators.cjs.map +1 -0
  15. package/dist/generators.d.cts +15 -0
  16. package/dist/generators.d.ts +15 -0
  17. package/dist/generators.js +4 -0
  18. package/dist/generators.js.map +1 -0
  19. package/dist/index.cjs +33 -76
  20. package/dist/index.cjs.map +1 -1
  21. package/dist/index.d.cts +2 -4
  22. package/dist/index.d.ts +2 -4
  23. package/dist/index.js +34 -77
  24. package/dist/index.js.map +1 -1
  25. package/dist/types-DJxL-JeY.d.cts +195 -0
  26. package/dist/types-DJxL-JeY.d.ts +195 -0
  27. package/package.json +23 -15
  28. package/src/components/InfiniteQuery.tsx +129 -0
  29. package/src/components/InfiniteQueryOptions.tsx +121 -0
  30. package/src/components/Mutation.tsx +112 -304
  31. package/src/components/Query.tsx +91 -593
  32. package/src/components/QueryKey.tsx +51 -182
  33. package/src/components/QueryOptions.tsx +64 -465
  34. package/src/components/SuspenseQuery.tsx +129 -0
  35. package/src/components/index.ts +3 -0
  36. package/src/generators/__snapshots__/clientDataReturnTypeFull.ts +64 -0
  37. package/src/generators/__snapshots__/clientGetImportPath.ts +64 -0
  38. package/src/generators/__snapshots__/clientPostImportPath.ts +59 -0
  39. package/src/generators/__snapshots__/findByTags.ts +64 -0
  40. package/src/generators/__snapshots__/findByTagsPathParamsObject.ts +64 -0
  41. package/src/generators/__snapshots__/findByTagsWithCustomQueryKey.ts +64 -0
  42. package/src/generators/__snapshots__/findByTagsWithZod.ts +64 -0
  43. package/src/generators/__snapshots__/findInfiniteByTags.ts +74 -0
  44. package/src/generators/__snapshots__/findInfiniteByTagsCursor.ts +74 -0
  45. package/src/generators/__snapshots__/getAsMutation.ts +31 -0
  46. package/src/generators/__snapshots__/postAsQuery.ts +77 -0
  47. package/src/generators/__snapshots__/updatePetById.ts +59 -0
  48. package/src/generators/__snapshots__/updatePetByIdPathParamsObject.ts +63 -0
  49. package/src/generators/index.ts +4 -0
  50. package/src/generators/infiniteQueryGenerator.tsx +124 -0
  51. package/src/generators/mutationGenerator.tsx +94 -0
  52. package/src/generators/queryGenerator.tsx +121 -0
  53. package/src/generators/suspenseQueryGenerator.tsx +120 -0
  54. package/src/plugin.ts +38 -49
  55. package/src/types.ts +35 -59
  56. package/dist/chunk-AGLJPONA.cjs +0 -1423
  57. package/dist/chunk-AGLJPONA.cjs.map +0 -1
  58. package/dist/chunk-I7X4HNDR.js +0 -1413
  59. package/dist/chunk-I7X4HNDR.js.map +0 -1
  60. package/dist/index-BzoLlZve.d.cts +0 -537
  61. package/dist/index-BzoLlZve.d.ts +0 -537
  62. package/src/OperationGenerator.tsx +0 -57
  63. package/src/__snapshots__/mutateAsQuery/updatePetWithForm.ts +0 -69
  64. package/src/__snapshots__/pathParamsTypeInline/getPetById.ts +0 -62
  65. package/src/__snapshots__/pathParamsTypeObject/getPetById.ts +0 -68
  66. package/src/__snapshots__/queryOptions/getPetById.ts +0 -41
  67. package/src/__snapshots__/queryWithoutQueryOptions/getPetById.ts +0 -51
  68. package/src/__snapshots__/variablesTypeMutate/deletePet.ts +0 -24
  69. package/src/components/QueryImports.tsx +0 -167
  70. package/src/components/SchemaType.tsx +0 -74
  71. package/src/components/__snapshots__/gen/showPetById.ts +0 -67
  72. package/src/components/__snapshots__/gen/useCreatePets.ts +0 -46
  73. package/src/components/__snapshots__/gen/useCreatePetsMutate.ts +0 -46
@@ -1,485 +1,84 @@
1
- import { PackageManager } from '@kubb/core'
2
- import transformers from '@kubb/core/transformers'
3
- import { FunctionParams, URLPath } from '@kubb/core/utils'
4
- import { useOperation, useOperationManager } from '@kubb/plugin-oas/hooks'
5
- import { getASTParams } from '@kubb/plugin-oas/utils'
6
- import { pluginZodName } from '@kubb/plugin-zod'
7
- import { File, Function, useApp } from '@kubb/react'
1
+ import { getPathParams } from '@kubb/plugin-oas/utils'
2
+ import { File, Function, FunctionParams } from '@kubb/react'
8
3
 
9
- import { isRequired } from '@kubb/oas'
10
- import type { HttpMethod } from '@kubb/oas'
11
- import { pluginTsName } from '@kubb/plugin-ts'
12
4
  import type { ReactNode } from 'react'
13
- import type { Infinite, PluginReactQuery, Suspense } from '../types.ts'
14
- import { reactQueryDepRegex } from '../utils.ts'
15
5
 
16
- type TemplateProps = {
17
- /**
18
- * Name of the function
19
- */
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 { PluginReactQuery } from '../types.ts'
10
+ import { QueryKey } from './QueryKey.tsx'
11
+
12
+ type Props = {
20
13
  name: string
21
- /**
22
- * Parameters/options/props that need to be used
23
- */
24
- params: string
25
- /**
26
- * Options for JSdocs
27
- */
28
- JSDoc?: {
29
- comments: string[]
30
- }
31
- hook: {
32
- queryKey: string
33
- children?: string
34
- }
35
- client: {
36
- generics: string
37
- method: HttpMethod
38
- path: URLPath
39
- withQueryParams: boolean
40
- withPathParams: boolean
41
- withData: boolean
42
- withHeaders: boolean
43
- contentType: string
44
- }
45
- infinite: Infinite | false
46
- dataReturnType: NonNullable<PluginReactQuery['options']['dataReturnType']>
47
- parser: string | undefined
14
+ clientName: string
15
+ queryKeyName: string
16
+ typeSchemas: OperationSchemas
17
+ pathParamsType: PluginReactQuery['resolvedOptions']['pathParamsType']
48
18
  }
49
19
 
50
- function Template({ name, params, JSDoc, hook, client, infinite, dataReturnType, parser }: TemplateProps): ReactNode {
51
- const isV5 = new PackageManager().isValidSync(reactQueryDepRegex, '>=5')
52
- const isFormData = client.contentType === 'multipart/form-data'
53
- const headers = [
54
- client.contentType !== 'application/json' ? `'Content-Type': '${client.contentType}'` : undefined,
55
- client.withHeaders ? '...headers' : undefined,
56
- ]
57
- .filter(Boolean)
58
- .join(', ')
59
-
60
- const clientOptions = [
61
- `method: "${client.method}"`,
62
- `url: ${client.path.template}`,
63
- client.withQueryParams && !infinite ? 'params' : undefined,
64
- client.withData && !isFormData ? 'data' : undefined,
65
- client.withData && isFormData ? 'data: formData' : undefined,
66
- headers.length ? `headers: { ${headers}, ...options.headers }` : undefined,
67
- '...options',
68
- client.withQueryParams && !!infinite
69
- ? `params: {
70
- ...params,
71
- ['${infinite.queryParam}']: pageParam,
72
- ...(options.params || {}),
73
- }`
74
- : undefined,
75
- ].filter(Boolean)
20
+ type GetParamsProps = {
21
+ pathParamsType: PluginReactQuery['resolvedOptions']['pathParamsType']
22
+ typeSchemas: OperationSchemas
23
+ }
76
24
 
77
- const queryOptions = [
78
- isV5 && !!infinite ? `initialPageParam: ${infinite.initialPageParam}` : undefined,
79
- isV5 && !!infinite && !!infinite.cursorParam ? `getNextPageParam: (lastPage) => lastPage['${infinite.cursorParam}']` : undefined,
80
- isV5 && !!infinite && !!infinite.cursorParam ? `getPreviousPageParam: (firstPage) => firstPage['${infinite.cursorParam}']` : undefined,
81
- isV5 && !!infinite && !infinite.cursorParam && dataReturnType === 'full'
82
- ? 'getNextPageParam: (lastPage, _allPages, lastPageParam) => Array.isArray(lastPage.data) && lastPage.data.length === 0 ? undefined : lastPageParam + 1'
25
+ function getParams({ pathParamsType, typeSchemas }: GetParamsProps) {
26
+ return FunctionParams.factory({
27
+ pathParams: {
28
+ mode: pathParamsType === 'object' ? 'object' : 'inlineSpread',
29
+ children: getPathParams(typeSchemas.pathParams, { typed: true }),
30
+ },
31
+ data: typeSchemas.request?.name
32
+ ? {
33
+ type: typeSchemas.request?.name,
34
+ optional: isOptional(typeSchemas.request?.schema),
35
+ }
83
36
  : undefined,
84
- isV5 && !!infinite && !infinite.cursorParam && dataReturnType === 'data'
85
- ? 'getNextPageParam: (lastPage, _allPages, lastPageParam) => Array.isArray(lastPage) && lastPage.length === 0 ? undefined : lastPageParam + 1'
37
+ params: typeSchemas.queryParams?.name
38
+ ? {
39
+ type: typeSchemas.queryParams?.name,
40
+ optional: isOptional(typeSchemas.queryParams?.schema),
41
+ }
86
42
  : undefined,
87
- isV5 && !!infinite && !infinite.cursorParam
88
- ? 'getPreviousPageParam: (_firstPage, _allPages, firstPageParam) => firstPageParam <= 1 ? undefined : firstPageParam - 1'
43
+ headers: typeSchemas.headerParams?.name
44
+ ? {
45
+ type: typeSchemas.headerParams?.name,
46
+ optional: isOptional(typeSchemas.headerParams?.schema),
47
+ }
89
48
  : undefined,
90
- ].filter(Boolean)
91
-
92
- const resolvedClientOptions = `${transformers.createIndent(4)}${clientOptions.join(`,\n${transformers.createIndent(4)}`)}`
93
- const resolvedQueryOptions = `${transformers.createIndent(4)}${queryOptions.join(`,\n${transformers.createIndent(4)}`)}`
94
-
95
- let returnRes = parser ? `return ${parser}(res.data)` : 'return res.data'
96
-
97
- if (dataReturnType === 'full') {
98
- returnRes = parser ? `return {...res, data: ${parser}(res.data)}` : 'return res'
99
- }
100
-
101
- const formData = isFormData
102
- ? `
103
- const formData = new FormData()
104
- if(data) {
105
- Object.keys(data).forEach((key) => {
106
- const value = data[key];
107
- if (typeof key === "string" && (typeof value === "string" || value instanceof Blob)) {
108
- formData.append(key, value);
109
- }
110
- })
111
- }
112
- `
113
- : undefined
114
-
115
- if (infinite) {
116
- if (isV5) {
117
- return (
118
- <File.Source name={name} isExportable isIndexable>
119
- <Function name={name} export params={params} JSDoc={JSDoc}>
120
- {`
121
- const queryKey = ${hook.queryKey}
122
-
123
- return infiniteQueryOptions({
124
- queryKey,
125
- queryFn: async ({ pageParam }) => {
126
- ${hook.children || ''}
127
- ${formData || ''}
128
- const res = await client<${client.generics}>({
129
- ${resolvedClientOptions}
130
- })
131
-
132
- ${returnRes}
133
- },
134
- ${resolvedQueryOptions}
135
- })
136
-
137
- `}
138
- </Function>
139
- </File.Source>
140
- )
141
- }
142
-
143
- return (
144
- <File.Source name={name} isExportable isIndexable>
145
- <Function name={name} export params={params} JSDoc={JSDoc}>
146
- {`
147
- const queryKey = ${hook.queryKey}
148
-
149
- return {
150
- queryKey,
151
- queryFn: async ({ pageParam }) => {
152
- ${hook.children || ''}
153
- ${formData || ''}
154
- const res = await client<${client.generics}>({
155
- ${resolvedClientOptions}
156
- })
157
-
158
- ${returnRes}
159
- },
160
- ${resolvedQueryOptions}
161
- }
162
-
163
- `}
164
- </Function>
165
- </File.Source>
166
- )
167
- }
168
-
169
- if (isV5) {
170
- return (
171
- <File.Source name={name} isExportable isIndexable>
172
- <Function name={name} export params={params} JSDoc={JSDoc}>
173
- {`
174
- const queryKey = ${hook.queryKey}
175
-
176
- return queryOptions({
177
- queryKey,
178
- queryFn: async () => {
179
- ${hook.children || ''}
180
- ${formData || ''}
181
- const res = await client<${client.generics}>({
182
- ${resolvedClientOptions}
183
- })
184
-
185
- ${returnRes}
186
- },
187
- ${resolvedQueryOptions}
188
- })
49
+ config: {
50
+ type: typeSchemas.request?.name ? `Partial<RequestConfig<${typeSchemas.request?.name}>>` : 'Partial<RequestConfig>',
51
+ default: '{}',
52
+ },
53
+ })
54
+ }
189
55
 
190
- `}
191
- </Function>
192
- </File.Source>
193
- )
194
- }
56
+ export function QueryOptions({ name, clientName, typeSchemas, pathParamsType, queryKeyName }: Props): ReactNode {
57
+ const params = getParams({ pathParamsType, typeSchemas })
58
+ const clientParams = Client.getParams({
59
+ typeSchemas,
60
+ pathParamsType,
61
+ })
62
+ const queryKeyParams = QueryKey.getParams({
63
+ pathParamsType,
64
+ typeSchemas,
65
+ })
195
66
 
196
67
  return (
197
68
  <File.Source name={name} isExportable isIndexable>
198
- <Function name={name} export params={params} JSDoc={JSDoc}>
69
+ <Function name={name} export params={params.toConstructor()}>
199
70
  {`
200
- const queryKey = ${hook.queryKey}
201
-
202
- return {
203
- queryKey,
204
- queryFn: async () => {
205
- ${hook.children || ''}
206
- ${formData || ''}
207
- const res = await client<${client.generics}>({
208
- ${resolvedClientOptions}
209
- })
210
-
211
- ${returnRes}
212
- },
213
- ${resolvedQueryOptions}
214
- }
215
-
216
- `}
71
+ const queryKey = ${queryKeyName}(${queryKeyParams.toCall()})
72
+ return queryOptions({
73
+ queryKey,
74
+ queryFn: async () => {
75
+ return ${clientName}(${clientParams.toCall()})
76
+ },
77
+ })
78
+ `}
217
79
  </Function>
218
80
  </File.Source>
219
81
  )
220
82
  }
221
83
 
222
- type FrameworkProps = TemplateProps & {
223
- context: {
224
- factory: {
225
- name: string
226
- }
227
- queryKey: string
228
- }
229
- }
230
-
231
- const defaultTemplates = {
232
- get react() {
233
- return function (props: FrameworkProps): ReactNode {
234
- return <Template {...props} />
235
- }
236
- },
237
- get solid() {
238
- return function (props: FrameworkProps): ReactNode {
239
- return <Template {...props} />
240
- }
241
- },
242
- get svelte() {
243
- return function (props: FrameworkProps): ReactNode {
244
- return <Template {...props} />
245
- }
246
- },
247
- get vue() {
248
- return function ({ client, context, ...rest }: FrameworkProps): ReactNode {
249
- const { factory, queryKey } = context
250
-
251
- const {
252
- plugin: {
253
- options: { pathParamsType },
254
- },
255
- } = useApp<PluginReactQuery>()
256
-
257
- const { getSchemas } = useOperationManager()
258
- const operation = useOperation()
259
-
260
- const schemas = getSchemas(operation, { pluginKey: [pluginTsName], type: 'type' })
261
- const params = new FunctionParams()
262
- const queryKeyParams = new FunctionParams()
263
-
264
- params.add([
265
- ...(pathParamsType === 'object'
266
- ? [
267
- getASTParams(schemas.pathParams, {
268
- typed: true,
269
- override: (item) => ({
270
- ...item,
271
- name: item.name ? `ref${transformers.pascalCase(item.name)}` : undefined,
272
- type: `MaybeRef<${item.type}>`,
273
- }),
274
- }),
275
- ]
276
- : getASTParams(schemas.pathParams, {
277
- typed: true,
278
- override: (item) => ({
279
- ...item,
280
- name: item.name ? `ref${transformers.pascalCase(item.name)}` : undefined,
281
- type: `MaybeRef<${item.type}>`,
282
- }),
283
- })),
284
- {
285
- name: 'refParams',
286
- type: `MaybeRef<${schemas.queryParams?.name}>`,
287
- enabled: client.withQueryParams,
288
- required: isRequired(schemas.queryParams?.schema),
289
- },
290
- {
291
- name: 'refHeaders',
292
- type: `MaybeRef<${schemas.headerParams?.name}>`,
293
- enabled: client.withHeaders,
294
- required: isRequired(schemas.headerParams?.schema),
295
- },
296
- {
297
- name: 'refData',
298
- type: `MaybeRef<${schemas.request?.name}>`,
299
- enabled: client.withData,
300
- required: isRequired(schemas.request?.schema),
301
- },
302
- {
303
- name: 'options',
304
- type: `${factory.name}['client']['parameters']`,
305
- default: '{}',
306
- },
307
- ])
308
-
309
- queryKeyParams.add([
310
- ...(pathParamsType === 'object'
311
- ? [
312
- getASTParams(schemas.pathParams, {
313
- override: (item) => ({
314
- ...item,
315
- name: item.name ? `ref${transformers.pascalCase(item.name)}` : undefined,
316
- }),
317
- }),
318
- ]
319
- : getASTParams(schemas.pathParams, {
320
- override: (item) => ({
321
- ...item,
322
- name: item.name ? `ref${transformers.pascalCase(item.name)}` : undefined,
323
- }),
324
- })),
325
- {
326
- name: 'refParams',
327
- enabled: client.withQueryParams,
328
- required: isRequired(schemas.queryParams?.schema),
329
- },
330
- {
331
- name: 'refData',
332
- enabled: client.withData,
333
- required: isRequired(schemas.request?.schema),
334
- },
335
- ])
336
-
337
- const unrefs = params.items
338
- .filter((item) => item.enabled)
339
- .map((item) => {
340
- return item.name ? `const ${transformers.camelCase(item.name.replace('ref', ''))} = unref(${item.name})` : undefined
341
- })
342
- .join('\n')
343
-
344
- const hook = {
345
- queryKey: `${queryKey}(${queryKeyParams.toString()})`,
346
- children: unrefs,
347
- }
348
-
349
- return <Template {...rest} params={params.toString()} hook={hook} client={client} />
350
- }
351
- },
352
- } as const
353
-
354
- type Props = {
355
- infinite: Infinite | false
356
- suspense: Suspense | false
357
- factory: {
358
- name: string
359
- }
360
- resultType: string
361
- /**
362
- * This will make it possible to override the default behaviour.
363
- */
364
- Template?: React.ComponentType<FrameworkProps>
365
- dataReturnType: NonNullable<PluginReactQuery['options']['dataReturnType']>
366
- }
367
-
368
- export function QueryOptions({ factory, infinite, suspense, resultType, dataReturnType, Template = defaultTemplates.react }: Props): ReactNode {
369
- const {
370
- pluginManager,
371
- plugin: {
372
- key: pluginKey,
373
- options: { parser, pathParamsType, queryOptions },
374
- },
375
- } = useApp<PluginReactQuery>()
376
-
377
- const { getSchemas } = useOperationManager()
378
- const operation = useOperation()
379
-
380
- const contentType = operation.getContentType()
381
- const schemas = getSchemas(operation, { pluginKey: [pluginTsName], type: 'type' })
382
- const zodSchemas = getSchemas(operation, { pluginKey: [pluginZodName], type: 'function' })
383
-
384
- const queryKey = pluginManager.resolveName({
385
- name: [factory.name, infinite ? 'Infinite' : undefined, suspense ? 'Suspense' : undefined, 'QueryKey'].filter(Boolean).join(''),
386
- pluginKey,
387
- })
388
- const queryOptionsName = pluginManager.resolveName({
389
- name: [factory.name, infinite ? 'Infinite' : undefined, suspense ? 'Suspense' : undefined, 'QueryOptions'].filter(Boolean).join(''),
390
- pluginKey,
391
- })
392
-
393
- const generics = new FunctionParams()
394
- const params = new FunctionParams()
395
- const queryKeyParams = new FunctionParams()
396
-
397
- const clientGenerics = [`${factory.name}['data']`, `${factory.name}['error']`]
398
- // suspense is having 4 generics instead of 5, TQueryData is not needed because data will always be defined
399
- const resultGenerics = suspense
400
- ? [`${factory.name}['response']`, `${factory.name}["error"]`, 'TData']
401
- : [`${factory.name}['response']`, `${factory.name}["error"]`, 'TData', 'TQueryData']
402
-
403
- const client = {
404
- withQueryParams: !!schemas.queryParams?.name,
405
- withData: !!schemas.request?.name,
406
- withPathParams: !!schemas.pathParams?.name,
407
- withHeaders: !!schemas.headerParams?.name,
408
- method: operation.method,
409
- path: new URLPath(operation.path),
410
- generics: clientGenerics.toString(),
411
- contentType,
412
- }
413
-
414
- generics.add([
415
- { type: 'TData', default: `${factory.name}["response"]` },
416
- suspense ? undefined : { type: 'TQueryData', default: `${factory.name}["response"]` },
417
- ])
418
-
419
- params.add([
420
- ...(pathParamsType === 'object' ? [getASTParams(schemas.pathParams, { typed: true })] : getASTParams(schemas.pathParams, { typed: true })),
421
- {
422
- name: 'params',
423
- type: `${factory.name}['queryParams']`,
424
- enabled: client.withQueryParams,
425
- required: isRequired(schemas.queryParams?.schema),
426
- },
427
- {
428
- name: 'headers',
429
- type: `${factory.name}['headerParams']`,
430
- enabled: client.withHeaders,
431
- required: isRequired(schemas.headerParams?.schema),
432
- },
433
- {
434
- name: 'data',
435
- type: `${factory.name}['request']`,
436
- enabled: client.withData,
437
- required: isRequired(schemas.request?.schema),
438
- },
439
- {
440
- name: 'options',
441
- type: `${factory.name}['client']['parameters']`,
442
- default: '{}',
443
- },
444
- ])
445
-
446
- queryKeyParams.add([
447
- ...(pathParamsType === 'object' ? [getASTParams(schemas.pathParams)] : getASTParams(schemas.pathParams)),
448
- {
449
- name: 'params',
450
- enabled: client.withQueryParams,
451
- required: isRequired(schemas.queryParams?.schema),
452
- },
453
- {
454
- name: 'data',
455
- enabled: client.withData,
456
- required: isRequired(schemas.request?.schema),
457
- },
458
- ])
459
-
460
- const hook = {
461
- queryKey: `${queryKey}(${queryKeyParams.toString()})`,
462
- }
463
-
464
- if (!queryOptions) {
465
- return null
466
- }
467
-
468
- return (
469
- <Template
470
- name={queryOptionsName}
471
- params={params.toString()}
472
- client={client}
473
- hook={hook}
474
- infinite={infinite}
475
- dataReturnType={dataReturnType}
476
- parser={parser === 'zod' ? `${zodSchemas.response.name}.parse` : undefined}
477
- context={{
478
- factory,
479
- queryKey,
480
- }}
481
- />
482
- )
483
- }
484
-
485
- QueryOptions.templates = defaultTemplates
84
+ QueryOptions.getParams = getParams
@@ -0,0 +1,129 @@
1
+ import { File, Function, FunctionParams } from '@kubb/react'
2
+
3
+ import { type Operation, isOptional } from '@kubb/oas'
4
+ import type { OperationSchemas } from '@kubb/plugin-oas'
5
+ import { getComments, getPathParams } from '@kubb/plugin-oas/utils'
6
+ import type { ReactNode } from 'react'
7
+ import type { PluginReactQuery } from '../types.ts'
8
+ import { QueryKey } from './QueryKey.tsx'
9
+ import { QueryOptions } from './QueryOptions.tsx'
10
+
11
+ type Props = {
12
+ /**
13
+ * Name of the function
14
+ */
15
+ name: string
16
+ queryOptionsName: string
17
+ queryKeyName: string
18
+ queryKeyTypeName: string
19
+ typeSchemas: OperationSchemas
20
+ operation: Operation
21
+ pathParamsType: PluginReactQuery['resolvedOptions']['pathParamsType']
22
+ dataReturnType: PluginReactQuery['resolvedOptions']['client']['dataReturnType']
23
+ }
24
+
25
+ type GetParamsProps = {
26
+ pathParamsType: PluginReactQuery['resolvedOptions']['pathParamsType']
27
+ dataReturnType: PluginReactQuery['resolvedOptions']['client']['dataReturnType']
28
+ typeSchemas: OperationSchemas
29
+ }
30
+
31
+ function getParams({ pathParamsType, dataReturnType, typeSchemas }: GetParamsProps) {
32
+ const TData = dataReturnType === 'data' ? typeSchemas.response.name : `ResponseConfig<${typeSchemas.response.name}>`
33
+
34
+ return FunctionParams.factory({
35
+ pathParams: {
36
+ mode: pathParamsType === 'object' ? 'object' : 'inlineSpread',
37
+ children: getPathParams(typeSchemas.pathParams, { typed: true }),
38
+ },
39
+ data: typeSchemas.request?.name
40
+ ? {
41
+ type: typeSchemas.request?.name,
42
+ optional: isOptional(typeSchemas.request?.schema),
43
+ }
44
+ : undefined,
45
+ params: typeSchemas.queryParams?.name
46
+ ? {
47
+ type: typeSchemas.queryParams?.name,
48
+ optional: isOptional(typeSchemas.queryParams?.schema),
49
+ }
50
+ : undefined,
51
+ headers: typeSchemas.headerParams?.name
52
+ ? {
53
+ type: typeSchemas.headerParams?.name,
54
+ optional: isOptional(typeSchemas.headerParams?.schema),
55
+ }
56
+ : undefined,
57
+ options: {
58
+ type: `
59
+ {
60
+ query?: Partial<UseSuspenseQueryOptions<${[TData, typeSchemas.errors?.map((item) => item.name).join(' | ') || 'unknown', 'TData', 'TQueryKey'].join(', ')}>>,
61
+ client?: ${typeSchemas.request?.name ? `Partial<RequestConfig<${typeSchemas.request?.name}>>` : 'Partial<RequestConfig>'}
62
+ }
63
+ `,
64
+ default: '{}',
65
+ },
66
+ })
67
+ }
68
+
69
+ export function SuspenseQuery({
70
+ name,
71
+ queryKeyTypeName,
72
+ queryOptionsName,
73
+ queryKeyName,
74
+ pathParamsType,
75
+ dataReturnType,
76
+ typeSchemas,
77
+ operation,
78
+ }: Props): ReactNode {
79
+ const TData = dataReturnType === 'data' ? typeSchemas.response.name : `ResponseConfig<${typeSchemas.response.name}>`
80
+ const returnType = `UseSuspenseQueryResult<${['TData', typeSchemas.errors?.map((item) => item.name).join(' | ') || 'unknown'].join(', ')}> & { queryKey: TQueryKey }`
81
+ const generics = [`TData = ${TData}`, `TQueryData = ${TData}`, `TQueryKey extends QueryKey = ${queryKeyTypeName}`]
82
+
83
+ const queryKeyParams = QueryKey.getParams({
84
+ pathParamsType,
85
+ typeSchemas,
86
+ })
87
+ const queryOptionsParams = QueryOptions.getParams({
88
+ pathParamsType,
89
+ typeSchemas,
90
+ })
91
+ const params = getParams({
92
+ pathParamsType,
93
+ dataReturnType,
94
+ typeSchemas,
95
+ })
96
+
97
+ const queryOptions = `${queryOptionsName}(${queryOptionsParams.toCall()}) as unknown as UseSuspenseQueryOptions`
98
+
99
+ return (
100
+ <File.Source name={name} isExportable isIndexable>
101
+ <Function
102
+ name={name}
103
+ export
104
+ generics={generics.join(', ')}
105
+ params={params.toConstructor()}
106
+ JSDoc={{
107
+ comments: getComments(operation),
108
+ }}
109
+ >
110
+ {`
111
+ const { query: queryOptions, client: config = {} } = options ?? {}
112
+ const queryKey = queryOptions?.queryKey ?? ${queryKeyName}(${queryKeyParams.toCall()})
113
+
114
+ const query = useSuspenseQuery({
115
+ ...${queryOptions},
116
+ queryKey,
117
+ ...queryOptions as unknown as Omit<UseSuspenseQueryOptions, "queryKey">
118
+ }) as ${returnType}
119
+
120
+ query.queryKey = queryKey as TQueryKey
121
+
122
+ return query
123
+ `}
124
+ </Function>
125
+ </File.Source>
126
+ )
127
+ }
128
+
129
+ SuspenseQuery.getParams = getParams
@@ -2,3 +2,6 @@ export { Mutation } from './Mutation.tsx'
2
2
  export { Query } from './Query.tsx'
3
3
  export { QueryKey } from './QueryKey.tsx'
4
4
  export { QueryOptions } from './QueryOptions.tsx'
5
+ export { InfiniteQueryOptions } from './InfiniteQueryOptions.tsx'
6
+ export { InfiniteQuery } from './InfiniteQuery.tsx'
7
+ export { SuspenseQuery } from './SuspenseQuery.tsx'