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

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 (54) hide show
  1. package/LICENSE +17 -10
  2. package/README.md +34 -85
  3. package/dist/components-Dow6tde8.js +1459 -0
  4. package/dist/components-Dow6tde8.js.map +1 -0
  5. package/dist/components-HwdCDefj.cjs +1603 -0
  6. package/dist/components-HwdCDefj.cjs.map +1 -0
  7. package/dist/components.cjs +1 -1
  8. package/dist/components.d.ts +49 -179
  9. package/dist/components.js +1 -1
  10. package/dist/generators-CcOmnTPa.cjs +1454 -0
  11. package/dist/generators-CcOmnTPa.cjs.map +1 -0
  12. package/dist/generators-yfZr_qfT.js +1412 -0
  13. package/dist/generators-yfZr_qfT.js.map +1 -0
  14. package/dist/generators.cjs +1 -1
  15. package/dist/generators.d.ts +9 -505
  16. package/dist/generators.js +1 -1
  17. package/dist/index.cjs +197 -126
  18. package/dist/index.cjs.map +1 -1
  19. package/dist/index.d.ts +4 -4
  20. package/dist/index.js +193 -126
  21. package/dist/index.js.map +1 -1
  22. package/dist/types-DG_OxOym.d.ts +363 -0
  23. package/extension.yaml +911 -0
  24. package/package.json +59 -64
  25. package/src/components/InfiniteQuery.tsx +79 -138
  26. package/src/components/InfiniteQueryOptions.tsx +55 -166
  27. package/src/components/Mutation.tsx +74 -111
  28. package/src/components/MutationOptions.tsx +61 -80
  29. package/src/components/Query.tsx +66 -142
  30. package/src/components/QueryOptions.tsx +56 -138
  31. package/src/components/SuspenseInfiniteQuery.tsx +79 -138
  32. package/src/components/SuspenseInfiniteQueryOptions.tsx +55 -166
  33. package/src/components/SuspenseQuery.tsx +66 -152
  34. package/src/generators/customHookOptionsFileGenerator.tsx +37 -51
  35. package/src/generators/hookOptionsGenerator.tsx +111 -174
  36. package/src/generators/infiniteQueryGenerator.tsx +158 -178
  37. package/src/generators/mutationGenerator.tsx +112 -139
  38. package/src/generators/queryGenerator.tsx +128 -142
  39. package/src/generators/suspenseInfiniteQueryGenerator.tsx +157 -156
  40. package/src/generators/suspenseQueryGenerator.tsx +126 -152
  41. package/src/index.ts +1 -1
  42. package/src/plugin.ts +134 -187
  43. package/src/resolvers/resolverReactQuery.ts +107 -0
  44. package/src/types.ts +172 -49
  45. package/src/utils.ts +10 -0
  46. package/dist/components-BHQT9ZLc.cjs +0 -1634
  47. package/dist/components-BHQT9ZLc.cjs.map +0 -1
  48. package/dist/components-CpyHYGOw.js +0 -1520
  49. package/dist/components-CpyHYGOw.js.map +0 -1
  50. package/dist/generators-DP07m3rH.cjs +0 -1469
  51. package/dist/generators-DP07m3rH.cjs.map +0 -1
  52. package/dist/generators-DkQwKTc2.js +0 -1427
  53. package/dist/generators-DkQwKTc2.js.map +0 -1
  54. package/dist/types-D5S7Ny9r.d.ts +0 -270
@@ -1,203 +1,177 @@
1
1
  import path from 'node:path'
2
- import { usePluginDriver } from '@kubb/core/hooks'
3
- import { pluginClientName } from '@kubb/plugin-client'
4
- import { Client } from '@kubb/plugin-client/components'
5
- import { createReactGenerator } from '@kubb/plugin-oas/generators'
6
- import { useOas, useOperationManager } from '@kubb/plugin-oas/hooks'
7
- import { getBanner, getFooter } from '@kubb/plugin-oas/utils'
2
+ import { resolveOperationTypeNames } from '@internals/shared'
3
+ import { resolveZodSchemaNames } from '@internals/tanstack-query'
4
+ import { defineGenerator } from '@kubb/core'
5
+ import { Client, pluginClientName } from '@kubb/plugin-client'
8
6
  import { pluginTsName } from '@kubb/plugin-ts'
