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

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 (52) 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/package.json +59 -62
  24. package/src/components/InfiniteQuery.tsx +75 -139
  25. package/src/components/InfiniteQueryOptions.tsx +62 -164
  26. package/src/components/Mutation.tsx +58 -113
  27. package/src/components/MutationOptions.tsx +61 -80
  28. package/src/components/Query.tsx +67 -140
  29. package/src/components/QueryOptions.tsx +75 -135
  30. package/src/components/SuspenseInfiniteQuery.tsx +75 -139
  31. package/src/components/SuspenseInfiniteQueryOptions.tsx +62 -164
  32. package/src/components/SuspenseQuery.tsx +67 -150
  33. package/src/generators/customHookOptionsFileGenerator.tsx +33 -45
  34. package/src/generators/hookOptionsGenerator.tsx +115 -175
  35. package/src/generators/infiniteQueryGenerator.tsx +183 -176
  36. package/src/generators/mutationGenerator.tsx +127 -138
  37. package/src/generators/queryGenerator.tsx +141 -141
  38. package/src/generators/suspenseInfiniteQueryGenerator.tsx +175 -155
  39. package/src/generators/suspenseQueryGenerator.tsx +149 -148
  40. package/src/index.ts +1 -1
  41. package/src/plugin.ts +133 -183
  42. package/src/resolvers/resolverReactQuery.ts +22 -0
  43. package/src/types.ts +67 -45
  44. package/src/utils.ts +40 -0
  45. package/dist/components-BHQT9ZLc.cjs +0 -1634
  46. package/dist/components-BHQT9ZLc.cjs.map +0 -1
  47. package/dist/components-CpyHYGOw.js +0 -1520
  48. package/dist/components-CpyHYGOw.js.map +0 -1
  49. package/dist/generators-DP07m3rH.cjs +0 -1469
  50. package/dist/generators-DP07m3rH.cjs.map +0 -1
  51. package/dist/generators-DkQwKTc2.js +0 -1427
  52. package/dist/generators-DkQwKTc2.js.map +0 -1
package/src/plugin.ts CHANGED
@@ -1,14 +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'
10
+ import { MutationKey } from './components/MutationKey.tsx'
12
11
  import { QueryKey } from './components/QueryKey.tsx'
