@kubb/plugin-react-query 5.0.0-alpha.8 → 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 -476
  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,201 +1,202 @@
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 { getOperationParameters, 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, SuspenseInfiniteQuery, SuspenseInfiniteQueryOptions } from '../components'
13
11
  import type { PluginReactQuery } from '../types'
14
12
 
15
- export const suspenseInfiniteQueryGenerator = createReactGenerator<PluginReactQuery>({
13
+ export const suspenseInfiniteQueryGenerator = defineGenerator<PluginReactQuery>({
16
14
  name: 'react-suspense-infinite-query',
17
- Operation({ config, operation, generator, plugin }) {
15
+ renderer: jsxRenderer,
16
+ operation(node, ctx) {
17
+ const { adapter, config, driver, resolver, root } = ctx
18
18
  const {
19
- options,
20
- options: { output },
21
- } = plugin
22
- const driver = usePluginDriver()
19
+ output,
20
+ query,
21
+ mutation,
22
+ infinite,
23
+ suspense,
24
+ paramsCasing,
25
+ paramsType,
26
+ pathParamsType,
27
+ parser,
28
+ client: clientOptions,
29
+ group,
30
+ customOptions,
31
+ } = ctx.options
23
32
 
24
- const oas = useOas()
25
- const { getSchemas, getName, getFile } = useOperationManager(generator)
33
+ const pluginTs = driver.getPlugin(pluginTsName)
34
+ if (!pluginTs) return null
35
+ const tsResolver = driver.getResolver(pluginTsName)
26
36
 
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
- )
31
- const isSuspense = !!options.suspense
32
- const infiniteOptions = options.infinite && typeof options.infinite === 'object' ? options.infinite : undefined
37
+ const isQuery = query === false || (!!query && query.methods.some((method) => node.method.toLowerCase() === method.toLowerCase()))
38
+ const isMutation =
39
+ mutation !== false &&
40
+ !isQuery &&
41
+ difference(mutation ? mutation.methods : [], query ? query.methods : []).some((method) => node.method.toLowerCase() === method.toLowerCase())
42
+ const isSuspense = !!suspense
43
+ const infiniteOptions = infinite && typeof infinite === 'object' ? infinite : undefined
33
44
 
34
- const importPath = options.query ? options.query.importPath : '@tanstack/react-query'
45
+ if (!isQuery || isMutation || !isSuspense || !infiniteOptions) return null
35
46
 
36
- const query = {
37
- name: getName(operation, { type: 'function', prefix: 'use', suffix: 'suspenseInfinite' }),
38
- typeName: getName(operation, { type: 'type' }),
39
- file: getFile(operation, { prefix: 'use', suffix: 'suspenseInfinite' }),
40
- }
47
+ // Validate queryParam exists in operation's query parameters
48
+ const normalizeKey = (key: string) => key.replace(/\?$/, '')
49
+ const queryParamKeys = getOperationParameters(node).query.map((p) => p.name)
50
+ const hasQueryParam = infiniteOptions.queryParam ? queryParamKeys.some((k) => normalizeKey(k) === infiniteOptions.queryParam) : false
51
+ const hasCursorParam = !infiniteOptions.cursorParam || true
41
52
 
42
- const hasClientPlugin = !!driver.getPluginByName(pluginClientName)
43
- // Class-based clients are not compatible with query hooks, so we generate inline clients
44
- const shouldUseClientPlugin = hasClientPlugin && options.client.clientType !== 'class'
45
- const client = {
46
- name: shouldUseClientPlugin
47
- ? getName(operation, {
48
- type: 'function',
49
- pluginName: pluginClientName,
50
- })
51
- : getName(operation, {
52
- type: 'function',
53
- suffix: 'suspenseInfinite',
54
- }),
55
- file: getFile(operation, { pluginName: pluginClientName }),
56
- }
53
+ if (!hasQueryParam || !hasCursorParam) return null
57
54
 
58
- const queryOptions = {
59
- name: getName(operation, { type: 'function', suffix: 'SuspenseInfiniteQueryOptions' }),
60
- }
55
+ const importPath = query ? query.importPath : '@tanstack/react-query'
61
56
 
62
- const queryKey = {
63
- name: getName(operation, { type: 'const', suffix: 'SuspenseInfiniteQueryKey' }),
64
- typeName: getName(operation, { type: 'type', suffix: 'SuspenseInfiniteQueryKey' }),
65
- }
57
+ const queryName = resolver.resolveSuspenseInfiniteQueryName(node)
58
+ const queryOptionsName = resolver.resolveSuspenseInfiniteQueryOptionsName(node)
59
+ const queryKeyName = resolver.resolveSuspenseInfiniteQueryKeyName(node)
60
+ const queryKeyTypeName = resolver.resolveSuspenseInfiniteQueryKeyTypeName(node)
61
+ const clientBaseName = resolver.resolveSuspenseInfiniteClientName(node)
66
62
 
67
- const type = {
68
- file: getFile(operation, { pluginName: pluginTsName }),
69
- //todo remove type?
70
- schemas: getSchemas(operation, { pluginName: pluginTsName, type: 'type' }),
63
+ const meta = {
64
+ file: resolver.resolveFile({ name: queryName, extname: '.ts', tag: node.tags[0] ?? 'default', path: node.path }, { root, output, group }),
65
+ fileTs: tsResolver.resolveFile(
66
+ { name: node.operationId, extname: '.ts', tag: node.tags[0] ?? 'default', path: node.path },
67
+ { root, output: pluginTs.options?.output ?? output, group: pluginTs.options?.group },
68
+ ),
71
69
  }
72
70
 
73
- const zod = {
74
- file: getFile(operation, { pluginName: pluginZodName }),
75
- schemas: getSchemas(operation, { pluginName: pluginZodName, type: 'function' }),
76
- }
71
+ const importedTypeNames = resolveOperationTypeNames(node, tsResolver, { paramsCasing, order: 'body-response-first' })
77
72
 
78
- if (!isQuery || isMutation || !isSuspense || !infiniteOptions) {
79
- return null
80
- }
73
+ const pluginZod = parser === 'zod' ? driver.getPlugin(pluginZodName) : undefined
74
+ const zodResolver = pluginZod ? driver.getResolver(pluginZodName) : undefined
75
+ const fileZod = zodResolver
76
+ ? zodResolver.resolveFile(
77
+ { name: node.operationId, extname: '.ts', tag: node.tags[0] ?? 'default', path: node.path },
78
+ { root, output: pluginZod?.options?.output ?? output, group: pluginZod?.options?.group },
79
+ )
80
+ : undefined
81
+ const zodSchemaNames = resolveZodSchemaNames(node, zodResolver)
82
+
83
+ const clientPlugin = driver.getPlugin(pluginClientName)
84
+ const hasClientPlugin = clientPlugin?.name === pluginClientName
85
+ const shouldUseClientPlugin = hasClientPlugin && clientOptions.clientType !== 'class'
86
+ const clientResolver = shouldUseClientPlugin ? driver.getResolver(pluginClientName) : undefined
87
+
88
+ const clientFile = shouldUseClientPlugin
89
+ ? clientResolver?.resolveFile(
90
+ { name: node.operationId, extname: '.ts', tag: node.tags[0] ?? 'default', path: node.path },
91
+ {
92
+ root,
93
+ output: clientPlugin?.options?.output ?? output,
94
+ group: clientPlugin?.options?.group,
95
+ },
96
+ )
97
+ : undefined
98
+
99
+ const resolvedClientName = shouldUseClientPlugin ? (clientResolver?.resolveName(node.operationId) ?? clientBaseName) : clientBaseName
81
100
 
82
101
  return (
83
102
  <File
84
- baseName={query.file.baseName}
85
- path={query.file.path}
86
- meta={query.file.meta}
87
- banner={getBanner({ oas, output, config: driver.config })}
88
- footer={getFooter({ oas, output })}
103
+ baseName={meta.file.baseName}
104
+ path={meta.file.path}
105
+ meta={meta.file.meta}
106
+ banner={resolver.resolveBanner(adapter.inputNode, { output, config })}
107
+ footer={resolver.resolveFooter(adapter.inputNode, { output, config })}
89
108
  >
90
- {options.parser === 'zod' && (
91
- <File.Import name={[zod.schemas.response.name, zod.schemas.request?.name].filter(Boolean)} root={query.file.path} path={zod.file.path} />
92
- )}
93
- {options.client.importPath ? (
109
+ {fileZod && zodSchemaNames.length > 0 && <File.Import name={zodSchemaNames} root={meta.file.path} path={fileZod.path} />}
110
+ {clientOptions.importPath ? (
94
111
  <>
95
- {!shouldUseClientPlugin && <File.Import name={'fetch'} path={options.client.importPath} />}
96
- <File.Import name={['Client', 'RequestConfig', 'ResponseErrorConfig']} path={options.client.importPath} isTypeOnly />
97
- {options.client.dataReturnType === 'full' && <File.Import name={['ResponseConfig']} path={options.client.importPath} isTypeOnly />}
112
+ {!shouldUseClientPlugin && <File.Import name={'fetch'} path={clientOptions.importPath} />}
113
+ <File.Import name={['Client', 'RequestConfig', 'ResponseErrorConfig']} path={clientOptions.importPath} isTypeOnly />
114
+ {clientOptions.dataReturnType === 'full' && <File.Import name={['ResponseConfig']} path={clientOptions.importPath} isTypeOnly />}
98
115
  </>
99
116
  ) : (
100
117
  <>
101
- {!shouldUseClientPlugin && (
102
- <File.Import name={['fetch']} root={query.file.path} path={path.resolve(config.root, config.output.path, '.kubb/fetch.ts')} />
103
- )}
118
+ {!shouldUseClientPlugin && <File.Import name={['fetch']} root={meta.file.path} path={path.resolve(root, '.kubb/fetch.ts')} />}
104
119
  <File.Import
105
120
  name={['Client', 'RequestConfig', 'ResponseErrorConfig']}
106
- root={query.file.path}
107
- path={path.resolve(config.root, config.output.path, '.kubb/fetch.ts')}
121
+ root={meta.file.path}
122
+ path={path.resolve(root, '.kubb/fetch.ts')}
108
123
  isTypeOnly
109
124
  />
110
- {options.client.dataReturnType === 'full' && (
111
- <File.Import name={['ResponseConfig']} root={query.file.path} path={path.resolve(config.root, config.output.path, '.kubb/fetch.ts')} isTypeOnly />
125
+ {clientOptions.dataReturnType === 'full' && (
126
+ <File.Import name={['ResponseConfig']} root={meta.file.path} path={path.resolve(root, '.kubb/fetch.ts')} isTypeOnly />
112
127
  )}
113
128
  </>
114
129
  )}
115
-
116
- {shouldUseClientPlugin && <File.Import name={[client.name]} root={query.file.path} path={client.file.path} />}
117
- {!shouldUseClientPlugin && (
118
- <File.Import name={['buildFormData']} root={query.file.path} path={path.resolve(config.root, config.output.path, '.kubb/config.ts')} />
130
+ {shouldUseClientPlugin && clientFile && <File.Import name={[resolvedClientName]} root={meta.file.path} path={clientFile.path} />}
131
+ {!shouldUseClientPlugin && <File.Import name={['buildFormData']} root={meta.file.path} path={path.resolve(root, '.kubb/config.ts')} />}
132
+ {customOptions && <File.Import name={[customOptions.name]} path={customOptions.importPath} />}
133
+ {meta.fileTs && importedTypeNames.length > 0 && (
134
+ <File.Import name={Array.from(new Set(importedTypeNames))} root={meta.file.path} path={meta.fileTs.path} isTypeOnly />
119
135
  )}
120
- {options.customOptions && <File.Import name={[options.customOptions.name]} path={options.customOptions.importPath} />}
121
- <File.Import
122
- name={[
123
- type.schemas.request?.name,
124
- type.schemas.response.name,
125
- type.schemas.pathParams?.name,
126
- type.schemas.queryParams?.name,
127
- type.schemas.headerParams?.name,
128
- ...(type.schemas.statusCodes?.map((item) => item.name) || []),
129
- ].filter(Boolean)}
130
- root={query.file.path}
131
- path={type.file.path}
132
- isTypeOnly
133
- />
136
+
134
137
  <QueryKey
135
- name={queryKey.name}
136
- typeName={queryKey.typeName}
137
- operation={operation}
138
- paramsCasing={options.paramsCasing}
139
- pathParamsType={options.pathParamsType}
140
- typeSchemas={type.schemas}
141
- transformer={options.queryKey}
138
+ name={queryKeyName}
139
+ typeName={queryKeyTypeName}
140
+ node={node}
141
+ tsResolver={tsResolver}
142
+ pathParamsType={pathParamsType}
143
+ paramsCasing={paramsCasing}
144
+ transformer={ctx.options.queryKey}
142
145
  />
146
+
143
147
  {!shouldUseClientPlugin && (
144
148
  <Client
145
- name={client.name}
146
- baseURL={options.client.baseURL}
147
- operation={operation}
148
- typeSchemas={type.schemas}
149
- zodSchemas={zod.schemas}
150
- dataReturnType={options.client.dataReturnType || 'data'}
151
- paramsCasing={options.client?.paramsCasing || options.paramsCasing}
152
- paramsType={options.paramsType}
153
- pathParamsType={options.pathParamsType}
154
- parser={options.parser}
149
+ name={resolvedClientName}
150
+ baseURL={clientOptions.baseURL}
151
+ dataReturnType={clientOptions.dataReturnType || 'data'}
152
+ paramsCasing={clientOptions.paramsCasing || paramsCasing}
153
+ paramsType={paramsType}
154
+ pathParamsType={pathParamsType}
155
+ parser={parser}
156
+ node={node}
157
+ tsResolver={tsResolver}
158
+ zodResolver={zodResolver}
155
159
  />
156
160
  )}
157
- {infiniteOptions && (
158
- <>
159
- <File.Import name={['InfiniteData']} isTypeOnly path={importPath} />
160
- <File.Import name={['infiniteQueryOptions']} path={importPath} />
161
- <SuspenseInfiniteQueryOptions
162
- name={queryOptions.name}
163
- clientName={client.name}
164
- queryKeyName={queryKey.name}
165
- typeSchemas={type.schemas}
166
- paramsCasing={options.paramsCasing}
167
- paramsType={options.paramsType}
168
- pathParamsType={options.pathParamsType}
169
- dataReturnType={options.client.dataReturnType || 'data'}
170
- cursorParam={infiniteOptions.cursorParam}
171
- nextParam={infiniteOptions.nextParam}
172
- previousParam={infiniteOptions.previousParam}
173
- initialPageParam={infiniteOptions.initialPageParam}
174
- queryParam={infiniteOptions.queryParam}
175
- />
176
- </>
177
- )}
178
- {infiniteOptions && (
179
- <>
180
- <File.Import name={['useSuspenseInfiniteQuery']} path={importPath} />
181
- <File.Import name={['QueryKey', 'QueryClient', 'UseSuspenseInfiniteQueryOptions', 'UseSuspenseInfiniteQueryResult']} path={importPath} isTypeOnly />
182
- <SuspenseInfiniteQuery
183
- name={query.name}
184
- queryOptionsName={queryOptions.name}
185
- typeSchemas={type.schemas}
186
- paramsCasing={options.paramsCasing}
187
- paramsType={options.paramsType}
188
- pathParamsType={options.pathParamsType}
189
- operation={operation}
190
- dataReturnType={options.client.dataReturnType || 'data'}
191
- queryKeyName={queryKey.name}
192
- queryKeyTypeName={queryKey.typeName}
193
- customOptions={options.customOptions}
194
- initialPageParam={infiniteOptions.initialPageParam}
195
- queryParam={infiniteOptions.queryParam}
196
- />
197
- </>
198
- )}
161
+
162
+ <File.Import name={['InfiniteData']} isTypeOnly path={importPath} />
163
+ <File.Import name={['infiniteQueryOptions']} path={importPath} />
164
+
165
+ <SuspenseInfiniteQueryOptions
166
+ name={queryOptionsName}
167
+ clientName={resolvedClientName}
168
+ queryKeyName={queryKeyName}
169
+ node={node}
170
+ tsResolver={tsResolver}
171
+ paramsCasing={paramsCasing}
172
+ paramsType={paramsType}
173
+ pathParamsType={pathParamsType}
174
+ dataReturnType={clientOptions.dataReturnType || 'data'}
175
+ cursorParam={infiniteOptions.cursorParam}
176
+ nextParam={infiniteOptions.nextParam}
177
+ previousParam={infiniteOptions.previousParam}
178
+ initialPageParam={infiniteOptions.initialPageParam}
179
+ queryParam={infiniteOptions.queryParam}
180
+ />
181
+
182
+ <File.Import name={['useSuspenseInfiniteQuery']} path={importPath} />
183
+ <File.Import name={['QueryKey', 'QueryClient', 'UseSuspenseInfiniteQueryOptions', 'UseSuspenseInfiniteQueryResult']} path={importPath} isTypeOnly />
184
+
185
+ <SuspenseInfiniteQuery
186
+ name={queryName}
187
+ queryOptionsName={queryOptionsName}
188
+ queryKeyName={queryKeyName}
189
+ queryKeyTypeName={queryKeyTypeName}
190
+ node={node}
191
+ tsResolver={tsResolver}
192
+ paramsCasing={paramsCasing}
193
+ paramsType={paramsType}
194
+ pathParamsType={pathParamsType}
195
+ dataReturnType={clientOptions.dataReturnType || 'data'}
196
+ initialPageParam={infiniteOptions.initialPageParam}
197
+ queryParam={infiniteOptions.queryParam}
198
+ customOptions={customOptions}
199
+ />
199
200
  </File>
200
201
  )
201
202
  },