9
7
  import { pluginZodName } from '@kubb/plugin-zod'
10
- import { File } from '@kubb/react-fabric'
8
+ import { File, jsxRenderer } from '@kubb/renderer-jsx'
11
9
  import { difference } from 'remeda'
12
10
  import { QueryKey, QueryOptions, SuspenseQuery } from '../components'
13
11
  import type { PluginReactQuery } from '../types'
14
12
 
15
- export const suspenseQueryGenerator = createReactGenerator<PluginReactQuery>({
13
+ export const suspenseQueryGenerator = defineGenerator<PluginReactQuery>({
16
14
  name: 'react-suspense-query',
17
- Operation({ config, operation, generator, plugin }) {
18
- const {
19
- options,
20
- options: { output },
21
- } = plugin
22
- const driver = usePluginDriver()
23
-
24
- const oas = useOas()
25
- const { getSchemas, getName, getFile } = useOperationManager(generator)
26
-
27
- const isQuery = typeof options.query === 'boolean' ? true : options.query?.methods.some((method) => operation.method === method)
28
- const isMutation = difference(options.mutation ? options.mutation.methods : [], options.query ? options.query.methods : []).some(
29
- (method) => operation.method === method,
30
- )
15
+ renderer: jsxRenderer,
16
+ operation(node, ctx) {
17
+ const { adapter, config, driver, resolver, root } = ctx
18
+ const { output, query, mutation, suspense, paramsCasing, paramsType, pathParamsType, parser, client: clientOptions, group, customOptions } = ctx.options
31
19
 
32
- const isSuspense = !!options.suspense
20
+ const pluginTs = driver.getPlugin(pluginTsName)
21
+ if (!pluginTs) return null
22
+ const tsResolver = driver.getResolver(pluginTsName)
33
23
 
34
- const importPath = options.query ? options.query.importPath : '@tanstack/react-query'
24
+ // query: false means "this IS a query op" (suspense hooks still generate)
25
+ const isQuery = query === false || (!!query && query.methods.some((method) => node.method.toLowerCase() === method.toLowerCase()))
26
+ const isMutation =
27
+ mutation !== false &&
28
+ !isQuery &&
29
+ difference(mutation ? mutation.methods : [], query ? query.methods : []).some((method) => node.method.toLowerCase() === method.toLowerCase())
30
+ const isSuspense = !!suspense
35
31
 
36
- const query = {
37
- name: getName(operation, {
38
- type: 'function',
39
- prefix: 'use',
40
- suffix: 'suspense',
41
- }),
42
- typeName: getName(operation, { type: 'type' }),
43
- file: getFile(operation, { prefix: 'use', suffix: 'suspense' }),
44
- }
32
+ if (!isQuery || isMutation || !isSuspense) return null
45
33
 
46
- const hasClientPlugin = !!driver.getPluginByName(pluginClientName)
47
- // Class-based clients are not compatible with query hooks, so we generate inline clients
48
- const shouldUseClientPlugin = hasClientPlugin && options.client.clientType !== 'class'
49
- const client = {
50
- name: shouldUseClientPlugin
51
- ? getName(operation, {
52
- type: 'function',
53
- pluginName: pluginClientName,
54
- })
55
- : getName(operation, {
56
- type: 'function',
57
- suffix: 'suspense',
58
- }),
59
- file: getFile(operation, { pluginName: pluginClientName }),
60
- }
34
+ const importPath = query ? query.importPath : '@tanstack/react-query'
61
35
 
62
- const queryOptions = {
63
- name: getName(operation, {
64
- type: 'function',
65
- suffix: 'SuspenseQueryOptions',
66
- }),
67
- }
36
+ const queryName = resolver.resolveSuspenseQueryName(node)
37
+ const queryOptionsName = resolver.resolveSuspenseQueryOptionsName(node)
38
+ const queryKeyName = resolver.resolveSuspenseQueryKeyName(node)
39
+ const queryKeyTypeName = resolver.resolveSuspenseQueryKeyTypeName(node)
40
+ const clientName = resolver.resolveSuspenseClientName(node)
68
41
 
69
- const queryKey = {
70
- name: getName(operation, { type: 'const', suffix: 'SuspenseQueryKey' }),
71
- typeName: getName(operation, {
72
- type: 'type',
73
- suffix: 'SuspenseQueryKey',
74
- }),
42
+ const meta = {
43
+ file: resolver.resolveFile({ name: queryName, extname: '.ts', tag: node.tags[0] ?? 'default', path: node.path }, { root, output, group }),
44
+ fileTs: tsResolver.resolveFile(
45
+ { name: node.operationId, extname: '.ts', tag: node.tags[0] ?? 'default', path: node.path },
46
+ { root, output: pluginTs.options?.output ?? output, group: pluginTs.options?.group },
47
+ ),
75
48
  }
76
49
 
77
- const type = {
78
- file: getFile(operation, { pluginName: pluginTsName }),
79
- //todo remove type?
80
- schemas: getSchemas(operation, {
81
- pluginName: pluginTsName,
82
- type: 'type',
83
- }),
84
- }
50
+ const importedTypeNames = resolveOperationTypeNames(node, tsResolver, {
51
+ paramsCasing,
52
+ exclude: [queryKeyTypeName],
53
+ order: 'body-response-first',
54
+ })
85
55
 
86
- const zod = {
87
- file: getFile(operation, { pluginName: pluginZodName }),
88
- schemas: getSchemas(operation, {
89
- pluginName: pluginZodName,
90
- type: 'function',
91
- }),
92
- }
56
+ const pluginZod = parser === 'zod' ? driver.getPlugin(pluginZodName) : undefined
57
+ const zodResolver = pluginZod ? driver.getResolver(pluginZodName) : undefined
58
+ const fileZod = zodResolver
59
+ ? zodResolver.resolveFile(
60
+ { name: node.operationId, extname: '.ts', tag: node.tags[0] ?? 'default', path: node.path },
61
+ { root, output: pluginZod?.options?.output ?? output, group: pluginZod?.options?.group },
62
+ )
63
+ : undefined
64
+ const zodSchemaNames = resolveZodSchemaNames(node, zodResolver)
93
65
 
94
- if (!isQuery || isMutation || !isSuspense) {
95
- return null
96
- }
66
+ const clientPlugin = driver.getPlugin(pluginClientName)
67
+ const hasClientPlugin = clientPlugin?.name === pluginClientName
68
+ const shouldUseClientPlugin = hasClientPlugin && clientOptions.clientType !== 'class'
69
+ const clientResolver = shouldUseClientPlugin ? driver.getResolver(pluginClientName) : undefined
70
+
71
+ const clientFile = shouldUseClientPlugin
72
+ ? clientResolver?.resolveFile(
73
+ { name: node.operationId, extname: '.ts', tag: node.tags[0] ?? 'default', path: node.path },
74
+ {
75
+ root,
76
+ output: clientPlugin?.options?.output ?? output,
77
+ group: clientPlugin?.options?.group,
78
+ },
79
+ )
80
+ : undefined
81
+
82
+ const resolvedClientName = shouldUseClientPlugin ? (clientResolver?.resolveName(node.operationId) ?? clientName) : clientName
97
83
 
98
84
  return (
99
85
  <File
100
- baseName={query.file.baseName}
101
- path={query.file.path}
102
- meta={query.file.meta}
103
- banner={getBanner({ oas, output, config: driver.config })}
104
- footer={getFooter({ oas, output })}
86
+ baseName={meta.file.baseName}
87
+ path={meta.file.path}
88
+ meta={meta.file.meta}
89
+ banner={resolver.resolveBanner(adapter.inputNode, { output, config })}
90
+ footer={resolver.resolveFooter(adapter.inputNode, { output, config })}
105
91
  >
106
- {options.parser === 'zod' && (
107
- <File.Import name={[zod.schemas.response.name, zod.schemas.request?.name].filter(Boolean)} root={query.file.path} path={zod.file.path} />
108
- )}
109
- {options.client.importPath ? (
92
+ {fileZod && zodSchemaNames.length > 0 && <File.Import name={zodSchemaNames} root={meta.file.path} path={fileZod.path} />}
93
+ {clientOptions.importPath ? (
110
94
  <>
111
- {!shouldUseClientPlugin && <File.Import name={'fetch'} path={options.client.importPath} />}
112
- <File.Import name={['Client', 'RequestConfig', 'ResponseErrorConfig']} path={options.client.importPath} isTypeOnly />
113
- {options.client.dataReturnType === 'full' && <File.Import name={['ResponseConfig']} path={options.client.importPath} isTypeOnly />}
95
+ {!shouldUseClientPlugin && <File.Import name={'fetch'} path={clientOptions.importPath} />}
96
+ <File.Import name={['Client', 'RequestConfig', 'ResponseErrorConfig']} path={clientOptions.importPath} isTypeOnly />
97
+ {clientOptions.dataReturnType === 'full' && <File.Import name={['ResponseConfig']} path={clientOptions.importPath} isTypeOnly />}
114
98
  </>
115
99
  ) : (
116
100
  <>
117
- {!shouldUseClientPlugin && (
118
- <File.Import name={['fetch']} root={query.file.path} path={path.resolve(config.root, config.output.path, '.kubb/fetch.ts')} />
119
- )}
101
+ {!shouldUseClientPlugin && <File.Import name={['fetch']} root={meta.file.path} path={path.resolve(root, '.kubb/fetch.ts')} />}
120
102
  <File.Import
121
103
  name={['Client', 'RequestConfig', 'ResponseErrorConfig']}
122
- root={query.file.path}
123
- path={path.resolve(config.root, config.output.path, '.kubb/fetch.ts')}
104
+ root={meta.file.path}
105
+ path={path.resolve(root, '.kubb/fetch.ts')}
124
106
  isTypeOnly
125
107
  />
126
- {options.client.dataReturnType === 'full' && (
127
- <File.Import name={['ResponseConfig']} root={query.file.path} path={path.resolve(config.root, config.output.path, '.kubb/fetch.ts')} isTypeOnly />
108
+ {clientOptions.dataReturnType === 'full' && (
109
+ <File.Import name={['ResponseConfig']} root={meta.file.path} path={path.resolve(root, '.kubb/fetch.ts')} isTypeOnly />
128
110
  )}
129
111
  </>
130
112
  )}
131
- {shouldUseClientPlugin && <File.Import name={[client.name]} root={query.file.path} path={client.file.path} />}
132
- {!shouldUseClientPlugin && (
133
- <File.Import name={['buildFormData']} root={query.file.path} path={path.resolve(config.root, config.output.path, '.kubb/config.ts')} />
113
+ {shouldUseClientPlugin && clientFile && <File.Import name={[resolvedClientName]} root={meta.file.path} path={clientFile.path} />}
114
+ {!shouldUseClientPlugin && <File.Import name={['buildFormData']} root={meta.file.path} path={path.resolve(root, '.kubb/config.ts')} />}
115
+ {customOptions && <File.Import name={[customOptions.name]} path={customOptions.importPath} />}
116
+ {meta.fileTs && importedTypeNames.length > 0 && (
117
+ <File.Import name={Array.from(new Set(importedTypeNames))} root={meta.file.path} path={meta.fileTs.path} isTypeOnly />
134
118
  )}
135
- {options.customOptions && <File.Import name={[options.customOptions.name]} path={options.customOptions.importPath} />}
136
- <File.Import
137
- name={[
138
- type.schemas.request?.name,
139
- type.schemas.response.name,
140
- type.schemas.pathParams?.name,
141
- type.schemas.queryParams?.name,
142
- type.schemas.headerParams?.name,
143
- ...(type.schemas.statusCodes?.map((item) => item.name) || []),
144
- ].filter(Boolean)}
145
- root={query.file.path}
146
- path={type.file.path}
147
- isTypeOnly
148
- />
119
+
149
120
  <QueryKey
150
- name={queryKey.name}
151
- typeName={queryKey.typeName}
152
- operation={operation}
153
- paramsCasing={options.paramsCasing}
154
- pathParamsType={options.pathParamsType}
155
- typeSchemas={type.schemas}
156
- transformer={options.queryKey}
121
+ name={queryKeyName}
122
+ typeName={queryKeyTypeName}
123
+ node={node}
124
+ tsResolver={tsResolver}
125
+ pathParamsType={pathParamsType}
126
+ paramsCasing={paramsCasing}
127
+ transformer={ctx.options.queryKey}
157
128
  />
158
129
 
159
130
  {!shouldUseClientPlugin && (
160
131
  <Client
161
- name={client.name}
162
- baseURL={options.client.baseURL}
163
- operation={operation}
164
- typeSchemas={type.schemas}
165
- zodSchemas={zod.schemas}
166
- dataReturnType={options.client.dataReturnType || 'data'}
167
- paramsCasing={options.client?.paramsCasing || options.paramsCasing}
168
- paramsType={options.paramsType}
169
- pathParamsType={options.pathParamsType}
170
- parser={options.parser}
132
+ name={resolvedClientName}
133
+ baseURL={clientOptions.baseURL}
134
+ dataReturnType={clientOptions.dataReturnType || 'data'}
135
+ paramsCasing={clientOptions.paramsCasing || paramsCasing}
136
+ paramsType={paramsType}
137
+ pathParamsType={pathParamsType}
138
+ parser={parser}
139
+ node={node}
140
+ tsResolver={tsResolver}
141
+ zodResolver={zodResolver}
171
142
  />
172
143
  )}
144
+
173
145
  <File.Import name={['queryOptions']} path={importPath} />
146
+
174
147
  <QueryOptions
175
- name={queryOptions.name}
176
- clientName={client.name}
177
- queryKeyName={queryKey.name}
178
- typeSchemas={type.schemas}
179
- paramsCasing={options.paramsCasing}
180
- paramsType={options.paramsType}
181
- pathParamsType={options.pathParamsType}
182
- dataReturnType={options.client.dataReturnType}
148
+ name={queryOptionsName}
149
+ clientName={resolvedClientName}
150
+ queryKeyName={queryKeyName}
151
+ node={node}
152
+ tsResolver={tsResolver}
153
+ paramsCasing={paramsCasing}
154
+ paramsType={paramsType}
155
+ pathParamsType={pathParamsType}
156
+ dataReturnType={clientOptions.dataReturnType || 'data'}
183
157
  />
184
- {options.suspense && (
158
+
159
+ {suspense && (
185
160
  <>
186
161
  <File.Import name={['useSuspenseQuery']} path={importPath} />
187
162
  <File.Import name={['QueryKey', 'QueryClient', 'UseSuspenseQueryOptions', 'UseSuspenseQueryResult']} path={importPath} isTypeOnly />
188
-
189
163
  <SuspenseQuery
190
- name={query.name}
191
- queryOptionsName={queryOptions.name}
192
- typeSchemas={type.schemas}
193
- paramsType={options.paramsType}
194
- paramsCasing={options.paramsCasing}
195
- pathParamsType={options.pathParamsType}
196
- operation={operation}
197
- dataReturnType={options.client.dataReturnType || 'data'}
198
- queryKeyName={queryKey.name}
199
- queryKeyTypeName={queryKey.typeName}
200
- customOptions={options.customOptions}
164
+ name={queryName}
165
+ queryOptionsName={queryOptionsName}
166
+ queryKeyName={queryKeyName}
167
+ queryKeyTypeName={queryKeyTypeName}
168
+ node={node}
169
+ tsResolver={tsResolver}
170
+ paramsCasing={paramsCasing}
171
+ paramsType={paramsType}
172
+ pathParamsType={pathParamsType}
173
+ dataReturnType={clientOptions.dataReturnType || 'data'}
174
+ customOptions={customOptions}
201
175
  />
202
176
  </>
203
177
  )}
package/src/index.ts CHANGED
@@ -1,2 +1,2 @@
1
- export { pluginReactQuery, pluginReactQueryName } from './plugin.ts'
1
+ export { default, pluginReactQuery, pluginReactQueryName } from './plugin.ts'
2
2
  export type { PluginReactQuery } from './types.ts'