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

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 (53) hide show
  1. package/LICENSE +17 -10
  2. package/README.md +1 -3
  3. package/dist/components-DTGLu4UV.js +1451 -0
  4. package/dist/components-DTGLu4UV.js.map +1 -0
  5. package/dist/components-dAKJEn9b.cjs +1571 -0
  6. package/dist/components-dAKJEn9b.cjs.map +1 -0
  7. package/dist/components.cjs +1 -1
  8. package/dist/components.d.ts +105 -161
  9. package/dist/components.js +1 -1
  10. package/dist/generators-CWEQsdO9.cjs +1502 -0
  11. package/dist/generators-CWEQsdO9.cjs.map +1 -0
  12. package/dist/generators-C_fbcjpG.js +1460 -0
  13. package/dist/generators-C_fbcjpG.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 +114 -126
  18. package/dist/index.cjs.map +1 -1
  19. package/dist/index.d.ts +4 -4
  20. package/dist/index.js +110 -126
  21. package/dist/index.js.map +1 -1
  22. package/dist/{types-D5S7Ny9r.d.ts → types-DfaFRSBf.d.ts} +100 -86
  23. package/extension.yaml +938 -0
  24. package/package.json +59 -62
  25. package/src/components/InfiniteQuery.tsx +75 -139
  26. package/src/components/InfiniteQueryOptions.tsx +62 -164
  27. package/src/components/Mutation.tsx +58 -113
  28. package/src/components/MutationOptions.tsx +61 -80
  29. package/src/components/Query.tsx +67 -140
  30. package/src/components/QueryOptions.tsx +75 -135
  31. package/src/components/SuspenseInfiniteQuery.tsx +75 -139
  32. package/src/components/SuspenseInfiniteQueryOptions.tsx +62 -164
  33. package/src/components/SuspenseQuery.tsx +67 -150
  34. package/src/generators/customHookOptionsFileGenerator.tsx +33 -45
  35. package/src/generators/hookOptionsGenerator.tsx +115 -175
  36. package/src/generators/infiniteQueryGenerator.tsx +183 -176
  37. package/src/generators/mutationGenerator.tsx +127 -138
  38. package/src/generators/queryGenerator.tsx +141 -141
  39. package/src/generators/suspenseInfiniteQueryGenerator.tsx +175 -155
  40. package/src/generators/suspenseQueryGenerator.tsx +149 -148
  41. package/src/index.ts +1 -1
  42. package/src/plugin.ts +133 -183
  43. package/src/resolvers/resolverReactQuery.ts +22 -0
  44. package/src/types.ts +67 -45
  45. package/src/utils.ts +40 -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
@@ -1,190 +1,190 @@
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 { ast, defineGenerator } from '@kubb/core'
3
+ import { Client, pluginClientName } from '@kubb/plugin-client'
8
4
  import { pluginTsName } from '@kubb/plugin-ts'
9
5
  import { pluginZodName } from '@kubb/plugin-zod'
10
- import { File } from '@kubb/react-fabric'
6
+ import { File, jsxRenderer } from '@kubb/renderer-jsx'
11
7
  import { difference } from 'remeda'
12
8
  import { Query, QueryKey, QueryOptions } from '../components'
13
9
  import type { PluginReactQuery } from '../types'
10
+ import { transformName } from '../utils.ts'
14
11
 
