@kubb/plugin-react-query 5.0.0-alpha.9 → 5.0.0-beta.100

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 (47) hide show
  1. package/LICENSE +17 -10
  2. package/README.md +38 -93
  3. package/dist/index.cjs +2317 -149
  4. package/dist/index.cjs.map +1 -1
  5. package/dist/index.d.ts +494 -6
  6. package/dist/index.js +2283 -143
  7. package/dist/index.js.map +1 -1
  8. package/package.json +47 -75
  9. package/dist/components-BHQT9ZLc.cjs +0 -1634
  10. package/dist/components-BHQT9ZLc.cjs.map +0 -1
  11. package/dist/components-CpyHYGOw.js +0 -1520
  12. package/dist/components-CpyHYGOw.js.map +0 -1
  13. package/dist/components.cjs +0 -13
  14. package/dist/components.d.ts +0 -398
  15. package/dist/components.js +0 -2
  16. package/dist/generators-DP07m3rH.cjs +0 -1469
  17. package/dist/generators-DP07m3rH.cjs.map +0 -1
  18. package/dist/generators-DkQwKTc2.js +0 -1427
  19. package/dist/generators-DkQwKTc2.js.map +0 -1
  20. package/dist/generators.cjs +0 -9
  21. package/dist/generators.d.ts +0 -523
  22. package/dist/generators.js +0 -2
  23. package/dist/types-D5S7Ny9r.d.ts +0 -270
  24. package/src/components/InfiniteQuery.tsx +0 -220
  25. package/src/components/InfiniteQueryOptions.tsx +0 -289
  26. package/src/components/Mutation.tsx +0 -158
  27. package/src/components/MutationKey.tsx +0 -1
  28. package/src/components/MutationOptions.tsx +0 -122
  29. package/src/components/Query.tsx +0 -194
  30. package/src/components/QueryKey.tsx +0 -1
  31. package/src/components/QueryOptions.tsx +0 -181
  32. package/src/components/SuspenseInfiniteQuery.tsx +0 -220
  33. package/src/components/SuspenseInfiniteQueryOptions.tsx +0 -289
  34. package/src/components/SuspenseQuery.tsx +0 -204
  35. package/src/components/index.ts +0 -11
  36. package/src/generators/customHookOptionsFileGenerator.tsx +0 -98
  37. package/src/generators/hookOptionsGenerator.tsx +0 -196
  38. package/src/generators/index.ts +0 -7
  39. package/src/generators/infiniteQueryGenerator.tsx +0 -214
  40. package/src/generators/mutationGenerator.tsx +0 -195
  41. package/src/generators/queryGenerator.tsx +0 -194
  42. package/src/generators/suspenseInfiniteQueryGenerator.tsx +0 -202
  43. package/src/generators/suspenseQueryGenerator.tsx +0 -207
  44. package/src/index.ts +0 -2
  45. package/src/plugin.ts +0 -239
  46. package/src/types.ts +0 -205
  47. /package/dist/{chunk--u3MIqq1.js → rolldown-runtime-C0LytTxp.js} +0 -0