13
12
  import {
14
13
  customHookOptionsFileGenerator,
@@ -19,11 +18,12 @@ import {
19
18
  suspenseInfiniteQueryGenerator,
20
19
  suspenseQueryGenerator,
21
20
  } from './generators'
21
+ import { resolverReactQuery } from './resolvers/resolverReactQuery.ts'
22
22
  import type { PluginReactQuery } from './types.ts'
23
23
 
24
24
  export const pluginReactQueryName = 'plugin-react-query' satisfies PluginReactQuery['name']
25
25
 
26
- export const pluginReactQuery = createPlugin<PluginReactQuery>((options) => {
26
+ export const pluginReactQuery = definePlugin<PluginReactQuery>((options) => {
27
27
  const {
28
28
  output = { path: 'hooks', barrelType: 'named' },
29
29
  group,
@@ -36,204 +36,154 @@ export const pluginReactQuery = createPlugin<PluginReactQuery>((options) => {
36
36
  transformers = {},
37
37
  paramsType = 'inline',
38
38
  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
39
  mutation = {},
49
40
  query = {},
50
41
  mutationKey = MutationKey.getTransformer,
51
42
  queryKey = QueryKey.getTransformer,
52
43
  customOptions,
53
44
  paramsCasing,
54
- contentType,
55
45
  client,
46
+ resolver: userResolver,
47
+ transformer: userTransformer,
48
+ generators: userGenerators = [],
56
49
  } = options
57
50
 
58
51
  const clientName = client?.client ?? 'axios'
59
52
  const clientImportPath = client?.importPath ?? (!client?.bundle ? `@kubb/plugin-client/clients/${clientName}` : undefined)
60
53
 
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
- }
54
+ const selectedGenerators =
55
+ options.generators ??
56
+ [
57
+ queryGenerator,
58
+ suspenseQueryGenerator,
59
+ infiniteQueryGenerator,
60
+ suspenseInfiniteQueryGenerator,
61
+ mutationGenerator,
62
+ hookOptionsGenerator,
63
+ customHookOptionsFileGenerator,
64
+ ].filter(Boolean)
123
65
 
124
- if (group && (options?.group?.path || options?.group?.tag)) {
125
- const groupName: Group['name'] = group?.name
66
+ const groupConfig = group
67
+ ? ({
68
+ ...group,
69
+ name: group.name
126
70
  ? group.name
127
- : (ctx) => {
128
- if (group?.type === 'path') {
71
+ : (ctx: { group: string }) => {
72
+ if (group.type === 'path') {
129
73
  return `${ctx.group.split('/')[1]}`
130
74
  }
131
75
  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
76
  },
188
- ],
189
- imports: [],
190
- exports: [],
191
- })
192
- }
77
+ } satisfies Group)
78
+ : undefined
193
79
 
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: [],
80
+ return {
81
+ name: pluginReactQueryName,
82
+ options,
83
+ dependencies: [pluginTsName, parser === 'zod' ? pluginZodName : undefined].filter(Boolean),
84
+ hooks: {
85
+ 'kubb:plugin:setup'(ctx) {
86
+ const resolver = userResolver ? { ...resolverReactQuery, ...userResolver } : resolverReactQuery
87
+
88
+ ctx.setOptions({
89
+ output,
90
+ transformers,
91
+ client: {
92
+ bundle: client?.bundle,
93
+ baseURL: client?.baseURL,
94
+ client: clientName,
95
+ clientType: client?.clientType ?? 'function',
96
+ importPath: clientImportPath,
97
+ dataReturnType: client?.dataReturnType ?? 'data',
98
+ paramsCasing,
99
+ },
100
+ queryKey,
101
+ query:
102
+ query === false
103
+ ? false
104
+ : {
105
+ importPath: '@tanstack/react-query',
106
+ methods: ['get'],
107
+ ...query,
108
+ },
109
+ mutationKey,
110
+ mutation:
111
+ mutation === false
112
+ ? false
113
+ : {
114
+ importPath: '@tanstack/react-query',
115
+ methods: ['post', 'put', 'patch', 'delete'],
116
+ ...mutation,
117
+ },
118
+ infinite: infinite
119
+ ? {
120
+ queryParam: 'id',
121
+ initialPageParam: 0,
122
+ cursorParam: undefined,
123
+ nextParam: undefined,
124
+ previousParam: undefined,
125
+ ...infinite,
126
+ }
127
+ : false,
128
+ suspense,
129
+ customOptions: customOptions ? { name: 'useCustomHookOptions', ...customOptions } : undefined,
130
+ parser,
131
+ paramsType,
132
+ pathParamsType,
133
+ paramsCasing,
134
+ group: groupConfig,
135
+ exclude,
136
+ include,
137
+ override,
138
+ resolver,
208
139
  })
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)
140
+ ctx.setResolver(resolver)
141
+ if (userTransformer) {
142
+ ctx.setTransformer(userTransformer)
143
+ }
144
+
145
+ for (const gen of selectedGenerators) {
146
+ ctx.addGenerator(gen)
147
+ }
148
+ for (const gen of userGenerators) {
149
+ ctx.addGenerator(gen)
150
+ }
151
+
152
+ const root = path.resolve(ctx.config.root, ctx.config.output.path)
153
+ const hasClientPlugin = !!ctx.config.plugins?.some((p) => (p as { name?: string }).name === pluginClientName)
154
+
155
+ if (client?.bundle && !hasClientPlugin && !clientImportPath) {
156
+ ctx.injectFile({
157
+ baseName: 'fetch.ts',
158
+ path: path.resolve(root, '.kubb/fetch.ts'),
159
+ sources: [
160
+ ast.createSource({
161
+ name: 'fetch',
162
+ nodes: [ast.createText(clientName === 'fetch' ? fetchClientSource : axiosClientSource)],
163
+ isExportable: true,
164
+ isIndexable: true,
165
+ }),
166
+ ],
167
+ })
168
+ }
169
+
170
+ if (!hasClientPlugin) {
171
+ ctx.injectFile({
172
+ baseName: 'config.ts',
173
+ path: path.resolve(root, '.kubb/config.ts'),
174
+ sources: [
175
+ ast.createSource({
176
+ name: 'config',
177
+ nodes: [ast.createText(configSource)],
178
+ isExportable: false,
179
+ isIndexable: false,
180
+ }),
181
+ ],
182
+ })
183
+ }
184
+ },
237
185
  },
238
186
  }
239
187
  })
188
+
189
+ export default pluginReactQuery
@@ -0,0 +1,22 @@
1
+ import { camelCase } from '@internals/utils'
2
+ import { defineResolver } from '@kubb/core'
3
+ import type { PluginReactQuery } from '../types.ts'
4
+
5
+ /**
6
+ * Naming convention resolver for React Query plugin.
7
+ *
8
+ * Provides default naming helpers using camelCase for functions and file paths.
9
+ *
10
+ * @example
11
+ * `resolverReactQuery.default('list pets', 'function') // → 'listPets'`
12
+ */
13
+ export const resolverReactQuery = defineResolver<PluginReactQuery>((ctx) => ({
14
+ name: 'default',
15
+ pluginName: 'plugin-react-query',
16
+ default(name, type) {
17
+ return camelCase(name, { isFile: type === 'file' })
18
+ },
19
+ resolveName(name) {
20
+ return ctx.default(name, 'function')
21
+ },
22
+ }))
package/src/types.ts CHANGED
@@ -1,30 +1,41 @@
1
1
  import type { Transformer } from '@internals/tanstack-query'
2
- import type { Group, Output, PluginFactoryOptions, ResolveNameParams } from '@kubb/core'
3
- import type { contentType, HttpMethod, Oas } from '@kubb/oas'
2
+ import type { ast, Exclude, Generator, Group, Include, Output, Override, PluginFactoryOptions, Resolver } from '@kubb/core'
4
3
  import type { ClientImportPath, PluginClient } from '@kubb/plugin-client'
5
- import type { Exclude, Include, Override, ResolvePathOptions } from '@kubb/plugin-oas'
6
- import type { Generator } from '@kubb/plugin-oas/generators'
7
4
 
8
5
  export type { Transformer } from '@internals/tanstack-query'
9
6
 
7
+ /**
8
+ * Resolver for React Query that provides naming methods for hook functions.
9
+ */
10
+ export type ResolverReactQuery = Resolver & {
11
+ /**
12
+ * Resolves the hook function name for an operation.
13
+ *
14
+ * @example Resolving hook names
15
+ * `resolver.resolveName('show pet by id') // -> 'showPetById'`
16
+ */
17
+ resolveName(this: ResolverReactQuery, name: string): string
18
+ }
19
+
10
20
  type Suspense = object
11
21
 
12
22
  /**
13
- * Customize the queryKey
23
+ * Customize the queryKey.
14
24
  */
15
25
  type QueryKey = Transformer
16
26
 
17
27
  /**
18
- * Customize the mutationKey
28
+ * Customize the mutationKey.
19
29
  */
20
30
  type MutationKey = Transformer
21
31
 
22
32
  type Query = {
23
33
  /**
24
- * Define which HttpMethods can be used for queries
34
+ * HTTP methods to use for queries.
35
+ *
25
36
  * @default ['get']
26
37
  */
27
- methods: Array<HttpMethod>
38
+ methods?: Array<string>
28
39
  /**
29
40
  * Path to the useQuery hook for useQuery functionality.
30
41
  * Used as `import { useQuery } from '${importPath}'`.
@@ -37,13 +48,14 @@ type Query = {
37
48
 
38
49
  type Mutation = {
39
50
  /**
40
- * Define which HttpMethods can be used for mutations
51
+ * HTTP methods to use for mutations.
52
+ *
41
53
  * @default ['post', 'put', 'delete']
42
54
  */
43
- methods: Array<HttpMethod>
55
+ methods?: Array<string>
44
56
  /**
45
- * Path to the useQuery hook for useQuery functionality.
46
- * Used as `import { useQuery } from '${importPath}'`.
57
+ * Path to the useMutation hook for useMutation functionality.
58
+ * Used as `import { useMutation } from '${importPath}'`.
47
59
  * Accepts relative and absolute paths.
48
60
  * Path is used as-is; relative paths are based on the generated file location.
49
61
  * @default '@tanstack/react-query'
@@ -99,99 +111,99 @@ export type Options = {
99
111
  * Specify the export location for the files and define the behavior of the output
100
112
  * @default { path: 'hooks', barrelType: 'named' }
101
113
  */
102
- output?: Output<Oas>
103
- /**
104
- * Define which contentType should be used.
105
- * By default, the first JSON valid mediaType is used
106
- */
107
- contentType?: contentType
114
+ output?: Output
108
115
  /**
109
116
  * Group the @tanstack/query hooks based on the provided name.
110
117
  */
111
118
  group?: Group
112
119
  client?: ClientImportPath & Pick<PluginClient['options'], 'clientType' | 'dataReturnType' | 'baseURL' | 'bundle' | 'paramsCasing'>
113
120
  /**
114
- * Array containing exclude parameters to exclude/skip tags/operations/methods/paths.
121
+ * Tags, operations, or paths to exclude from generation.
115
122
  */
116
123
  exclude?: Array<Exclude>
117
124
  /**
118
- * Array containing include parameters to include tags/operations/methods/paths.
125
+ * Tags, operations, or paths to include in generation.
119
126
  */
120
127
  include?: Array<Include>
121
128
  /**
122
- * Array containing override parameters to override `options` based on tags/operations/methods/paths.
129
+ * Override options for specific tags, operations, or paths.
123
130
  */
124
131
  override?: Array<Override<ResolvedOptions>>
125
132
  /**
126
- * How to style your params, by default no casing is applied
127
- * - 'camelcase' uses camelcase for the params names
133
+ * Apply casing to parameter names.
128
134
  */
129
135
  paramsCasing?: 'camelcase'
130
136
  /**
131
- * How to pass your params.
132
- * - 'object' returns the params and pathParams as an object.
133
- * - 'inline' returns the params as comma separated params.
137
+ * How parameters are passed: grouped in an object or spread inline.
138
+ *
134
139
  * @default 'inline'
135
140
  */
136
141
  paramsType?: 'object' | 'inline'
137
142
  /**
138
- * How to pass your pathParams.
139
- * - 'object' returns the pathParams as an object.
140
- * - 'inline': returns the pathParams as comma separated params.
143
+ * How path parameters are passed: grouped in an object or spread inline.
144
+ *
141
145
  * @default 'inline'
142
146
  */
143
147
  pathParamsType?: PluginClient['options']['pathParamsType']
144
-
145
148
  /**
146
- * When set, an infiniteQuery hooks is added.
149
+ * Add infinite query hooks.
147
150
  */
148
151
  infinite?: Partial<Infinite> | false
149
152
  /**
150
- * When set, a suspenseQuery hooks is added.
153
+ * Add suspense query hooks.
151
154
  */
152
155
  suspense?: Partial<Suspense> | false
153
156
  queryKey?: QueryKey
154
157
  /**
155
- * Override some useQuery behaviors.
158
+ * Configure useQuery behavior.
156
159
  */
157
160
  query?: Partial<Query> | false
158
161
  mutationKey?: MutationKey
159
162
  /**
160
- * Override some useMutation behaviors.
163
+ * Configure useMutation behavior.
161
164
  */
162
165
  mutation?: Partial<Mutation> | false
163
166
  /**
164
- * When set, a custom hook is used to customize the options of the generated hooks.
165
- * It will also generate a `HookOptions` type that can be used to type the custom options of each hook for type-safety.
167
+ * Use a custom hook to customize hook options and generate a HookOptions type.
166
168
  */
167
169
  customOptions?: CustomOptions
168
170
  /**
169
- * Which parser should be used before returning the data to `@tanstack/query`.
170
- * `'zod'` uses `@kubb/plugin-zod` to parse the data.
171
+ * Parser to use for validating response data.
171
172
  */
172
173
  parser?: PluginClient['options']['parser']
173
174
  transformers?: {
174
175
  /**
175
- * Customize the names based on the type that is provided by the plugin.
176
+ * Override the default naming for hooks.
176
177
  */
177
- name?: (name: ResolveNameParams['name'], type?: ResolveNameParams['type']) => string
178
+ name?: (name: string, type?: string) => string
178
179
  }
179
180
  /**
180
- * Define some generators next to the react-query generators
181
+ * Override naming conventions for function names and types.
182
+ */
183
+ resolver?: Partial<ResolverReactQuery> & ThisType<ResolverReactQuery>
184
+ /**
185
+ * AST visitor to transform generated nodes.
186
+ */
187
+ transformer?: ast.Visitor
188
+ /**
189
+ * Additional generators alongside the default generators.
181
190
  */
182
191
  generators?: Array<Generator<PluginReactQuery>>
183
192
  }
184
193
 
185
194
  type ResolvedOptions = {
186
- output: Output<Oas>
187
- group: Options['group']
195
+ output: Output
196
+ group: Group | undefined
197
+ exclude: NonNullable<Options['exclude']>
198
+ include: Options['include']
199
+ override: NonNullable<Options['override']>
188
200
  client: Pick<PluginClient['options'], 'client' | 'clientType' | 'dataReturnType' | 'importPath' | 'baseURL' | 'bundle' | 'paramsCasing'>
189
201
  parser: Required<NonNullable<Options['parser']>>
190
202
  pathParamsType: NonNullable<Options['pathParamsType']>
191
203
  paramsCasing: Options['paramsCasing']
192
204
  paramsType: NonNullable<Options['paramsType']>
193
205
  /**
194
- * Only used of infinite
206
+ * Only used for infinite
195
207
  */
196
208
  infinite: NonNullable<Infinite> | false
197
209
  suspense: Suspense | false
@@ -200,6 +212,16 @@ type ResolvedOptions = {
200
212
  mutationKey: MutationKey | undefined
201
213
  mutation: NonNullable<Required<Mutation>> | false
202
214
  customOptions: NonNullable<Required<CustomOptions>> | undefined
215
+ resolver: ResolverReactQuery
216
+ transformers: NonNullable<Options['transformers']>
203
217
  }
204
218
 
205
- export type PluginReactQuery = PluginFactoryOptions<'plugin-react-query', Options, ResolvedOptions, never, ResolvePathOptions>
219
+ export type PluginReactQuery = PluginFactoryOptions<'plugin-react-query', Options, ResolvedOptions, ResolverReactQuery>
220
+
221
+ declare global {
222
+ namespace Kubb {
223
+ interface PluginRegistry {
224
+ 'plugin-react-query': PluginReactQuery
225
+ }
226
+ }
227
+ }
package/src/utils.ts ADDED
@@ -0,0 +1,40 @@
1
+ import type { ast } from '@kubb/core'
2
+ import type { PluginReactQuery } from './types.ts'
3
+
4
+ export {
5
+ buildGroupParam,
6
+ buildMutationArgParams,
7
+ buildQueryKeyParams,
8
+ getComments,
9
+ resolveErrorNames,
10
+ resolveHeaderGroupType,
11
+ resolvePathParamType,
12
+ resolveQueryGroupType,
13
+ resolveStatusCodeNames,
14
+ } from '@internals/tanstack-query'
15
+
16
+ export function transformName(name: string, type: string, transformers?: PluginReactQuery['resolvedOptions']['transformers']): string {
17
+ return transformers?.name?.(name, type) || name
18
+ }
19
+
20
+ function matchesPattern(node: ast.OperationNode, ov: { type: string; pattern: string | RegExp }): boolean {
21
+ const { type, pattern } = ov
22
+ const matches = (value: string) => (typeof pattern === 'string' ? value === pattern : pattern.test(value))
23
+ if (type === 'operationId') return matches(node.operationId)
24
+ if (type === 'tag') return node.tags.some((t) => matches(t))
25
+ if (type === 'path') return matches(node.path)
26
+ if (type === 'method') return matches(node.method)
27
+ return false
28
+ }
29
+
30
+ /**
31
+ * Resolves per-operation overrides (first matching override wins), mirroring v4 OperationGenerator.getOptions().
32
+ */
33
+ export function resolveOperationOverrides(
34
+ node: ast.OperationNode,
35
+ override?: PluginReactQuery['resolvedOptions']['override'],
36
+ ): Partial<PluginReactQuery['resolvedOptions']> {
37
+ if (!override) return {}
38
+ const match = override.find((ov) => matchesPattern(node, ov as { type: string; pattern: string | RegExp }))
39
+ return (match as { options?: Partial<PluginReactQuery['resolvedOptions']> })?.options ?? {}
40
+ }