15
- export const queryGenerator = createReactGenerator<PluginReactQuery>({
12
+ export const queryGenerator = defineGenerator<PluginReactQuery>({
16
13
  name: 'react-query',
17
- Operation({ config, plugin, operation, generator }) {
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
- )
14
+ renderer: jsxRenderer,
15
+ operation(node, ctx) {
16
+ const { adapter, config, driver, resolver, root } = ctx
17
+ const { output, query, mutation, paramsCasing, paramsType, pathParamsType, parser, client: clientOptions, group, transformers, customOptions } = ctx.options
31
18
 
32
- const importPath = options.query ? options.query.importPath : '@tanstack/react-query'
19
+ const pluginTs = driver.getPlugin(pluginTsName)
20
+ if (!pluginTs) return null
21
+ const tsResolver = driver.getResolver(pluginTsName)
33
22
 
34
- const query = {
35
- name: getName(operation, { type: 'function', prefix: 'use' }),
36
- typeName: getName(operation, { type: 'type' }),
37
- file: getFile(operation, { prefix: 'use' }),
38
- }
23
+ // query: false means "this IS a query op, but skip the useQuery hook"
24
+ const isQuery = query === false || (!!query && query.methods.some((method) => node.method.toLowerCase() === method.toLowerCase()))
25
+ const isMutation =
26
+ mutation !== false &&
27
+ !isQuery &&
28
+ difference(mutation ? mutation.methods : [], query ? query.methods : []).some((method) => node.method.toLowerCase() === method.toLowerCase())
39
29
 
40
- const hasClientPlugin = !!driver.getPluginByName(pluginClientName)
41
- // Class-based clients are not compatible with query hooks, so we generate inline clients
42
- const shouldUseClientPlugin = hasClientPlugin && options.client.clientType !== 'class'
43
- const client = {
44
- name: shouldUseClientPlugin
45
- ? getName(operation, {
46
- type: 'function',
47
- pluginName: pluginClientName,
48
- })
49
- : getName(operation, {
50
- type: 'function',
51
- }),
52
- file: getFile(operation, { pluginName: pluginClientName }),
53
- }
30
+ if (!isQuery || isMutation) return null
54
31
 
55
- const queryOptions = {
56
- name: getName(operation, { type: 'function', suffix: 'QueryOptions' }),
57
- }
32
+ const importPath = query ? query.importPath : '@tanstack/react-query'
58
33
 
59
- const queryKey = {
60
- name: getName(operation, { type: 'const', suffix: 'QueryKey' }),
61
- typeName: getName(operation, { type: 'type', suffix: 'QueryKey' }),
62
- }
34
+ const baseName = resolver.resolveName(node.operationId)
35
+ const capitalize = (s: string) => s.charAt(0).toUpperCase() + s.slice(1)
36
+ const queryName = transformName(`use${capitalize(baseName)}`, 'function', transformers)
37
+ const queryOptionsName = transformName(`${baseName}QueryOptions`, 'function', transformers)
38
+ const queryKeyName = transformName(`${baseName}QueryKey`, 'const', transformers)
39
+ const queryKeyTypeName = transformName(`${capitalize(baseName)}QueryKey`, 'type', transformers)
40
+ const clientName = transformName(baseName, 'function', transformers)
63
41
 
64
- const type = {
65
- file: getFile(operation, { pluginName: pluginTsName }),
66
- //todo remove type?
67
- schemas: getSchemas(operation, {
68
- pluginName: pluginTsName,
69
- type: 'type',
70
- }),
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
+ ),
71
48
  }
72
49
 
73
- const zod = {
74
- // grouping is coming from react-query instead of zod option, we need to pass the options of zod instead
75
- file: getFile(operation, { pluginName: pluginZodName }),
76
- schemas: getSchemas(operation, {
77
- pluginName: pluginZodName,
78
- type: 'function',
79
- }),
80
- }
50
+ const casedParams = ast.caseParams(node.parameters, paramsCasing)
51
+ const pathParams = casedParams.filter((p) => p.in === 'path')
52
+ const queryParams = casedParams.filter((p) => p.in === 'query')
53
+ const headerParams = casedParams.filter((p) => p.in === 'header')
81
54
 
82
- if (!isQuery || isMutation) {
83
- return null
84
- }
55
+ const importedTypeNames = [
56
+ node.requestBody?.content?.[0]?.schema ? tsResolver.resolveDataName(node) : undefined,
57
+ tsResolver.resolveResponseName(node),
58
+ ...pathParams.map((p) => tsResolver.resolvePathParamsName(node, p)),
59
+ ...queryParams.map((p) => tsResolver.resolveQueryParamsName(node, p)),
60
+ ...headerParams.map((p) => tsResolver.resolveHeaderParamsName(node, p)),
61
+ ...node.responses.map((res) => tsResolver.resolveResponseStatusName(node, res.statusCode)),
62
+ ].filter((name): name is string => !!name && name !== queryKeyTypeName)
63
+
64
+ const pluginZod = parser === 'zod' ? driver.getPlugin(pluginZodName) : undefined
65
+ const zodResolver = pluginZod ? driver.getResolver(pluginZodName) : undefined
66
+ const fileZod = zodResolver
67
+ ? zodResolver.resolveFile(
68
+ { name: node.operationId, extname: '.ts', tag: node.tags[0] ?? 'default', path: node.path },
69
+ { root, output: pluginZod?.options?.output ?? output, group: pluginZod?.options?.group },
70
+ )
71
+ : undefined
72
+ const zodSchemaNames =
73
+ zodResolver && parser === 'zod'
74
+ ? [zodResolver.resolveResponseName?.(node), node.requestBody?.content?.[0]?.schema ? zodResolver.resolveDataName?.(node) : undefined].filter(Boolean)
75
+ : []
76
+
77
+ const clientPlugin = driver.getPlugin(pluginClientName)
78
+ const hasClientPlugin = clientPlugin?.name === pluginClientName
79
+ const shouldUseClientPlugin = hasClientPlugin && clientOptions.clientType !== 'class'
80
+ const clientResolver = shouldUseClientPlugin ? driver.getResolver(pluginClientName) : undefined
81
+
82
+ const clientFile = shouldUseClientPlugin
83
+ ? clientResolver?.resolveFile(
84
+ { name: node.operationId, extname: '.ts', tag: node.tags[0] ?? 'default', path: node.path },
85
+ {
86
+ root,
87
+ output: clientPlugin?.options?.output ?? output,
88
+ group: clientPlugin?.options?.group,
89
+ },
90
+ )
91
+ : undefined
92
+
93
+ const resolvedClientName = shouldUseClientPlugin ? (clientResolver?.resolveName(node.operationId) ?? clientName) : clientName
85
94
 
86
95
  return (
87
96
  <File
88
- baseName={query.file.baseName}
89
- path={query.file.path}
90
- meta={query.file.meta}
91
- banner={getBanner({ oas, output, config: driver.config })}
92
- footer={getFooter({ oas, output })}
97
+ baseName={meta.file.baseName}
98
+ path={meta.file.path}
99
+ meta={meta.file.meta}
100
+ banner={resolver.resolveBanner(adapter.inputNode, { output, config })}
101
+ footer={resolver.resolveFooter(adapter.inputNode, { output, config })}
93
102
  >
94
- {options.parser === 'zod' && (
95
- <File.Import name={[zod.schemas.response.name, zod.schemas.request?.name].filter(Boolean)} root={query.file.path} path={zod.file.path} />
103
+ {parser === 'zod' && fileZod && zodSchemaNames.length > 0 && (
104
+ <File.Import name={zodSchemaNames as string[]} root={meta.file.path} path={fileZod.path} />
96
105
  )}
97
- {options.client.importPath ? (
106
+ {clientOptions.importPath ? (
98
107
  <>
99
- {!shouldUseClientPlugin && <File.Import name={'fetch'} path={options.client.importPath} />}
100
- <File.Import name={['Client', 'RequestConfig', 'ResponseErrorConfig']} path={options.client.importPath} isTypeOnly />
101
- {options.client.dataReturnType === 'full' && <File.Import name={['ResponseConfig']} path={options.client.importPath} isTypeOnly />}
108
+ {!shouldUseClientPlugin && <File.Import name={'fetch'} path={clientOptions.importPath} />}
109
+ <File.Import name={['Client', 'RequestConfig', 'ResponseErrorConfig']} path={clientOptions.importPath} isTypeOnly />
110
+ {clientOptions.dataReturnType === 'full' && <File.Import name={['ResponseConfig']} path={clientOptions.importPath} isTypeOnly />}
102
111
  </>
103
112
  ) : (
104
113
  <>
105
- {!shouldUseClientPlugin && (
106
- <File.Import name={['fetch']} root={query.file.path} path={path.resolve(config.root, config.output.path, '.kubb/fetch.ts')} />
107
- )}
114
+ {!shouldUseClientPlugin && <File.Import name={['fetch']} root={meta.file.path} path={path.resolve(root, '.kubb/fetch.ts')} />}
108
115
  <File.Import
109
116
  name={['Client', 'RequestConfig', 'ResponseErrorConfig']}
110
- root={query.file.path}
111
- path={path.resolve(config.root, config.output.path, '.kubb/fetch.ts')}
117
+ root={meta.file.path}
118
+ path={path.resolve(root, '.kubb/fetch.ts')}
112
119
  isTypeOnly
113
120
  />
114
- {options.client.dataReturnType === 'full' && (
115
- <File.Import name={['ResponseConfig']} root={query.file.path} path={path.resolve(config.root, config.output.path, '.kubb/fetch.ts')} isTypeOnly />
121
+ {clientOptions.dataReturnType === 'full' && (
122
+ <File.Import name={['ResponseConfig']} root={meta.file.path} path={path.resolve(root, '.kubb/fetch.ts')} isTypeOnly />
116
123
  )}
117
124
  </>
118
125
  )}
119
-
120
- {shouldUseClientPlugin && <File.Import name={[client.name]} root={query.file.path} path={client.file.path} />}
121
- {!shouldUseClientPlugin && (
122
- <File.Import name={['buildFormData']} root={query.file.path} path={path.resolve(config.root, config.output.path, '.kubb/config.ts')} />
126
+ {shouldUseClientPlugin && clientFile && <File.Import name={[resolvedClientName]} root={meta.file.path} path={clientFile.path} />}
127
+ {!shouldUseClientPlugin && <File.Import name={['buildFormData']} root={meta.file.path} path={path.resolve(root, '.kubb/config.ts')} />}
128
+ {customOptions && <File.Import name={[customOptions.name]} path={customOptions.importPath} />}
129
+ {meta.fileTs && importedTypeNames.length > 0 && (
130
+ <File.Import name={Array.from(new Set(importedTypeNames))} root={meta.file.path} path={meta.fileTs.path} isTypeOnly />
123
131
  )}
124
- {options.customOptions && <File.Import name={[options.customOptions.name]} path={options.customOptions.importPath} />}
125
- <File.Import
126
- name={[
127
- type.schemas.request?.name,
128
- type.schemas.response.name,
129
- type.schemas.pathParams?.name,
130
- type.schemas.queryParams?.name,
131
- type.schemas.headerParams?.name,
132
- ...(type.schemas.statusCodes?.map((item) => item.name) || []),
133
- ].filter(Boolean)}
134
- root={query.file.path}
135
- path={type.file.path}
136
- isTypeOnly
137
- />
132
+
138
133
  <QueryKey
139
- name={queryKey.name}
140
- typeName={queryKey.typeName}
141
- operation={operation}
142
- pathParamsType={options.pathParamsType}
143
- typeSchemas={type.schemas}
144
- paramsCasing={options.paramsCasing}
145
- transformer={options.queryKey}
134
+ name={queryKeyName}
135
+ typeName={queryKeyTypeName}
136
+ node={node}
137
+ tsResolver={tsResolver}
138
+ pathParamsType={pathParamsType}
139
+ paramsCasing={paramsCasing}
140
+ transformer={ctx.options.queryKey}
146
141
  />
142
+
147
143
  {!shouldUseClientPlugin && (
148
144
  <Client
149
- name={client.name}
150
- baseURL={options.client.baseURL}
151
- operation={operation}
152
- typeSchemas={type.schemas}
153
- zodSchemas={zod.schemas}
154
- dataReturnType={options.client.dataReturnType || 'data'}
155
- paramsType={options.paramsType}
156
- paramsCasing={options.client?.paramsCasing || options.paramsCasing}
157
- pathParamsType={options.pathParamsType}
158
- parser={options.parser}
145
+ name={resolvedClientName}
146
+ baseURL={clientOptions.baseURL}
147
+ dataReturnType={clientOptions.dataReturnType || 'data'}
148
+ paramsCasing={clientOptions.paramsCasing || paramsCasing}
149
+ paramsType={paramsType}
150
+ pathParamsType={pathParamsType}
151
+ parser={parser}
152
+ node={node}
153
+ tsResolver={tsResolver}
154
+ zodResolver={zodResolver}
159
155
  />
160
156
  )}
157
+
161
158
  <File.Import name={['queryOptions']} path={importPath} />
159
+
162
160
  <QueryOptions
163
- name={queryOptions.name}
164
- clientName={client.name}
165
- queryKeyName={queryKey.name}
166
- typeSchemas={type.schemas}
167
- paramsCasing={options.paramsCasing}
168
- paramsType={options.paramsType}
169
- pathParamsType={options.pathParamsType}
170
- dataReturnType={options.client.dataReturnType || 'data'}
161
+ name={queryOptionsName}
162
+ clientName={resolvedClientName}
163
+ queryKeyName={queryKeyName}
164
+ node={node}
165
+ tsResolver={tsResolver}
166
+ paramsCasing={paramsCasing}
167
+ paramsType={paramsType}
168
+ pathParamsType={pathParamsType}
169
+ dataReturnType={clientOptions.dataReturnType || 'data'}
171
170
  />
172
- {options.query && (
171
+
172
+ {query && (
173
173
  <>
174
174
  <File.Import name={['useQuery']} path={importPath} />
175
- <File.Import name={['QueryKey', 'QueryClient', 'QueryObserverOptions', 'UseQueryResult', 'QueryClient']} path={importPath} isTypeOnly />
175
+ <File.Import name={['QueryKey', 'QueryClient', 'QueryObserverOptions', 'UseQueryResult']} path={importPath} isTypeOnly />
176
176
  <Query
177
- name={query.name}
178
- queryOptionsName={queryOptions.name}
179
- typeSchemas={type.schemas}
180
- paramsCasing={options.paramsCasing}
181
- paramsType={options.paramsType}
182
- pathParamsType={options.pathParamsType}
183
- operation={operation}
184
- dataReturnType={options.client.dataReturnType || 'data'}
185
- queryKeyName={queryKey.name}
186
- queryKeyTypeName={queryKey.typeName}
187
- customOptions={options.customOptions}
177
+ name={queryName}
178
+ queryOptionsName={queryOptionsName}
179
+ queryKeyName={queryKeyName}
180
+ queryKeyTypeName={queryKeyTypeName}
181
+ node={node}
182
+ tsResolver={tsResolver}
183
+ paramsCasing={paramsCasing}
184
+ paramsType={paramsType}
185
+ pathParamsType={pathParamsType}
186
+ dataReturnType={clientOptions.dataReturnType || 'data'}
187
+ customOptions={customOptions}
188
188
  />
189
189
  </>
190
190
  )}