@@ -1,289 +0,0 @@
1
- import { getNestedAccessor } from '@internals/utils'
2
- import { isAllOptional, isOptional } from '@kubb/oas'
3
- import { Client } from '@kubb/plugin-client/components'
4
- import type { OperationSchemas } from '@kubb/plugin-oas'
5
- import { getPathParams } from '@kubb/plugin-oas/utils'
6
- import { File, Function, FunctionParams } from '@kubb/react-fabric'
7
- import type { FabricReactNode } from '@kubb/react-fabric/types'
8
- import type { Infinite, PluginReactQuery } from '../types.ts'
9
- import { QueryKey } from './QueryKey.tsx'
10
-
11
- type Props = {
12
- name: string
13
- clientName: string
14
- queryKeyName: string
15
- typeSchemas: OperationSchemas
16
- paramsCasing: PluginReactQuery['resolvedOptions']['paramsCasing']
17
- paramsType: PluginReactQuery['resolvedOptions']['paramsType']
18
- pathParamsType: PluginReactQuery['resolvedOptions']['pathParamsType']
19
- dataReturnType: PluginReactQuery['resolvedOptions']['client']['dataReturnType']
20
- initialPageParam: Infinite['initialPageParam']
21
- cursorParam: Infinite['cursorParam']
22
- nextParam: Infinite['nextParam']
23
- previousParam: Infinite['previousParam']
24
- queryParam: Infinite['queryParam']
25
- }
26
-
27
- type GetParamsProps = {
28
- paramsCasing: PluginReactQuery['resolvedOptions']['paramsCasing']
29
- paramsType: PluginReactQuery['resolvedOptions']['paramsType']
30
- pathParamsType: PluginReactQuery['resolvedOptions']['pathParamsType']
31
- typeSchemas: OperationSchemas
32
- }
33
-
34
- function getParams({ paramsType, paramsCasing, pathParamsType, typeSchemas }: GetParamsProps) {
35
- if (paramsType === 'object') {
36
- const pathParams = getPathParams(typeSchemas.pathParams, { typed: true, casing: paramsCasing })
37
-
38
- const children = {
39
- ...pathParams,
40
- data: typeSchemas.request?.name
41
- ? {
42
- type: typeSchemas.request?.name,
43
- optional: isOptional(typeSchemas.request?.schema),
44
- }
45
- : undefined,
46
- params: typeSchemas.queryParams?.name
47
- ? {
48
- type: typeSchemas.queryParams?.name,
49
- optional: isOptional(typeSchemas.queryParams?.schema),
50
- }
51
- : undefined,
52
- headers: typeSchemas.headerParams?.name
53
- ? {
54
- type: typeSchemas.headerParams?.name,
55
- optional: isOptional(typeSchemas.headerParams?.schema),
56
- }
57
- : undefined,
58
- }
59
-
60
- // Check if all children are optional or undefined
61
- const allChildrenAreOptional = Object.values(children).every((child) => !child || child.optional)
62
-
63
- return FunctionParams.factory({
64
- data: {
65
- mode: 'object',
66
- children,
67
- default: allChildrenAreOptional ? '{}' : undefined,
68
- },
69
- config: {
70
- type: typeSchemas.request?.name
71
- ? `Partial<RequestConfig<${typeSchemas.request?.name}>> & { client?: Client }`
72
- : 'Partial<RequestConfig> & { client?: Client }',
73
- default: '{}',
74
- },
75
- })
76
- }
77
-
78
- return FunctionParams.factory({
79
- pathParams: typeSchemas.pathParams?.name
80
- ? {
81
- mode: pathParamsType === 'object' ? 'object' : 'inlineSpread',
82
- children: getPathParams(typeSchemas.pathParams, {
83
- typed: true,
84
- casing: paramsCasing,
85
- }),
86
- default: isAllOptional(typeSchemas.pathParams?.schema) ? '{}' : undefined,
87
- }
88
- : undefined,
89
- data: typeSchemas.request?.name
90
- ? {
91
- type: typeSchemas.request?.name,
92
- optional: isOptional(typeSchemas.request?.schema),
93
- }
94
- : undefined,
95
- params: typeSchemas.queryParams?.name
96
- ? {
97
- type: typeSchemas.queryParams?.name,
98
- optional: isOptional(typeSchemas.queryParams?.schema),
99
- }
100
- : undefined,
101
- headers: typeSchemas.headerParams?.name
102
- ? {
103
- type: typeSchemas.headerParams?.name,
104
- optional: isOptional(typeSchemas.headerParams?.schema),
105
- }
106
- : undefined,
107
- config: {
108
- type: typeSchemas.request?.name
109
- ? `Partial<RequestConfig<${typeSchemas.request?.name}>> & { client?: Client }`
110
- : 'Partial<RequestConfig> & { client?: Client }',
111
- default: '{}',
112
- },
113
- })
114
- }
115
-
116
- export function SuspenseInfiniteQueryOptions({
117
- name,
118
- clientName,
119
- initialPageParam,
120
- cursorParam,
121
- nextParam,
122
- previousParam,
123
- typeSchemas,
124
- paramsCasing,
125
- paramsType,
126
- dataReturnType,
127
- pathParamsType,
128
- queryParam,
129
- queryKeyName,
130
- }: Props): FabricReactNode {
131
- const queryFnDataType = dataReturnType === 'data' ? typeSchemas.response.name : `ResponseConfig<${typeSchemas.response.name}>`
132
- const errorType = `ResponseErrorConfig<${typeSchemas.errors?.map((item) => item.name).join(' | ') || 'Error'}>`
133
- const isInitialPageParamDefined = initialPageParam !== undefined && initialPageParam !== null
134
- const fallbackPageParamType =
135
- typeof initialPageParam === 'number'
136
- ? 'number'
137
- : typeof initialPageParam === 'string'
138
- ? initialPageParam.includes(' as ')
139
- ? (() => {
140
- const parts = initialPageParam.split(' as ')
141
- return parts[parts.length - 1] ?? 'unknown'
142
- })()
143
- : 'string'
144
- : typeof initialPageParam === 'boolean'
145
- ? 'boolean'
146
- : 'unknown'
147
- const queryParamType = queryParam && typeSchemas.queryParams?.name ? `${typeSchemas.queryParams?.name}['${queryParam}']` : undefined
148
- const pageParamType = queryParamType ? (isInitialPageParamDefined ? `NonNullable<${queryParamType}>` : queryParamType) : fallbackPageParamType
149
-
150
- const params = getParams({
151
- paramsType,
152
- paramsCasing,
153
- pathParamsType,
154
- typeSchemas,
155
- })
156
- const clientParams = Client.getParams({
157
- paramsCasing,
158
- typeSchemas,
159
- paramsType,
160
- pathParamsType,
161
- isConfigurable: true,
162
- })
163
- const queryKeyParams = QueryKey.getParams({
164
- pathParamsType,
165
- typeSchemas,
166
- paramsCasing,
167
- })
168
-
169
- // Determine if we should use the new nextParam/previousParam or fall back to legacy cursorParam behavior
170
- const hasNewParams = nextParam !== undefined || previousParam !== undefined
171
-
172
- let getNextPageParamExpr: string | undefined
173
- let getPreviousPageParamExpr: string | undefined
174
-
175
- if (hasNewParams) {
176
- // Use the new nextParam and previousParam
177
- if (nextParam) {
178
- const accessor = getNestedAccessor(nextParam, 'lastPage')
179
- if (accessor) {
180
- getNextPageParamExpr = `getNextPageParam: (lastPage) => ${accessor}`
181
- }
182
- }
183
- if (previousParam) {
184
- const accessor = getNestedAccessor(previousParam, 'firstPage')
185
- if (accessor) {
186
- getPreviousPageParamExpr = `getPreviousPageParam: (firstPage) => ${accessor}`
187
- }
188
- }
189
- } else if (cursorParam) {
190
- // Legacy behavior: use cursorParam for both next and previous
191
- getNextPageParamExpr = `getNextPageParam: (lastPage) => lastPage['${cursorParam}']`
192
- getPreviousPageParamExpr = `getPreviousPageParam: (firstPage) => firstPage['${cursorParam}']`
193
- } else {
194
- // Fallback behavior: page-based pagination
195
- if (dataReturnType === 'full') {
196
- getNextPageParamExpr =
197
- 'getNextPageParam: (lastPage, _allPages, lastPageParam) => Array.isArray(lastPage.data) && lastPage.data.length === 0 ? undefined : lastPageParam + 1'
198
- } else {
199
- getNextPageParamExpr =
200
- 'getNextPageParam: (lastPage, _allPages, lastPageParam) => Array.isArray(lastPage) && lastPage.length === 0 ? undefined : lastPageParam + 1'
201
- }
202
- getPreviousPageParamExpr = 'getPreviousPageParam: (_firstPage, _allPages, firstPageParam) => firstPageParam <= 1 ? undefined : firstPageParam - 1'
203
- }
204
-
205
- const queryOptions = [
206
- `initialPageParam: ${typeof initialPageParam === 'string' ? JSON.stringify(initialPageParam) : initialPageParam}`,
207
- getNextPageParamExpr,
208
- getPreviousPageParamExpr,
209
- ].filter(Boolean)
210
-
211
- const infiniteOverrideParams =
212
- queryParam && typeSchemas.queryParams?.name
213
- ? `
214
- params = {
215
- ...(params ?? {}),
216
- ['${queryParam}']: pageParam as unknown as ${typeSchemas.queryParams?.name}['${queryParam}'],
217
- } as ${typeSchemas.queryParams?.name}`
218
- : ''
219
-
220
- // Only add enabled check for required (non-optional) parameters
221
- // Optional parameters with defaults should not prevent query execution
222
- const enabled = Object.entries(queryKeyParams.flatParams)
223
- .map(([key, item]) => {
224
- // Only include if the parameter exists and is NOT optional
225
- // This ensures we only check required parameters
226
- return item && !item.optional && !item.default ? key : undefined
227
- })
228
- .filter(Boolean)
229
- .join('&& ')
230
-
231
- const enabledText = enabled ? `enabled: !!(${enabled}),` : ''
232
-
233
- if (infiniteOverrideParams) {
234
- return (
235
- <File.Source name={name} isExportable isIndexable>
236
- <Function name={name} export params={params.toConstructor()}>
237
- {`
238
- const queryKey = ${queryKeyName}(${queryKeyParams.toCall()})
239
- return infiniteQueryOptions<${queryFnDataType}, ${errorType}, InfiniteData<${queryFnDataType}>, typeof queryKey, ${pageParamType}>({
240
- ${enabledText}
241
- queryKey,
242
- queryFn: async ({ signal, pageParam }) => {
243
- ${infiniteOverrideParams}
244
- return ${clientName}(${clientParams.toCall({
245
- transformName(name) {
246
- if (name === 'config') {
247
- return '{ ...config, signal: config.signal ?? signal }'
248
- }
249
-
250
- return name
251
- },
252
- })})
253
- },
254
- ${queryOptions.join(',\n')}
255
- })
256
- `}
257
- </Function>
258
- </File.Source>
259
- )
260
- }
261
-
262
- return (
263
- <File.Source name={name} isExportable isIndexable>
264
- <Function name={name} export params={params.toConstructor()}>
265
- {`
266
- const queryKey = ${queryKeyName}(${queryKeyParams.toCall()})
267
- return infiniteQueryOptions<${queryFnDataType}, ${errorType}, InfiniteData<${queryFnDataType}>, typeof queryKey, ${pageParamType}>({
268
- ${enabledText}
269
- queryKey,
270
- queryFn: async ({ signal }) => {
271
- return ${clientName}(${clientParams.toCall({
272
- transformName(name) {
273
- if (name === 'config') {
274
- return '{ ...config, signal: config.signal ?? signal }'
275
- }
276
-
277
- return name
278
- },
279
- })})
280
- },
281
- ${queryOptions.join(',\n')}
282
- })
283
- `}
284
- </Function>
285
- </File.Source>
286
- )
287
- }
288
-
289
- SuspenseInfiniteQueryOptions.getParams = getParams
@@ -1,204 +0,0 @@
1
- import { isAllOptional, isOptional, type Operation } from '@kubb/oas'
2
- import type { OperationSchemas } from '@kubb/plugin-oas'
3
- import { getComments, getPathParams } from '@kubb/plugin-oas/utils'
4
- import { File, Function, FunctionParams } from '@kubb/react-fabric'
5
- import type { FabricReactNode } from '@kubb/react-fabric/types'
6
- import type { PluginReactQuery } from '../types.ts'
7
- import { QueryKey } from './QueryKey.tsx'
8
- import { QueryOptions } from './QueryOptions.tsx'
9
-
10
- type Props = {
11
- /**
12
- * Name of the function
13
- */
14
- name: string
15
- queryOptionsName: string
16
- queryKeyName: string
17
- queryKeyTypeName: string
18
- typeSchemas: OperationSchemas
19
- operation: Operation
20
- paramsCasing: PluginReactQuery['resolvedOptions']['paramsCasing']
21
- paramsType: PluginReactQuery['resolvedOptions']['paramsType']
22
- pathParamsType: PluginReactQuery['resolvedOptions']['pathParamsType']
23
- dataReturnType: PluginReactQuery['resolvedOptions']['client']['dataReturnType']
24
- customOptions: PluginReactQuery['resolvedOptions']['customOptions']
25
- }
26
-
27
- type GetParamsProps = {
28
- paramsCasing: PluginReactQuery['resolvedOptions']['paramsCasing']
29
- paramsType: PluginReactQuery['resolvedOptions']['paramsType']
30
- pathParamsType: PluginReactQuery['resolvedOptions']['pathParamsType']
31
- dataReturnType: PluginReactQuery['resolvedOptions']['client']['dataReturnType']
32
- typeSchemas: OperationSchemas
33
- }
34
-
35
- function getParams({ paramsType, paramsCasing, pathParamsType, dataReturnType, typeSchemas }: GetParamsProps) {
36
- const TData = dataReturnType === 'data' ? typeSchemas.response.name : `ResponseConfig<${typeSchemas.response.name}>`
37
- const TError = `ResponseErrorConfig<${typeSchemas.errors?.map((item) => item.name).join(' | ') || 'Error'}>`
38
-
39
- if (paramsType === 'object') {
40
- const pathParams = getPathParams(typeSchemas.pathParams, { typed: true, casing: paramsCasing })
41
-
42
- const children = {
43
- ...pathParams,
44
- data: typeSchemas.request?.name
45
- ? {
46
- type: typeSchemas.request?.name,
47
- optional: isOptional(typeSchemas.request?.schema),
48
- }
49
- : undefined,
50
- params: typeSchemas.queryParams?.name
51
- ? {
52
- type: typeSchemas.queryParams?.name,
53
- optional: isOptional(typeSchemas.queryParams?.schema),
54
- }
55
- : undefined,
56
- headers: typeSchemas.headerParams?.name
57
- ? {
58
- type: typeSchemas.headerParams?.name,
59
- optional: isOptional(typeSchemas.headerParams?.schema),
60
- }
61
- : undefined,
62
- }
63
-
64
- // Check if all children are optional or undefined
65
- const allChildrenAreOptional = Object.values(children).every((child) => !child || child.optional)
66
-
67
- return FunctionParams.factory({
68
- data: {
69
- mode: 'object',
70
- children,
71
- default: allChildrenAreOptional ? '{}' : undefined,
72
- },
73
- options: {
74
- type: `
75
- {
76
- query?: Partial<UseSuspenseQueryOptions<${[TData, TError, 'TData', 'TQueryKey'].join(', ')}>> & { client?: QueryClient },
77
- client?: ${typeSchemas.request?.name ? `Partial<RequestConfig<${typeSchemas.request?.name}>> & { client?: Client }` : 'Partial<RequestConfig> & { client?: Client }'}
78
- }
79
- `,
80
- default: '{}',
81
- },
82
- })
83
- }
84
-
85
- return FunctionParams.factory({
86
- pathParams: typeSchemas.pathParams?.name
87
- ? {
88
- mode: pathParamsType === 'object' ? 'object' : 'inlineSpread',
89
- children: getPathParams(typeSchemas.pathParams, {
90
- typed: true,
91
- casing: paramsCasing,
92
- }),
93
- default: isAllOptional(typeSchemas.pathParams?.schema) ? '{}' : undefined,
94
- }
95
- : undefined,
96
- data: typeSchemas.request?.name
97
- ? {
98
- type: typeSchemas.request?.name,
99
- optional: isOptional(typeSchemas.request?.schema),
100
- }
101
- : undefined,
102
- params: typeSchemas.queryParams?.name
103
- ? {
104
- type: typeSchemas.queryParams?.name,
105
- optional: isOptional(typeSchemas.queryParams?.schema),
106
- }
107
- : undefined,
108
- headers: typeSchemas.headerParams?.name
109
- ? {
110
- type: typeSchemas.headerParams?.name,
111
- optional: isOptional(typeSchemas.headerParams?.schema),
112
- }
113
- : undefined,
114
- options: {
115
- type: `
116
- {
117
- query?: Partial<UseSuspenseQueryOptions<${[TData, TError, 'TData', 'TQueryKey'].join(', ')}>> & { client?: QueryClient },
118
- client?: ${typeSchemas.request?.name ? `Partial<RequestConfig<${typeSchemas.request?.name}>> & { client?: Client }` : 'Partial<RequestConfig> & { client?: Client }'}
119
- }
120
- `,
121
- default: '{}',
122
- },
123
- })
124
- }
125
-
126
- /**
127
- * Generates a strongly-typed React Query Suspense hook function for an OpenAPI operation.
128
- *
129
- * The generated function wraps `useSuspenseQuery`, providing type-safe parameters and return types based on the supplied OpenAPI schemas and configuration.
130
- *
131
- * @returns A React component source node containing the generated query function.
132
- */
133
- export function SuspenseQuery({
134
- name,
135
- queryKeyTypeName,
136
- queryOptionsName,
137
- queryKeyName,
138
- paramsType,
139
- paramsCasing,
140
- pathParamsType,
141
- dataReturnType,
142
- typeSchemas,
143
- operation,
144
- customOptions,
145
- }: Props): FabricReactNode {
146
- const TData = dataReturnType === 'data' ? typeSchemas.response.name : `ResponseConfig<${typeSchemas.response.name}>`
147
- const TError = `ResponseErrorConfig<${typeSchemas.errors?.map((item) => item.name).join(' | ') || 'Error'}>`
148
- const returnType = `UseSuspenseQueryResult<${['TData', TError].join(', ')}> & { queryKey: TQueryKey }`
149
- const generics = [`TData = ${TData}`, `TQueryKey extends QueryKey = ${queryKeyTypeName}`]
150
-
151
- const queryKeyParams = QueryKey.getParams({
152
- pathParamsType,
153
- typeSchemas,
154
- paramsCasing,
155
- })
156
- const queryOptionsParams = QueryOptions.getParams({
157
- paramsCasing,
158
- paramsType,
159
- pathParamsType,
160
- typeSchemas,
161
- })
162
- const params = getParams({
163
- paramsCasing,
164
- paramsType,
165
- pathParamsType,
166
- dataReturnType,
167
- typeSchemas,
168
- })
169
-
170
- const queryOptions = `${queryOptionsName}(${queryOptionsParams.toCall()})`
171
-
172
- return (
173
- <File.Source name={name} isExportable isIndexable>
174
- <Function
175
- name={name}
176
- export
177
- generics={generics.join(', ')}
178
- params={params.toConstructor()}
179
- JSDoc={{
180
- comments: getComments(operation),
181
- }}
182
- >
183
- {`
184
- const { query: queryConfig = {}, client: config = {} } = options ?? {}
185
- const { client: queryClient, ...resolvedOptions } = queryConfig
186
- const queryKey = resolvedOptions?.queryKey ?? ${queryKeyName}(${queryKeyParams.toCall()})
187
- ${customOptions ? `const customOptions = ${customOptions.name}({ hookName: '${name}', operationId: '${operation.getOperationId()}' })` : ''}
188
-
189
- const query = useSuspenseQuery({
190
- ...${queryOptions},${customOptions ? '\n...customOptions,' : ''}
191
- ...resolvedOptions,
192
- queryKey,
193
- } as unknown as UseSuspenseQueryOptions, queryClient) as ${returnType}
194
-
195
- query.queryKey = queryKey as TQueryKey
196
-
197
- return query
198
- `}
199
- </Function>
200
- </File.Source>
201
- )
202
- }
203
-
204
- SuspenseQuery.getParams = getParams
@@ -1,11 +0,0 @@
1
- export { InfiniteQuery } from './InfiniteQuery.tsx'
2
- export { InfiniteQueryOptions } from './InfiniteQueryOptions.tsx'
3
- export { Mutation } from './Mutation.tsx'
4
- export { MutationKey } from './MutationKey.tsx'
5
- export { MutationOptions } from './MutationOptions.tsx'
6
- export { Query } from './Query.tsx'
7
- export { QueryKey } from './QueryKey.tsx'
8
- export { QueryOptions } from './QueryOptions.tsx'
9
- export { SuspenseInfiniteQuery } from './SuspenseInfiniteQuery.tsx'
10
- export { SuspenseInfiniteQueryOptions } from './SuspenseInfiniteQueryOptions.tsx'
11
- export { SuspenseQuery } from './SuspenseQuery.tsx'
@@ -1,98 +0,0 @@
1
- import fs from 'node:fs'
2
- import path from 'node:path'
3
- import { usePluginDriver } from '@kubb/core/hooks'
4
- import type { Operation } from '@kubb/oas'
5
- import { createReactGenerator } from '@kubb/plugin-oas/generators'
6
- import { useOperationManager } from '@kubb/plugin-oas/hooks'
7
- import { File, Function } from '@kubb/react-fabric'
8
- import type { PluginReactQuery } from '../types'
9
-
10
- export const customHookOptionsFileGenerator = createReactGenerator<PluginReactQuery>({
11
- name: 'react-query-custom-hook-options-file',
12
- Operations({ operations, generator, plugin, config }) {
13
- const {
14
- options,
15
- options: { output },
16
- name: pluginName,
17
- } = plugin
18
- const driver = usePluginDriver()
19
-
20
- const { getFile } = useOperationManager(generator)
21
-
22
- if (!options.customOptions) {
23
- return null
24
- }
25
-
26
- const override = output.override ?? config.output.override ?? false
27
- const { importPath, name } = options.customOptions
28
-
29
- const root = path.resolve(config.root, config.output.path)
30
-
31
- const reactQueryImportPath = options.query ? options.query.importPath : '@tanstack/react-query'
32
-
33
- const getHookFilePath = (operations: Operation[]) => {
34
- const firstOperation = operations[0]
35
- if (firstOperation != null) {
36
- // Get the file of the first generated hook
37
- return getFile(firstOperation, { prefix: 'use' }).path
38
- }
39
- // Get the index file of the hooks directory
40
- return driver.getFile({ name: 'index', extname: '.ts', pluginName }).path
41
- }
42
-
43
- const ensureExtension = (filePath: string, extname: string) => {
44
- if (path.extname(filePath) === '') {
45
- return filePath + extname
46
- }
47
- return filePath
48
- }
49
-
50
- const getExternalFile = (filePath: string, rootPath: string) => {
51
- const actualFilePath = ensureExtension(filePath, '.ts')
52
- return {
53
- baseName: path.basename(actualFilePath) as `${string}.${string}`,
54
- name: path.basename(actualFilePath, path.extname(actualFilePath)),
55
- path: path.resolve(rootPath, actualFilePath),
56
- }
57
- }
58
-
59
- const basePath = path.dirname(getHookFilePath(operations))
60
- const file = getExternalFile(importPath, basePath)
61
-
62
- if (fs.existsSync(file.path) && !override) {
63
- return null
64
- }
65
-
66
- return (
67
- <File baseName={file.baseName} path={file.path}>
68
- <File.Import name={['QueryClient']} path={reactQueryImportPath} isTypeOnly />
69
- <File.Import name={['useQueryClient']} path={reactQueryImportPath} />
70
- <File.Import name={['HookOptions']} root={file.path} path={path.resolve(root, './index.ts')} />
71
- <File.Source name={file.name} isExportable isIndexable>
72
- <Function name="getCustomHookOptions" params="{ queryClient }: { queryClient: QueryClient }" returnType="Partial<HookOptions>">
73
- {`return {
74
- // TODO: Define custom hook options here
75
- // Example:
76
- // useUpdatePetHook: {
77
- // onSuccess: () => {
78
- // void queryClient.invalidateQueries({ queryKey: ['pet'] })
79
- // }
80
- // }
81
- }`}
82
- </Function>
83
- <Function
84
- name={name}
85
- generics="T extends keyof HookOptions"
86
- params="{ hookName, operationId }: { hookName: T, operationId: string }"
87
- returnType="HookOptions[T]"
88
- export
89
- >
90
- {`const queryClient = useQueryClient()
91
- const customOptions = getCustomHookOptions({ queryClient })
92
- return customOptions[hookName] ?? {}`}
93
- </Function>
94
- </File.Source>
95
- </File>
96
- )
97
- },
98
- })