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