@kubb/plugin-react-query 5.0.0-beta.15 → 5.0.0-beta.25
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.
- package/dist/{components-BZ3a2O0G.cjs → components-C1_zAoAO.cjs} +65 -84
- package/dist/components-C1_zAoAO.cjs.map +1 -0
- package/dist/{components-DJqIUiZW.js → components-C91DnOOV.js} +65 -84
- package/dist/components-C91DnOOV.js.map +1 -0
- package/dist/components.cjs +1 -1
- package/dist/components.d.ts +1 -1
- package/dist/components.js +1 -1
- package/dist/{generators-BQ_vEksc.js → generators-9srJC_zb.js} +115 -75
- package/dist/generators-9srJC_zb.js.map +1 -0
- package/dist/{generators-DSjer1xY.cjs → generators-DS3JH1hR.cjs} +115 -75
- package/dist/generators-DS3JH1hR.cjs.map +1 -0
- package/dist/generators.cjs +1 -1
- package/dist/generators.d.ts +41 -1
- package/dist/generators.js +1 -1
- package/dist/index.cjs +51 -11
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +30 -1
- package/dist/index.js +51 -11
- package/dist/index.js.map +1 -1
- package/dist/{types-DG_OxOym.d.ts → types-DiZPLTXl.d.ts} +92 -55
- package/extension.yaml +904 -325
- package/package.json +7 -7
- package/src/components/InfiniteQuery.tsx +4 -4
- package/src/components/InfiniteQueryOptions.tsx +21 -31
- package/src/components/Mutation.tsx +2 -2
- package/src/components/MutationOptions.tsx +1 -1
- package/src/components/Query.tsx +1 -1
- package/src/components/QueryOptions.tsx +1 -1
- package/src/components/SuspenseInfiniteQuery.tsx +4 -4
- package/src/components/SuspenseInfiniteQueryOptions.tsx +21 -31
- package/src/components/SuspenseQuery.tsx +1 -1
- package/src/generators/customHookOptionsFileGenerator.tsx +7 -1
- package/src/generators/hookOptionsGenerator.tsx +17 -11
- package/src/generators/infiniteQueryGenerator.tsx +22 -13
- package/src/generators/mutationGenerator.tsx +20 -12
- package/src/generators/queryGenerator.tsx +20 -12
- package/src/generators/suspenseInfiniteQueryGenerator.tsx +22 -13
- package/src/generators/suspenseQueryGenerator.tsx +21 -12
- package/src/plugin.ts +34 -5
- package/src/resolvers/resolverReactQuery.ts +15 -4
- package/src/types.ts +89 -52
- package/dist/components-BZ3a2O0G.cjs.map +0 -1
- package/dist/components-DJqIUiZW.js.map +0 -1
- package/dist/generators-BQ_vEksc.js.map +0 -1
- package/dist/generators-DSjer1xY.cjs.map +0 -1
|
@@ -10,11 +10,16 @@ import { difference } from 'remeda'
|
|
|
10
10
|
import { Query, QueryKey, QueryOptions } from '../components'
|
|
11
11
|
import type { PluginReactQuery } from '../types'
|
|
12
12
|
|
|
13
|
+
/**
|
|
14
|
+
* Built-in generator for `useQuery` hooks. Emits one `useFooQuery` hook per
|
|
15
|
+
* GET operation (configurable via `query.methods`) plus the matching
|
|
16
|
+
* `fooQueryKey` / `fooQueryOptions` helpers.
|
|
17
|
+
*/
|
|
13
18
|
export const queryGenerator = defineGenerator<PluginReactQuery>({
|
|
14
19
|
name: 'react-query',
|
|
15
20
|
renderer: jsxRendererSync,
|
|
16
21
|
operation(node, ctx) {
|
|
17
|
-
const { config, driver, resolver, root
|
|
22
|
+
const { config, driver, resolver, root } = ctx
|
|
18
23
|
const { output, query, mutation, paramsCasing, paramsType, pathParamsType, parser, client: clientOptions, group, customOptions } = ctx.options
|
|
19
24
|
|
|
20
25
|
const pluginTs = driver.getPlugin(pluginTsName)
|
|
@@ -39,10 +44,13 @@ export const queryGenerator = defineGenerator<PluginReactQuery>({
|
|
|
39
44
|
const clientName = resolver.resolveClientName(node)
|
|
40
45
|
|
|
41
46
|
const meta = {
|
|
42
|
-
file: resolver.resolveFile(
|
|
47
|
+
file: resolver.resolveFile(
|
|
48
|
+
{ name: queryName, extname: '.ts', tag: node.tags[0] ?? 'default', path: node.path },
|
|
49
|
+
{ root, output, group: group ?? undefined },
|
|
50
|
+
),
|
|
43
51
|
fileTs: tsResolver.resolveFile(
|
|
44
52
|
{ name: node.operationId, extname: '.ts', tag: node.tags[0] ?? 'default', path: node.path },
|
|
45
|
-
{ root, output: pluginTs.options?.output ?? output, group: pluginTs.options?.group },
|
|
53
|
+
{ root, output: pluginTs.options?.output ?? output, group: pluginTs.options?.group ?? undefined },
|
|
46
54
|
),
|
|
47
55
|
}
|
|
48
56
|
|
|
@@ -52,20 +60,20 @@ export const queryGenerator = defineGenerator<PluginReactQuery>({
|
|
|
52
60
|
order: 'body-response-first',
|
|
53
61
|
})
|
|
54
62
|
|
|
55
|
-
const pluginZod = parser === 'zod' ? driver.getPlugin(pluginZodName) :
|
|
56
|
-
const zodResolver = pluginZod ? driver.getResolver(pluginZodName) :
|
|
63
|
+
const pluginZod = parser === 'zod' ? driver.getPlugin(pluginZodName) : null
|
|
64
|
+
const zodResolver = pluginZod ? driver.getResolver(pluginZodName) : null
|
|
57
65
|
const fileZod = zodResolver
|
|
58
66
|
? zodResolver.resolveFile(
|
|
59
67
|
{ name: node.operationId, extname: '.ts', tag: node.tags[0] ?? 'default', path: node.path },
|
|
60
|
-
{ root, output: pluginZod?.options?.output ?? output, group: pluginZod?.options?.group },
|
|
68
|
+
{ root, output: pluginZod?.options?.output ?? output, group: pluginZod?.options?.group ?? undefined },
|
|
61
69
|
)
|
|
62
|
-
:
|
|
70
|
+
: null
|
|
63
71
|
const zodSchemaNames = resolveZodSchemaNames(node, zodResolver)
|
|
64
72
|
|
|
65
73
|
const clientPlugin = driver.getPlugin(pluginClientName)
|
|
66
74
|
const hasClientPlugin = clientPlugin?.name === pluginClientName
|
|
67
75
|
const shouldUseClientPlugin = hasClientPlugin && clientOptions.clientType !== 'class'
|
|
68
|
-
const clientResolver = shouldUseClientPlugin ? driver.getResolver(pluginClientName) :
|
|
76
|
+
const clientResolver = shouldUseClientPlugin ? driver.getResolver(pluginClientName) : null
|
|
69
77
|
|
|
70
78
|
const clientFile = shouldUseClientPlugin
|
|
71
79
|
? clientResolver?.resolveFile(
|
|
@@ -73,10 +81,10 @@ export const queryGenerator = defineGenerator<PluginReactQuery>({
|
|
|
73
81
|
{
|
|
74
82
|
root,
|
|
75
83
|
output: clientPlugin?.options?.output ?? output,
|
|
76
|
-
group: clientPlugin?.options?.group,
|
|
84
|
+
group: clientPlugin?.options?.group ?? undefined,
|
|
77
85
|
},
|
|
78
86
|
)
|
|
79
|
-
:
|
|
87
|
+
: null
|
|
80
88
|
|
|
81
89
|
const resolvedClientName = shouldUseClientPlugin ? (clientResolver?.resolveName(node.operationId) ?? clientName) : clientName
|
|
82
90
|
|
|
@@ -85,8 +93,8 @@ export const queryGenerator = defineGenerator<PluginReactQuery>({
|
|
|
85
93
|
baseName={meta.file.baseName}
|
|
86
94
|
path={meta.file.path}
|
|
87
95
|
meta={meta.file.meta}
|
|
88
|
-
banner={resolver.resolveBanner(
|
|
89
|
-
footer={resolver.resolveFooter(
|
|
96
|
+
banner={resolver.resolveBanner(ctx.meta, { output, config })}
|
|
97
|
+
footer={resolver.resolveFooter(ctx.meta, { output, config })}
|
|
90
98
|
>
|
|
91
99
|
{fileZod && zodSchemaNames.length > 0 && <File.Import name={zodSchemaNames} root={meta.file.path} path={fileZod.path} />}
|
|
92
100
|
{clientOptions.importPath ? (
|
|
@@ -10,11 +10,17 @@ import { difference } from 'remeda'
|
|
|
10
10
|
import { QueryKey, SuspenseInfiniteQuery, SuspenseInfiniteQueryOptions } from '../components'
|
|
11
11
|
import type { PluginReactQuery } from '../types'
|
|
12
12
|
|
|
13
|
+
/**
|
|
14
|
+
* Built-in generator for `useSuspenseInfiniteQuery` hooks. Enabled when both
|
|
15
|
+
* `suspense` and `infinite` are configured. Combines suspense semantics with
|
|
16
|
+
* cursor-based pagination — handlers throw promises while loading and pull
|
|
17
|
+
* additional pages on demand.
|
|
18
|
+
*/
|
|
13
19
|
export const suspenseInfiniteQueryGenerator = defineGenerator<PluginReactQuery>({
|
|
14
20
|
name: 'react-suspense-infinite-query',
|
|
15
21
|
renderer: jsxRendererSync,
|
|
16
22
|
operation(node, ctx) {
|
|
17
|
-
const { config, driver, resolver, root
|
|
23
|
+
const { config, driver, resolver, root } = ctx
|
|
18
24
|
const {
|
|
19
25
|
output,
|
|
20
26
|
query,
|
|
@@ -40,7 +46,7 @@ export const suspenseInfiniteQueryGenerator = defineGenerator<PluginReactQuery>(
|
|
|
40
46
|
!isQuery &&
|
|
41
47
|
difference(mutation ? mutation.methods : [], query ? query.methods : []).some((method) => node.method.toLowerCase() === method.toLowerCase())
|
|
42
48
|
const isSuspense = !!suspense
|
|
43
|
-
const infiniteOptions = infinite && typeof infinite === 'object' ? infinite :
|
|
49
|
+
const infiniteOptions = infinite && typeof infinite === 'object' ? infinite : null
|
|
44
50
|
|
|
45
51
|
if (!isQuery || isMutation || !isSuspense || !infiniteOptions) return null
|
|
46
52
|
|
|
@@ -61,29 +67,32 @@ export const suspenseInfiniteQueryGenerator = defineGenerator<PluginReactQuery>(
|
|
|
61
67
|
const clientBaseName = resolver.resolveSuspenseInfiniteClientName(node)
|
|
62
68
|
|
|
63
69
|
const meta = {
|
|
64
|
-
file: resolver.resolveFile(
|
|
70
|
+
file: resolver.resolveFile(
|
|
71
|
+
{ name: queryName, extname: '.ts', tag: node.tags[0] ?? 'default', path: node.path },
|
|
72
|
+
{ root, output, group: group ?? undefined },
|
|
73
|
+
),
|
|
65
74
|
fileTs: tsResolver.resolveFile(
|
|
66
75
|
{ name: node.operationId, extname: '.ts', tag: node.tags[0] ?? 'default', path: node.path },
|
|
67
|
-
{ root, output: pluginTs.options?.output ?? output, group: pluginTs.options?.group },
|
|
76
|
+
{ root, output: pluginTs.options?.output ?? output, group: pluginTs.options?.group ?? undefined },
|
|
68
77
|
),
|
|
69
78
|
}
|
|
70
79
|
|
|
71
80
|
const importedTypeNames = resolveOperationTypeNames(node, tsResolver, { paramsCasing, order: 'body-response-first' })
|
|
72
81
|
|
|
73
|
-
const pluginZod = parser === 'zod' ? driver.getPlugin(pluginZodName) :
|
|
74
|
-
const zodResolver = pluginZod ? driver.getResolver(pluginZodName) :
|
|
82
|
+
const pluginZod = parser === 'zod' ? driver.getPlugin(pluginZodName) : null
|
|
83
|
+
const zodResolver = pluginZod ? driver.getResolver(pluginZodName) : null
|
|
75
84
|
const fileZod = zodResolver
|
|
76
85
|
? zodResolver.resolveFile(
|
|
77
86
|
{ name: node.operationId, extname: '.ts', tag: node.tags[0] ?? 'default', path: node.path },
|
|
78
|
-
{ root, output: pluginZod?.options?.output ?? output, group: pluginZod?.options?.group },
|
|
87
|
+
{ root, output: pluginZod?.options?.output ?? output, group: pluginZod?.options?.group ?? undefined },
|
|
79
88
|
)
|
|
80
|
-
:
|
|
89
|
+
: null
|
|
81
90
|
const zodSchemaNames = resolveZodSchemaNames(node, zodResolver)
|
|
82
91
|
|
|
83
92
|
const clientPlugin = driver.getPlugin(pluginClientName)
|
|
84
93
|
const hasClientPlugin = clientPlugin?.name === pluginClientName
|
|
85
94
|
const shouldUseClientPlugin = hasClientPlugin && clientOptions.clientType !== 'class'
|
|
86
|
-
const clientResolver = shouldUseClientPlugin ? driver.getResolver(pluginClientName) :
|
|
95
|
+
const clientResolver = shouldUseClientPlugin ? driver.getResolver(pluginClientName) : null
|
|
87
96
|
|
|
88
97
|
const clientFile = shouldUseClientPlugin
|
|
89
98
|
? clientResolver?.resolveFile(
|
|
@@ -91,10 +100,10 @@ export const suspenseInfiniteQueryGenerator = defineGenerator<PluginReactQuery>(
|
|
|
91
100
|
{
|
|
92
101
|
root,
|
|
93
102
|
output: clientPlugin?.options?.output ?? output,
|
|
94
|
-
group: clientPlugin?.options?.group,
|
|
103
|
+
group: clientPlugin?.options?.group ?? undefined,
|
|
95
104
|
},
|
|
96
105
|
)
|
|
97
|
-
:
|
|
106
|
+
: null
|
|
98
107
|
|
|
99
108
|
const resolvedClientName = shouldUseClientPlugin ? (clientResolver?.resolveName(node.operationId) ?? clientBaseName) : clientBaseName
|
|
100
109
|
|
|
@@ -103,8 +112,8 @@ export const suspenseInfiniteQueryGenerator = defineGenerator<PluginReactQuery>(
|
|
|
103
112
|
baseName={meta.file.baseName}
|
|
104
113
|
path={meta.file.path}
|
|
105
114
|
meta={meta.file.meta}
|
|
106
|
-
banner={resolver.resolveBanner(
|
|
107
|
-
footer={resolver.resolveFooter(
|
|
115
|
+
banner={resolver.resolveBanner(ctx.meta, { output, config })}
|
|
116
|
+
footer={resolver.resolveFooter(ctx.meta, { output, config })}
|
|
108
117
|
>
|
|
109
118
|
{fileZod && zodSchemaNames.length > 0 && <File.Import name={zodSchemaNames} root={meta.file.path} path={fileZod.path} />}
|
|
110
119
|
{clientOptions.importPath ? (
|
|
@@ -10,11 +10,17 @@ import { difference } from 'remeda'
|
|
|
10
10
|
import { QueryKey, QueryOptions, SuspenseQuery } from '../components'
|
|
11
11
|
import type { PluginReactQuery } from '../types'
|
|
12
12
|
|
|
13
|
+
/**
|
|
14
|
+
* Built-in generator for `useSuspenseQuery` hooks. Enabled when
|
|
15
|
+
* `pluginReactQuery({ suspense: {} })`. Emits one `useFooSuspenseQuery` hook
|
|
16
|
+
* per query operation. Suspense queries throw promises while loading and
|
|
17
|
+
* require a `<Suspense>` boundary in the React tree. TanStack Query v5+ only.
|
|
18
|
+
*/
|
|
13
19
|
export const suspenseQueryGenerator = defineGenerator<PluginReactQuery>({
|
|
14
20
|
name: 'react-suspense-query',
|
|
15
21
|
renderer: jsxRendererSync,
|
|
16
22
|
operation(node, ctx) {
|
|
17
|
-
const { config, driver, resolver, root
|
|
23
|
+
const { config, driver, resolver, root } = ctx
|
|
18
24
|
const { output, query, mutation, suspense, paramsCasing, paramsType, pathParamsType, parser, client: clientOptions, group, customOptions } = ctx.options
|
|
19
25
|
|
|
20
26
|
const pluginTs = driver.getPlugin(pluginTsName)
|
|
@@ -40,10 +46,13 @@ export const suspenseQueryGenerator = defineGenerator<PluginReactQuery>({
|
|
|
40
46
|
const clientName = resolver.resolveSuspenseClientName(node)
|
|
41
47
|
|
|
42
48
|
const meta = {
|
|
43
|
-
file: resolver.resolveFile(
|
|
49
|
+
file: resolver.resolveFile(
|
|
50
|
+
{ name: queryName, extname: '.ts', tag: node.tags[0] ?? 'default', path: node.path },
|
|
51
|
+
{ root, output, group: group ?? undefined },
|
|
52
|
+
),
|
|
44
53
|
fileTs: tsResolver.resolveFile(
|
|
45
54
|
{ name: node.operationId, extname: '.ts', tag: node.tags[0] ?? 'default', path: node.path },
|
|
46
|
-
{ root, output: pluginTs.options?.output ?? output, group: pluginTs.options?.group },
|
|
55
|
+
{ root, output: pluginTs.options?.output ?? output, group: pluginTs.options?.group ?? undefined },
|
|
47
56
|
),
|
|
48
57
|
}
|
|
49
58
|
|
|
@@ -53,20 +62,20 @@ export const suspenseQueryGenerator = defineGenerator<PluginReactQuery>({
|
|
|
53
62
|
order: 'body-response-first',
|
|
54
63
|
})
|
|
55
64
|
|
|
56
|
-
const pluginZod = parser === 'zod' ? driver.getPlugin(pluginZodName) :
|
|
57
|
-
const zodResolver = pluginZod ? driver.getResolver(pluginZodName) :
|
|
65
|
+
const pluginZod = parser === 'zod' ? driver.getPlugin(pluginZodName) : null
|
|
66
|
+
const zodResolver = pluginZod ? driver.getResolver(pluginZodName) : null
|
|
58
67
|
const fileZod = zodResolver
|
|
59
68
|
? zodResolver.resolveFile(
|
|
60
69
|
{ name: node.operationId, extname: '.ts', tag: node.tags[0] ?? 'default', path: node.path },
|
|
61
|
-
{ root, output: pluginZod?.options?.output ?? output, group: pluginZod?.options?.group },
|
|
70
|
+
{ root, output: pluginZod?.options?.output ?? output, group: pluginZod?.options?.group ?? undefined },
|
|
62
71
|
)
|
|
63
|
-
:
|
|
72
|
+
: null
|
|
64
73
|
const zodSchemaNames = resolveZodSchemaNames(node, zodResolver)
|
|
65
74
|
|
|
66
75
|
const clientPlugin = driver.getPlugin(pluginClientName)
|
|
67
76
|
const hasClientPlugin = clientPlugin?.name === pluginClientName
|
|
68
77
|
const shouldUseClientPlugin = hasClientPlugin && clientOptions.clientType !== 'class'
|
|
69
|
-
const clientResolver = shouldUseClientPlugin ? driver.getResolver(pluginClientName) :
|
|
78
|
+
const clientResolver = shouldUseClientPlugin ? driver.getResolver(pluginClientName) : null
|
|
70
79
|
|
|
71
80
|
const clientFile = shouldUseClientPlugin
|
|
72
81
|
? clientResolver?.resolveFile(
|
|
@@ -74,10 +83,10 @@ export const suspenseQueryGenerator = defineGenerator<PluginReactQuery>({
|
|
|
74
83
|
{
|
|
75
84
|
root,
|
|
76
85
|
output: clientPlugin?.options?.output ?? output,
|
|
77
|
-
group: clientPlugin?.options?.group,
|
|
86
|
+
group: clientPlugin?.options?.group ?? undefined,
|
|
78
87
|
},
|
|
79
88
|
)
|
|
80
|
-
:
|
|
89
|
+
: null
|
|
81
90
|
|
|
82
91
|
const resolvedClientName = shouldUseClientPlugin ? (clientResolver?.resolveName(node.operationId) ?? clientName) : clientName
|
|
83
92
|
|
|
@@ -86,8 +95,8 @@ export const suspenseQueryGenerator = defineGenerator<PluginReactQuery>({
|
|
|
86
95
|
baseName={meta.file.baseName}
|
|
87
96
|
path={meta.file.path}
|
|
88
97
|
meta={meta.file.meta}
|
|
89
|
-
banner={resolver.resolveBanner(
|
|
90
|
-
footer={resolver.resolveFooter(
|
|
98
|
+
banner={resolver.resolveBanner(ctx.meta, { output, config })}
|
|
99
|
+
footer={resolver.resolveFooter(ctx.meta, { output, config })}
|
|
91
100
|
>
|
|
92
101
|
{fileZod && zodSchemaNames.length > 0 && <File.Import name={zodSchemaNames} root={meta.file.path} path={fileZod.path} />}
|
|
93
102
|
{clientOptions.importPath ? (
|
package/src/plugin.ts
CHANGED
|
@@ -20,8 +20,37 @@ import {
|
|
|
20
20
|
import { resolverReactQuery } from './resolvers/resolverReactQuery.ts'
|
|
21
21
|
import type { PluginReactQuery } from './types.ts'
|
|
22
22
|
|
|
23
|
+
/**
|
|
24
|
+
* Canonical plugin name for `@kubb/plugin-react-query`. Used for driver lookups
|
|
25
|
+
* and cross-plugin dependency references.
|
|
26
|
+
*/
|
|
23
27
|
export const pluginReactQueryName = 'plugin-react-query' satisfies PluginReactQuery['name']
|
|
24
28
|
|
|
29
|
+
/**
|
|
30
|
+
* Generates one TanStack Query hook per OpenAPI operation for React. Queries
|
|
31
|
+
* become `useFooQuery`/`useFooSuspenseQuery`/`useFooInfiniteQuery`; mutations
|
|
32
|
+
* become `useFooMutation`. Each hook is fully typed: query keys, input
|
|
33
|
+
* variables, response data, and error shape all come from the spec.
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* ```ts
|
|
37
|
+
* import { defineConfig } from 'kubb'
|
|
38
|
+
* import { pluginTs } from '@kubb/plugin-ts'
|
|
39
|
+
* import { pluginReactQuery } from '@kubb/plugin-react-query'
|
|
40
|
+
*
|
|
41
|
+
* export default defineConfig({
|
|
42
|
+
* input: { path: './petStore.yaml' },
|
|
43
|
+
* output: { path: './src/gen' },
|
|
44
|
+
* plugins: [
|
|
45
|
+
* pluginTs(),
|
|
46
|
+
* pluginReactQuery({
|
|
47
|
+
* output: { path: './hooks' },
|
|
48
|
+
* suspense: {},
|
|
49
|
+
* }),
|
|
50
|
+
* ],
|
|
51
|
+
* })
|
|
52
|
+
* ```
|
|
53
|
+
*/
|
|
25
54
|
export const pluginReactQuery = definePlugin<PluginReactQuery>((options) => {
|
|
26
55
|
const {
|
|
27
56
|
output = { path: 'hooks', barrelType: 'named' },
|
|
@@ -73,7 +102,7 @@ export const pluginReactQuery = definePlugin<PluginReactQuery>((options) => {
|
|
|
73
102
|
return `${camelCase(ctx.group)}Controller`
|
|
74
103
|
},
|
|
75
104
|
} satisfies Group)
|
|
76
|
-
:
|
|
105
|
+
: null
|
|
77
106
|
|
|
78
107
|
return {
|
|
79
108
|
name: pluginReactQueryName,
|
|
@@ -116,14 +145,14 @@ export const pluginReactQuery = definePlugin<PluginReactQuery>((options) => {
|
|
|
116
145
|
? {
|
|
117
146
|
queryParam: 'id',
|
|
118
147
|
initialPageParam: 0,
|
|
119
|
-
cursorParam:
|
|
120
|
-
nextParam:
|
|
121
|
-
previousParam:
|
|
148
|
+
cursorParam: null,
|
|
149
|
+
nextParam: null,
|
|
150
|
+
previousParam: null,
|
|
122
151
|
...infinite,
|
|
123
152
|
}
|
|
124
153
|
: false,
|
|
125
154
|
suspense,
|
|
126
|
-
customOptions: customOptions ? { name: 'useCustomHookOptions', ...customOptions } :
|
|
155
|
+
customOptions: customOptions ? { name: 'useCustomHookOptions', ...customOptions } : null,
|
|
127
156
|
parser,
|
|
128
157
|
paramsType,
|
|
129
158
|
pathParamsType,
|
|
@@ -7,12 +7,23 @@ function capitalize(name: string): string {
|
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
|
-
*
|
|
10
|
+
* Default resolver used by `@kubb/plugin-react-query`. Decides the names and
|
|
11
|
+
* file paths for every generated TanStack Query hook (`useFooQuery`,
|
|
12
|
+
* `useFooMutation`, `useFooInfiniteQuery`, ...) and its companion helpers
|
|
13
|
+
* (`fooQueryKey`, `fooQueryOptions`).
|
|
11
14
|
*
|
|
12
|
-
*
|
|
15
|
+
* Functions and files use camelCase; hooks get the `use` prefix; suspense and
|
|
16
|
+
* infinite variants are suffixed with `Suspense`/`Infinite`.
|
|
13
17
|
*
|
|
14
|
-
* @example
|
|
15
|
-
*
|
|
18
|
+
* @example Resolve hook and helper names
|
|
19
|
+
* ```ts
|
|
20
|
+
* import { resolverReactQuery } from '@kubb/plugin-react-query'
|
|
21
|
+
*
|
|
22
|
+
* resolverReactQuery.resolveQueryName(operationNode) // 'useGetPetById'
|
|
23
|
+
* resolverReactQuery.resolveMutationName(operationNode) // 'useUpdatePet'
|
|
24
|
+
* resolverReactQuery.resolveQueryKeyName(operationNode) // 'getPetByIdQueryKey'
|
|
25
|
+
* resolverReactQuery.resolveQueryOptionsName(operationNode) // 'getPetByIdQueryOptions'
|
|
26
|
+
* ```
|
|
16
27
|
*/
|
|
17
28
|
export const resolverReactQuery = defineResolver<PluginReactQuery>(() => ({
|
|
18
29
|
name: 'default',
|
package/src/types.ts
CHANGED
|
@@ -128,27 +128,34 @@ export type ResolverReactQuery = Resolver & {
|
|
|
128
128
|
type Suspense = object
|
|
129
129
|
|
|
130
130
|
/**
|
|
131
|
-
*
|
|
131
|
+
* Builds the `queryKey` used by each generated query hook.
|
|
132
|
+
*
|
|
133
|
+
* @note String values are inlined verbatim into generated code. Wrap literal
|
|
134
|
+
* strings in `JSON.stringify(...)`.
|
|
132
135
|
*/
|
|
133
136
|
type QueryKey = Transformer
|
|
134
137
|
|
|
135
138
|
/**
|
|
136
|
-
*
|
|
139
|
+
* Builds the `mutationKey` used by each generated mutation hook.
|
|
140
|
+
*
|
|
141
|
+
* @note String values are inlined verbatim into generated code. Wrap literal
|
|
142
|
+
* strings in `JSON.stringify(...)`.
|
|
137
143
|
*/
|
|
138
144
|
type MutationKey = Transformer
|
|
139
145
|
|
|
140
146
|
type Query = {
|
|
141
147
|
/**
|
|
142
|
-
* HTTP methods
|
|
148
|
+
* HTTP methods treated as queries. Operations using these methods produce
|
|
149
|
+
* `useQuery`-style hooks.
|
|
143
150
|
*
|
|
144
151
|
* @default ['get']
|
|
145
152
|
*/
|
|
146
153
|
methods?: Array<string>
|
|
147
154
|
/**
|
|
148
|
-
*
|
|
149
|
-
*
|
|
150
|
-
*
|
|
151
|
-
*
|
|
155
|
+
* Module specifier used in the `import { useQuery } from '...'` statement at
|
|
156
|
+
* the top of every generated hook file. Useful for routing through a wrapper
|
|
157
|
+
* that injects a default `queryClient`.
|
|
158
|
+
*
|
|
152
159
|
* @default '@tanstack/react-query'
|
|
153
160
|
*/
|
|
154
161
|
importPath?: string
|
|
@@ -156,16 +163,16 @@ type Query = {
|
|
|
156
163
|
|
|
157
164
|
type Mutation = {
|
|
158
165
|
/**
|
|
159
|
-
* HTTP methods
|
|
166
|
+
* HTTP methods treated as mutations. Operations using these methods produce
|
|
167
|
+
* `useMutation`-style hooks.
|
|
160
168
|
*
|
|
161
169
|
* @default ['post', 'put', 'delete']
|
|
162
170
|
*/
|
|
163
171
|
methods?: Array<string>
|
|
164
172
|
/**
|
|
165
|
-
*
|
|
166
|
-
*
|
|
167
|
-
*
|
|
168
|
-
* Path is used as-is; relative paths are based on the generated file location.
|
|
173
|
+
* Module specifier used in the `import { useMutation } from '...'` statement
|
|
174
|
+
* at the top of every generated hook file.
|
|
175
|
+
*
|
|
169
176
|
* @default '@tanstack/react-query'
|
|
170
177
|
*/
|
|
171
178
|
importPath?: string
|
|
@@ -173,42 +180,45 @@ type Mutation = {
|
|
|
173
180
|
|
|
174
181
|
export type Infinite = {
|
|
175
182
|
/**
|
|
176
|
-
*
|
|
183
|
+
* Name of the query parameter that holds the page cursor.
|
|
184
|
+
*
|
|
177
185
|
* @default 'id'
|
|
178
186
|
*/
|
|
179
|
-
queryParam
|
|
187
|
+
queryParam?: string
|
|
180
188
|
/**
|
|
181
|
-
*
|
|
182
|
-
*
|
|
189
|
+
* Path to the cursor field on the response. Leave undefined when the cursor
|
|
190
|
+
* is not known.
|
|
191
|
+
*
|
|
192
|
+
* @deprecated Use `nextParam` and `previousParam` for richer pagination control.
|
|
183
193
|
*/
|
|
184
|
-
cursorParam?: string |
|
|
194
|
+
cursorParam?: string | null
|
|
185
195
|
/**
|
|
186
|
-
*
|
|
187
|
-
*
|
|
196
|
+
* Path to the next-page cursor on the response. Supports dot notation
|
|
197
|
+
* (`'pagination.next.id'`) or array form (`['pagination', 'next', 'id']`).
|
|
188
198
|
*/
|
|
189
|
-
nextParam?: string | string
|
|
199
|
+
nextParam?: string | Array<string> | null
|
|
190
200
|
/**
|
|
191
|
-
*
|
|
192
|
-
*
|
|
201
|
+
* Path to the previous-page cursor on the response. Supports dot notation
|
|
202
|
+
* or array form.
|
|
193
203
|
*/
|
|
194
|
-
previousParam?: string | string
|
|
204
|
+
previousParam?: string | Array<string> | null
|
|
195
205
|
/**
|
|
196
|
-
*
|
|
206
|
+
* Initial value for `pageParam` on the first fetch.
|
|
207
|
+
*
|
|
197
208
|
* @default 0
|
|
198
209
|
*/
|
|
199
|
-
initialPageParam
|
|
210
|
+
initialPageParam?: unknown
|
|
200
211
|
}
|
|
201
212
|
|
|
202
213
|
type CustomOptions = {
|
|
203
214
|
/**
|
|
204
|
-
*
|
|
205
|
-
*
|
|
206
|
-
* It allows both relative and absolute paths but be aware that we will not change the path.
|
|
215
|
+
* Module specifier of your custom-options hook. Imported as
|
|
216
|
+
* `import ${name} from '${importPath}'`.
|
|
207
217
|
*/
|
|
208
218
|
importPath: string
|
|
209
219
|
/**
|
|
210
|
-
*
|
|
211
|
-
*
|
|
220
|
+
* Exported function name of your custom-options hook.
|
|
221
|
+
*
|
|
212
222
|
* @default 'useCustomHookOptions'
|
|
213
223
|
*/
|
|
214
224
|
name?: string
|
|
@@ -216,86 +226,113 @@ type CustomOptions = {
|
|
|
216
226
|
|
|
217
227
|
export type Options = {
|
|
218
228
|
/**
|
|
219
|
-
*
|
|
220
|
-
*
|
|
229
|
+
* Where the generated hooks are written and how they are exported.
|
|
230
|
+
*
|
|
231
|
+
* @default { path: 'hooks', barrel: { type: 'named' } }
|
|
221
232
|
*/
|
|
222
233
|
output?: Output
|
|
223
234
|
/**
|
|
224
|
-
*
|
|
235
|
+
* Split generated files into subfolders based on the operation's tag.
|
|
225
236
|
*/
|
|
226
237
|
group?: Group
|
|
238
|
+
/**
|
|
239
|
+
* HTTP client used inside every generated hook. Mirrors a subset of
|
|
240
|
+
* `pluginClient` options.
|
|
241
|
+
*/
|
|
227
242
|
client?: ClientImportPath & Pick<PluginClient['options'], 'clientType' | 'dataReturnType' | 'baseURL' | 'bundle' | 'paramsCasing'>
|
|
228
243
|
/**
|
|
229
|
-
*
|
|
244
|
+
* Skip operations matching at least one entry in the list.
|
|
230
245
|
*/
|
|
231
246
|
exclude?: Array<Exclude>
|
|
232
247
|
/**
|
|
233
|
-
*
|
|
248
|
+
* Restrict generation to operations matching at least one entry in the list.
|
|
234
249
|
*/
|
|
235
250
|
include?: Array<Include>
|
|
236
251
|
/**
|
|
237
|
-
*
|
|
252
|
+
* Apply a different options object to operations matching a pattern.
|
|
238
253
|
*/
|
|
239
254
|
override?: Array<Override<ResolvedOptions>>
|
|
240
255
|
/**
|
|
241
|
-
*
|
|
256
|
+
* Rename parameter properties in the generated hooks.
|
|
257
|
+
*
|
|
258
|
+
* @note Must match the value of `paramsCasing` on `@kubb/plugin-ts`.
|
|
242
259
|
*/
|
|
243
260
|
paramsCasing?: 'camelcase'
|
|
244
261
|
/**
|
|
245
|
-
* How parameters
|
|
262
|
+
* How operation parameters appear in the generated hook signature.
|
|
263
|
+
* - `'inline'` — positional arguments.
|
|
264
|
+
* - `'object'` — single destructured object argument.
|
|
246
265
|
*
|
|
247
266
|
* @default 'inline'
|
|
248
267
|
*/
|
|
249
268
|
paramsType?: 'object' | 'inline'
|
|
250
269
|
/**
|
|
251
|
-
* How path parameters are
|
|
270
|
+
* How URL path parameters are arranged inside the inline argument list.
|
|
252
271
|
*
|
|
253
272
|
* @default 'inline'
|
|
254
273
|
*/
|
|
255
274
|
pathParamsType?: PluginClient['options']['pathParamsType']
|
|
256
275
|
/**
|
|
257
|
-
*
|
|
276
|
+
* Enables `useInfiniteQuery` hooks for cursor- or page-based pagination.
|
|
277
|
+
* Pass an object to configure how the cursor is read; pass `false` to skip.
|
|
278
|
+
*
|
|
279
|
+
* @default false
|
|
258
280
|
*/
|
|
259
281
|
infinite?: Partial<Infinite> | false
|
|
260
282
|
/**
|
|
261
|
-
*
|
|
283
|
+
* Adds `useSuspenseQuery` hooks alongside the regular `useQuery` ones.
|
|
284
|
+
* Pass an empty object (`{}`) to enable. TanStack Query v5+ only.
|
|
262
285
|
*/
|
|
263
286
|
suspense?: Partial<Suspense> | false
|
|
287
|
+
/**
|
|
288
|
+
* Custom `queryKey` builder. Use to add a version namespace, swap to
|
|
289
|
+
* operation IDs, or shape keys to match an existing invalidation strategy.
|
|
290
|
+
*/
|
|
264
291
|
queryKey?: QueryKey
|
|
265
292
|
/**
|
|
266
|
-
*
|
|
293
|
+
* Configures query hooks. Set to `false` to skip generating hooks entirely
|
|
294
|
+
* and emit only `queryOptions(...)` helpers.
|
|
267
295
|
*/
|
|
268
296
|
query?: Partial<Query> | false
|
|
297
|
+
/**
|
|
298
|
+
* Custom `mutationKey` builder. Useful when you batch invalidations or read
|
|
299
|
+
* mutation state via `useMutationState`.
|
|
300
|
+
*/
|
|
269
301
|
mutationKey?: MutationKey
|
|
270
302
|
/**
|
|
271
|
-
*
|
|
303
|
+
* Configures mutation hooks. Set to `false` to skip mutation generation.
|
|
272
304
|
*/
|
|
273
305
|
mutation?: Partial<Mutation> | false
|
|
274
306
|
/**
|
|
275
|
-
*
|
|
307
|
+
* Wires every generated hook through a user-supplied function that returns
|
|
308
|
+
* extra options (`onSuccess`, `onError`, `select`, ...). Also emits a
|
|
309
|
+
* `HookOptions` type so the wrapper stays in sync with generated hooks.
|
|
276
310
|
*/
|
|
277
311
|
customOptions?: CustomOptions
|
|
278
312
|
/**
|
|
279
|
-
*
|
|
313
|
+
* Validator applied to response bodies before they reach the caller.
|
|
314
|
+
* - `'client'` — no validation. Trusts the API.
|
|
315
|
+
* - `'zod'` — pipes responses through schemas from `@kubb/plugin-zod`.
|
|
280
316
|
*/
|
|
281
317
|
parser?: PluginClient['options']['parser']
|
|
282
318
|
/**
|
|
283
|
-
* Override
|
|
319
|
+
* Override how hook names and file paths are built. Methods you omit fall
|
|
320
|
+
* back to the default `resolverReactQuery`.
|
|
284
321
|
*/
|
|
285
322
|
resolver?: Partial<ResolverReactQuery> & ThisType<ResolverReactQuery>
|
|
286
323
|
/**
|
|
287
|
-
* AST visitor to
|
|
324
|
+
* AST visitor applied to each operation node before printing.
|
|
288
325
|
*/
|
|
289
326
|
transformer?: ast.Visitor
|
|
290
327
|
/**
|
|
291
|
-
*
|
|
328
|
+
* Custom generators that run alongside the built-in React Query generators.
|
|
292
329
|
*/
|
|
293
330
|
generators?: Array<Generator<PluginReactQuery>>
|
|
294
331
|
}
|
|
295
332
|
|
|
296
333
|
type ResolvedOptions = {
|
|
297
334
|
output: Output
|
|
298
|
-
group: Group |
|
|
335
|
+
group: Group | null
|
|
299
336
|
exclude: NonNullable<Options['exclude']>
|
|
300
337
|
include: Options['include']
|
|
301
338
|
override: NonNullable<Options['override']>
|
|
@@ -309,11 +346,11 @@ type ResolvedOptions = {
|
|
|
309
346
|
*/
|
|
310
347
|
infinite: NonNullable<Infinite> | false
|
|
311
348
|
suspense: Suspense | false
|
|
312
|
-
queryKey: QueryKey |
|
|
349
|
+
queryKey: QueryKey | null
|
|
313
350
|
query: NonNullable<Required<Query>> | false
|
|
314
|
-
mutationKey: MutationKey |
|
|
351
|
+
mutationKey: MutationKey | null
|
|
315
352
|
mutation: NonNullable<Required<Mutation>> | false
|
|
316
|
-
customOptions: NonNullable<Required<CustomOptions>> |
|
|
353
|
+
customOptions: NonNullable<Required<CustomOptions>> | null
|
|
317
354
|
resolver: ResolverReactQuery
|
|
318
355
|
}
|
|
319
356
|
|