@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
package/src/plugin.ts CHANGED
@@ -1,15 +1,13 @@
1
1
  import path from 'node:path'
2
- import { camelCase, pascalCase } from '@internals/utils'
3
- import { createPlugin, type Group, getBarrelFiles, getMode } from '@kubb/core'
2
+ import { camelCase } from '@internals/utils'
3
+ import { ast, definePlugin, type Group } from '@kubb/core'
4
4
  import { pluginClientName } from '@kubb/plugin-client'
5
5
  import { source as axiosClientSource } from '@kubb/plugin-client/templates/clients/axios.source'
6
6
  import { source as fetchClientSource } from '@kubb/plugin-client/templates/clients/fetch.source'
7
7
  import { source as configSource } from '@kubb/plugin-client/templates/config.source'
8
- import { OperationGenerator, pluginOasName } from '@kubb/plugin-oas'
9
8
  import { pluginTsName } from '@kubb/plugin-ts'
10
9
  import { pluginZodName } from '@kubb/plugin-zod'
11
- import { MutationKey } from './components'
12
- import { QueryKey } from './components/QueryKey.tsx'
10
+ import { mutationKeyTransformer, queryKeyTransformer } from '@internals/tanstack-query'
13
11
  import {
14
12
  customHookOptionsFileGenerator,
15
13
  hookOptionsGenerator,
@@ -19,11 +17,12 @@ import {
19
17
  suspenseInfiniteQueryGenerator,
20
18
  suspenseQueryGenerator,
21
19
  } from './generators'
20
+ import { resolverReactQuery } from './resolvers/resolverReactQuery.ts'
22
21
  import type { PluginReactQuery } from './types.ts'
23
22
 
24
23
  export const pluginReactQueryName = 'plugin-react-query' satisfies PluginReactQuery['name']
25
24
 
26
- export const pluginReactQuery = createPlugin<PluginReactQuery>((options) => {
25
+ export const pluginReactQuery = definePlugin<PluginReactQuery>((options) => {
27
26
  const {
28
27
  output = { path: 'hooks', barrelType: 'named' },
29
28
  group,
@@ -33,207 +32,155 @@ export const pluginReactQuery = createPlugin<PluginReactQuery>((options) => {
33
32
  parser = 'client',
34
33
  suspense = {},
35
34
  infinite = false,
36
- transformers = {},
37
35
  paramsType = 'inline',
38
36
  pathParamsType = paramsType === 'object' ? 'object' : options.pathParamsType || 'inline',
39
- generators = [
40
- queryGenerator,
41
- suspenseQueryGenerator,
42
- infiniteQueryGenerator,
43
- suspenseInfiniteQueryGenerator,
44
- mutationGenerator,
45
- hookOptionsGenerator,
46
- customHookOptionsFileGenerator,
47
- ].filter(Boolean),
48
37
  mutation = {},
49
38
  query = {},
50
- mutationKey = MutationKey.getTransformer,
51
- queryKey = QueryKey.getTransformer,
39
+ mutationKey = mutationKeyTransformer,
40
+ queryKey = queryKeyTransformer,
52
41
  customOptions,
53
42
  paramsCasing,
54
- contentType,
55
43
  client,
44
+ resolver: userResolver,
45
+ transformer: userTransformer,
46
+ generators: userGenerators = [],
56
47
  } = options
57
48
 
58
49
  const clientName = client?.client ?? 'axios'
59
50
  const clientImportPath = client?.importPath ?? (!client?.bundle ? `@kubb/plugin-client/clients/${clientName}` : undefined)
60
51
 
61
- return {
62
- name: pluginReactQueryName,
63
- options: {
64
- output,
65
- client: {
66
- bundle: client?.bundle,
67
- baseURL: client?.baseURL,
68
- client: clientName,
69
- clientType: client?.clientType ?? 'function',
70
- dataReturnType: client?.dataReturnType ?? 'data',
71
- pathParamsType,
72
- importPath: clientImportPath,
73
- paramsCasing,
74
- },
75
- infinite: infinite
76
- ? {
77
- queryParam: 'id',
78
- initialPageParam: 0,
79
- cursorParam: undefined,
80
- nextParam: undefined,
81
- previousParam: undefined,
82
- ...infinite,
83
- }
84
- : false,
85
- suspense,
86
- queryKey,
87
- query:
88
- query === false
89
- ? false
90
- : {
91
- methods: ['get'],
92
- importPath: '@tanstack/react-query',
93
- ...query,
94
- },
95
- mutationKey,
96
- mutation:
97
- mutation === false
98
- ? false
99
- : {
100
- methods: ['post', 'put', 'patch', 'delete'],
101
- importPath: '@tanstack/react-query',
102
- ...mutation,
103
- },
104
- customOptions: customOptions ? { name: 'useCustomHookOptions', ...customOptions } : undefined,
105
- paramsType,
106
- pathParamsType,
107
- parser,
108
- paramsCasing,
109
- group,
110
- },
111
- pre: [pluginOasName, pluginTsName, parser === 'zod' ? pluginZodName : undefined].filter(Boolean),
112
- resolvePath(baseName, pathMode, options) {
113
- const root = path.resolve(this.config.root, this.config.output.path)
114
- const mode = pathMode ?? getMode(path.resolve(root, output.path))
115
-
116
- if (mode === 'single') {
117
- /**
118
- * when output is a file then we will always append to the same file(output file), see fileManager.addOrAppend
119
- * Other plugins then need to call addOrAppend instead of just add from the fileManager class
120
- */
121
- return path.resolve(root, output.path)
122
- }
52
+ const selectedGenerators =
53
+ options.generators ??
54
+ [
55
+ queryGenerator,
56
+ suspenseQueryGenerator,
57
+ infiniteQueryGenerator,
58
+ suspenseInfiniteQueryGenerator,
59
+ mutationGenerator,
60
+ hookOptionsGenerator,
61
+ customHookOptionsFileGenerator,
62
+ ].filter((generator): generator is NonNullable<typeof generator> => Boolean(generator))
123
63
 
124
- if (group && (options?.group?.path || options?.group?.tag)) {
125
- const groupName: Group['name'] = group?.name
64
+ const groupConfig = group
65
+ ? ({
66
+ ...group,
67
+ name: group.name
126
68
  ? group.name
127
- : (ctx) => {
128
- if (group?.type === 'path') {
69
+ : (ctx: { group: string }) => {
70
+ if (group.type === 'path') {
129
71
  return `${ctx.group.split('/')[1]}`
130
72
  }
131
73
  return `${camelCase(ctx.group)}Controller`
132
- }
133
-
134
- return path.resolve(
135
- root,
136
- output.path,
137
- groupName({
138
- group: group.type === 'path' ? options.group.path! : options.group.tag!,
139
- }),
140
- baseName,
141
- )
142
- }
143
-
144
- return path.resolve(root, output.path, baseName)
145
- },
146
- resolveName(name, type) {
147
- let resolvedName = camelCase(name)
148
-
149
- if (type === 'file' || type === 'function') {
150
- resolvedName = camelCase(name, {
151
- isFile: type === 'file',
152
- })
153
- }
154
- if (type === 'type') {
155
- resolvedName = pascalCase(name)
156
- }
157
-
158
- if (type) {
159
- return transformers?.name?.(resolvedName, type) || resolvedName
160
- }
161
-
162
- return resolvedName
163
- },
164
- async install() {
165
- const root = path.resolve(this.config.root, this.config.output.path)
166
- const mode = getMode(path.resolve(root, output.path))
167
- const oas = await this.getOas()
168
- const baseURL = await this.getBaseURL()
169
-
170
- if (baseURL) {
171
- this.plugin.options.client.baseURL = baseURL
172
- }
173
-
174
- const hasClientPlugin = !!this.driver.getPluginByName(pluginClientName)
175
-
176
- if (this.plugin.options.client.bundle && !hasClientPlugin && !this.plugin.options.client.importPath) {
177
- // pre add bundled fetch
178
- await this.upsertFile({
179
- baseName: 'fetch.ts',
180
- path: path.resolve(root, '.kubb/fetch.ts'),
181
- sources: [
182
- {
183
- name: 'fetch',
184
- value: this.plugin.options.client.client === 'fetch' ? fetchClientSource : axiosClientSource,
185
- isExportable: true,
186
- isIndexable: true,
187
74
  },
188
- ],
189
- imports: [],
190
- exports: [],
191
- })
192
- }
75
+ } satisfies Group)
76
+ : undefined
193
77
 
194
- if (!hasClientPlugin) {
195
- await this.upsertFile({
196
- baseName: 'config.ts',
197
- path: path.resolve(root, '.kubb/config.ts'),
198
- sources: [
199
- {
200
- name: 'config',
201
- value: configSource,
202
- isExportable: false,
203
- isIndexable: false,
204
- },
205
- ],
206
- imports: [],
207
- exports: [],
78
+ return {
79
+ name: pluginReactQueryName,
80
+ options,
81
+ dependencies: [pluginTsName, parser === 'zod' ? pluginZodName : undefined].filter((dependency): dependency is string => Boolean(dependency)),
82
+ hooks: {
83
+ 'kubb:plugin:setup'(ctx) {
84
+ const resolver = userResolver ? { ...resolverReactQuery, ...userResolver } : resolverReactQuery
85
+
86
+ ctx.setOptions({
87
+ output,
88
+ client: {
89
+ bundle: client?.bundle,
90
+ baseURL: client?.baseURL,
91
+ client: clientName,
92
+ clientType: client?.clientType ?? 'function',
93
+ importPath: clientImportPath,
94
+ dataReturnType: client?.dataReturnType ?? 'data',
95
+ paramsCasing,
96
+ },
97
+ queryKey,
98
+ query:
99
+ query === false
100
+ ? false
101
+ : {
102
+ importPath: '@tanstack/react-query',
103
+ methods: ['get'],
104
+ ...query,
105
+ },
106
+ mutationKey,
107
+ mutation:
108
+ mutation === false
109
+ ? false
110
+ : {
111
+ importPath: '@tanstack/react-query',
112
+ methods: ['post', 'put', 'patch', 'delete'],
113
+ ...mutation,
114
+ },
115
+ infinite: infinite
116
+ ? {
117
+ queryParam: 'id',
118
+ initialPageParam: 0,
119
+ cursorParam: undefined,
120
+ nextParam: undefined,
121
+ previousParam: undefined,
122
+ ...infinite,
123
+ }
124
+ : false,
125
+ suspense,
126
+ customOptions: customOptions ? { name: 'useCustomHookOptions', ...customOptions } : undefined,
127
+ parser,
128
+ paramsType,
129
+ pathParamsType,
130
+ paramsCasing,
131
+ group: groupConfig,
132
+ exclude,
133
+ include,
134
+ override,
135
+ resolver,
208
136
  })
209
- }
210
-
211
- const operationGenerator = new OperationGenerator(this.plugin.options, {
212
- fabric: this.fabric,
213
- oas,
214
- driver: this.driver,
215
- events: this.events,
216
- plugin: this.plugin,
217
- contentType,
218
- exclude,
219
- include,
220
- override,
221
- mode,
222
- })
223
-
224
- const files = await operationGenerator.build(...generators)
225
- await this.upsertFile(...files)
226
-
227
- const barrelFiles = await getBarrelFiles(this.fabric.files, {
228
- type: output.barrelType ?? 'named',
229
- root,
230
- output,
231
- meta: {
232
- pluginName: this.plugin.name,
233
- },
234
- })
235
-
236
- await this.upsertFile(...barrelFiles)
137
+ ctx.setResolver(resolver)
138
+ if (userTransformer) {
139
+ ctx.setTransformer(userTransformer)
140
+ }
141
+
142
+ for (const gen of selectedGenerators) {
143
+ ctx.addGenerator(gen)
144
+ }
145
+ for (const gen of userGenerators) {
146
+ ctx.addGenerator(gen)
147
+ }
148
+
149
+ const root = path.resolve(ctx.config.root, ctx.config.output.path)
150
+ const hasClientPlugin = !!ctx.config.plugins?.some((p) => (p as { name?: string }).name === pluginClientName)
151
+
152
+ if (client?.bundle && !hasClientPlugin && !clientImportPath) {
153
+ ctx.injectFile({
154
+ baseName: 'fetch.ts',
155
+ path: path.resolve(root, '.kubb/fetch.ts'),
156
+ sources: [
157
+ ast.createSource({
158
+ name: 'fetch',
159
+ nodes: [ast.createText(clientName === 'fetch' ? fetchClientSource : axiosClientSource)],
160
+ isExportable: true,
161
+ isIndexable: true,
162
+ }),
163
+ ],
164
+ })
165
+ }
166
+
167
+ if (!hasClientPlugin) {
168
+ ctx.injectFile({
169
+ baseName: 'config.ts',
170
+ path: path.resolve(root, '.kubb/config.ts'),
171
+ sources: [
172
+ ast.createSource({
173
+ name: 'config',
174
+ nodes: [ast.createText(configSource)],
175
+ isExportable: false,
176
+ isIndexable: false,
177
+ }),
178
+ ],
179
+ })
180
+ }
181
+ },
237
182
  },
238
183
  }
239
184
  })
185
+
186
+ export default pluginReactQuery
@@ -0,0 +1,107 @@
1
+ import { camelCase } from '@internals/utils'
2
+ import { defineResolver } from '@kubb/core'
3
+ import type { PluginReactQuery } from '../types.ts'
4
+
5
+ function capitalize(name: string): string {
6
+ return `${name.charAt(0).toUpperCase()}${name.slice(1)}`
7
+ }
8
+
9
+ /**
10
+ * Naming convention resolver for React Query plugin.
11
+ *
12
+ * Provides default naming helpers using camelCase for functions and file paths.
13
+ *
14
+ * @example
15
+ * `resolverReactQuery.default('list pets', 'function') // → 'listPets'`
16
+ */
17
+ export const resolverReactQuery = defineResolver<PluginReactQuery>(() => ({
18
+ name: 'default',
19
+ pluginName: 'plugin-react-query',
20
+ default(name, type) {
21
+ return camelCase(name, { isFile: type === 'file' })
22
+ },
23
+ resolveName(name) {
24
+ return this.default(name, 'function')
25
+ },
26
+ resolvePathName(name, type) {
27
+ return this.default(name, type)
28
+ },
29
+ resolveQueryName(node) {
30
+ return `use${capitalize(this.resolveName(node.operationId))}`
31
+ },
32
+ resolveSuspenseQueryName(node) {
33
+ return `use${capitalize(this.resolveName(node.operationId))}Suspense`
34
+ },
35
+ resolveInfiniteQueryName(node) {
36
+ return `use${capitalize(this.resolveName(node.operationId))}Infinite`
37
+ },
38
+ resolveSuspenseInfiniteQueryName(node) {
39
+ return `use${capitalize(this.resolveName(node.operationId))}SuspenseInfinite`
40
+ },
41
+ resolveMutationName(node) {
42
+ return `use${capitalize(this.resolveName(node.operationId))}`
43
+ },
44
+ resolveQueryOptionsName(node) {
45
+ return `${this.resolveName(node.operationId)}QueryOptions`
46
+ },
47
+ resolveSuspenseQueryOptionsName(node) {
48
+ return `${this.resolveName(node.operationId)}SuspenseQueryOptions`
49
+ },
50
+ resolveInfiniteQueryOptionsName(node) {
51
+ return `${this.resolveName(node.operationId)}InfiniteQueryOptions`
52
+ },
53
+ resolveSuspenseInfiniteQueryOptionsName(node) {
54
+ return `${this.resolveName(node.operationId)}SuspenseInfiniteQueryOptions`
55
+ },
56
+ resolveMutationOptionsName(node) {
57
+ return `${this.resolveName(node.operationId)}MutationOptions`
58
+ },
59
+ resolveQueryKeyName(node) {
60
+ return `${this.resolveName(node.operationId)}QueryKey`
61
+ },
62
+ resolveSuspenseQueryKeyName(node) {
63
+ return `${this.resolveName(node.operationId)}SuspenseQueryKey`
64
+ },
65
+ resolveInfiniteQueryKeyName(node) {
66
+ return `${this.resolveName(node.operationId)}InfiniteQueryKey`
67
+ },
68
+ resolveSuspenseInfiniteQueryKeyName(node) {
69
+ return `${this.resolveName(node.operationId)}SuspenseInfiniteQueryKey`
70
+ },
71
+ resolveMutationKeyName(node) {
72
+ return `${this.resolveName(node.operationId)}MutationKey`
73
+ },
74
+ resolveQueryKeyTypeName(node) {
75
+ return `${capitalize(this.resolveName(node.operationId))}QueryKey`
76
+ },
77
+ resolveSuspenseQueryKeyTypeName(node) {
78
+ return `${capitalize(this.resolveName(node.operationId))}SuspenseQueryKey`
79
+ },
80
+ resolveInfiniteQueryKeyTypeName(node) {
81
+ return `${capitalize(this.resolveName(node.operationId))}InfiniteQueryKey`
82
+ },
83
+ resolveSuspenseInfiniteQueryKeyTypeName(node) {
84
+ return `${capitalize(this.resolveName(node.operationId))}SuspenseInfiniteQueryKey`
85
+ },
86
+ resolveMutationTypeName(node) {
87
+ return capitalize(this.resolveName(node.operationId))
88
+ },
89
+ resolveClientName(node) {
90
+ return this.resolveName(node.operationId)
91
+ },
92
+ resolveSuspenseClientName(node) {
93
+ return `${this.resolveName(node.operationId)}Suspense`
94
+ },
95
+ resolveInfiniteClientName(node) {
96
+ return `${this.resolveName(node.operationId)}Infinite`
97
+ },
98
+ resolveSuspenseInfiniteClientName(node) {
99
+ return `${this.resolveName(node.operationId)}SuspenseInfinite`
100
+ },
101
+ resolveHookOptionsName() {
102
+ return 'HookOptions'
103
+ },
104
+ resolveCustomHookOptionsName() {
105
+ return 'getCustomHookOptions'
106
+ },
107
+ }))