@kubb/plugin-react-query 5.0.0-beta.22 → 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-D4SQmw7N.cjs → components-C1_zAoAO.cjs} +51 -51
- package/dist/components-C1_zAoAO.cjs.map +1 -0
- package/dist/{components-BTwB9V-K.js → components-C91DnOOV.js} +51 -51
- 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-BZ_sX2lp.js → generators-9srJC_zb.js} +97 -57
- package/dist/generators-9srJC_zb.js.map +1 -0
- package/dist/{generators-C4bV7v9Z.cjs → generators-DS3JH1hR.cjs} +97 -57
- 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 +8 -8
- 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 +8 -8
- package/src/components/SuspenseQuery.tsx +1 -1
- package/src/generators/customHookOptionsFileGenerator.tsx +7 -1
- package/src/generators/hookOptionsGenerator.tsx +14 -8
- package/src/generators/infiniteQueryGenerator.tsx +19 -10
- package/src/generators/mutationGenerator.tsx +17 -9
- package/src/generators/queryGenerator.tsx +17 -9
- package/src/generators/suspenseInfiniteQueryGenerator.tsx +19 -10
- package/src/generators/suspenseQueryGenerator.tsx +18 -9
- package/src/plugin.ts +34 -5
- package/src/resolvers/resolverReactQuery.ts +15 -4
- package/src/types.ts +89 -52
- package/dist/components-BTwB9V-K.js.map +0 -1
- package/dist/components-D4SQmw7N.cjs.map +0 -1
- package/dist/generators-BZ_sX2lp.js.map +0 -1
- package/dist/generators-C4bV7v9Z.cjs.map +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kubb/plugin-react-query",
|
|
3
|
-
"version": "5.0.0-beta.
|
|
3
|
+
"version": "5.0.0-beta.25",
|
|
4
4
|
"description": "Generate type-safe TanStack Query (React Query) hooks from your OpenAPI specification. Covers useQuery, useMutation, useInfiniteQuery, and queryOptions with full TypeScript support.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"code-generation",
|
|
@@ -68,12 +68,12 @@
|
|
|
68
68
|
"registry": "https://registry.npmjs.org/"
|
|
69
69
|
},
|
|
70
70
|
"dependencies": {
|
|
71
|
-
"@kubb/core": "5.0.0-beta.
|
|
72
|
-
"@kubb/renderer-jsx": "5.0.0-beta.
|
|
71
|
+
"@kubb/core": "5.0.0-beta.25",
|
|
72
|
+
"@kubb/renderer-jsx": "5.0.0-beta.25",
|
|
73
73
|
"remeda": "^2.34.1",
|
|
74
|
-
"@kubb/plugin-client": "5.0.0-beta.
|
|
75
|
-
"@kubb/plugin-ts": "5.0.0-beta.
|
|
76
|
-
"@kubb/plugin-zod": "5.0.0-beta.
|
|
74
|
+
"@kubb/plugin-client": "5.0.0-beta.25",
|
|
75
|
+
"@kubb/plugin-ts": "5.0.0-beta.25",
|
|
76
|
+
"@kubb/plugin-zod": "5.0.0-beta.25"
|
|
77
77
|
},
|
|
78
78
|
"devDependencies": {
|
|
79
79
|
"@internals/shared": "0.0.0",
|
|
@@ -81,7 +81,7 @@
|
|
|
81
81
|
"@internals/utils": "0.0.0"
|
|
82
82
|
},
|
|
83
83
|
"peerDependencies": {
|
|
84
|
-
"@kubb/renderer-jsx": "5.0.0-beta.
|
|
84
|
+
"@kubb/renderer-jsx": "5.0.0-beta.25"
|
|
85
85
|
},
|
|
86
86
|
"size-limit": [
|
|
87
87
|
{
|
|
@@ -39,7 +39,7 @@ function buildInfiniteQueryParamsNode(
|
|
|
39
39
|
},
|
|
40
40
|
): ast.FunctionParametersNode {
|
|
41
41
|
const { paramsType, paramsCasing, pathParamsType, resolver, pageParamGeneric } = options
|
|
42
|
-
const requestName = node.requestBody?.content?.[0]?.schema ? resolver.resolveDataName(node) :
|
|
42
|
+
const requestName = node.requestBody?.content?.[0]?.schema ? resolver.resolveDataName(node) : null
|
|
43
43
|
|
|
44
44
|
const optionsParam = ast.createFunctionParameter({
|
|
45
45
|
name: 'options',
|
|
@@ -104,11 +104,11 @@ export function InfiniteQuery({
|
|
|
104
104
|
? (() => {
|
|
105
105
|
const groupName = tsResolver.resolveQueryParamsName(node, rawQueryParams[0]!)
|
|
106
106
|
const individualName = tsResolver.resolveParamName(node, rawQueryParams[0]!)
|
|
107
|
-
return groupName !== individualName ? groupName :
|
|
107
|
+
return groupName !== individualName ? groupName : null
|
|
108
108
|
})()
|
|
109
|
-
:
|
|
109
|
+
: null
|
|
110
110
|
|
|
111
|
-
const queryParamType = queryParam && queryParamsTypeName ? `${queryParamsTypeName}['${queryParam}']` :
|
|
111
|
+
const queryParamType = queryParam && queryParamsTypeName ? `${queryParamsTypeName}['${queryParam}']` : null
|
|
112
112
|
const pageParamType = queryParamType ? (isInitialPageParamDefined ? `NonNullable<${queryParamType}>` : queryParamType) : fallbackPageParamType
|
|
113
113
|
|
|
114
114
|
const returnType = 'UseInfiniteQueryResult<TData, TError> & { queryKey: TQueryKey }'
|
|
@@ -72,11 +72,11 @@ export function InfiniteQueryOptions({
|
|
|
72
72
|
? (() => {
|
|
73
73
|
const groupName = tsResolver.resolveQueryParamsName(node, rawQueryParams[0]!)
|
|
74
74
|
const individualName = tsResolver.resolveParamName(node, rawQueryParams[0]!)
|
|
75
|
-
return groupName !== individualName ? groupName :
|
|
75
|
+
return groupName !== individualName ? groupName : null
|
|
76
76
|
})()
|
|
77
|
-
:
|
|
77
|
+
: null
|
|
78
78
|
|
|
79
|
-
const queryParamType = queryParam && queryParamsTypeName ? `${queryParamsTypeName}['${queryParam}']` :
|
|
79
|
+
const queryParamType = queryParam && queryParamsTypeName ? `${queryParamsTypeName}['${queryParam}']` : null
|
|
80
80
|
const pageParamType = queryParamType ? (isInitialPageParamDefined ? `NonNullable<${queryParamType}>` : queryParamType) : fallbackPageParamType
|
|
81
81
|
|
|
82
82
|
const paramsNode = getQueryOptionsParams(node, { paramsType, paramsCasing, pathParamsType, resolver: tsResolver })
|
|
@@ -90,15 +90,15 @@ export function InfiniteQueryOptions({
|
|
|
90
90
|
const enabledSource = buildEnabledCheck(queryKeyParamsNode)
|
|
91
91
|
const enabledText = enabledSource ? `enabled: !!(${enabledSource}),` : ''
|
|
92
92
|
|
|
93
|
-
const hasNewParams = nextParam
|
|
93
|
+
const hasNewParams = nextParam != null || previousParam != null
|
|
94
94
|
|
|
95
95
|
const [getNextPageParamExpr, getPreviousPageParamExpr] = (() => {
|
|
96
96
|
if (hasNewParams) {
|
|
97
|
-
const nextAccessor = nextParam ? getNestedAccessor(nextParam, 'lastPage') :
|
|
98
|
-
const prevAccessor = previousParam ? getNestedAccessor(previousParam, 'firstPage') :
|
|
97
|
+
const nextAccessor = nextParam ? getNestedAccessor(nextParam, 'lastPage') : null
|
|
98
|
+
const prevAccessor = previousParam ? getNestedAccessor(previousParam, 'firstPage') : null
|
|
99
99
|
return [
|
|
100
|
-
nextAccessor ? `getNextPageParam: (lastPage) => ${nextAccessor}` :
|
|
101
|
-
prevAccessor ? `getPreviousPageParam: (firstPage) => ${prevAccessor}` :
|
|
100
|
+
nextAccessor ? `getNextPageParam: (lastPage) => ${nextAccessor}` : null,
|
|
101
|
+
prevAccessor ? `getPreviousPageParam: (firstPage) => ${prevAccessor}` : null,
|
|
102
102
|
] as const
|
|
103
103
|
}
|
|
104
104
|
if (cursorParam) {
|
|
@@ -58,7 +58,7 @@ function buildMutationParamsNode(
|
|
|
58
58
|
resolver,
|
|
59
59
|
})
|
|
60
60
|
const TRequest = mutationArgParamsNode.params.length > 0 ? (declarationPrinter.print(mutationArgParamsNode) ?? '') : ''
|
|
61
|
-
const generics = [TData, TError, TRequest ? `{${TRequest}}` : '
|
|
61
|
+
const generics = [TData, TError, TRequest ? `{${TRequest}}` : 'undefined', 'TContext'].join(', ')
|
|
62
62
|
|
|
63
63
|
return ast.createFunctionParameters({
|
|
64
64
|
params: [
|
|
@@ -89,7 +89,7 @@ export function Mutation({ name, mutationOptionsName, paramsCasing, dataReturnTy
|
|
|
89
89
|
resolver: tsResolver,
|
|
90
90
|
})
|
|
91
91
|
const TRequest = mutationArgParamsNode.params.length > 0 ? (declarationPrinter.print(mutationArgParamsNode) ?? '') : ''
|
|
92
|
-
const generics = [TData, TError, TRequest ? `{${TRequest}}` : '
|
|
92
|
+
const generics = [TData, TError, TRequest ? `{${TRequest}}` : 'undefined', 'TContext'].join(', ')
|
|
93
93
|
const returnType = `UseMutationResult<${generics}>`
|
|
94
94
|
|
|
95
95
|
const mutationOptionsConfigNode = buildMutationConfigParamsNode(node, tsResolver)
|
|
@@ -90,7 +90,7 @@ export function MutationOptions({
|
|
|
90
90
|
<Function name={name} export params={paramsSignature} generics={['TContext = unknown']}>
|
|
91
91
|
{`
|
|
92
92
|
const mutationKey = ${mutationKeyName}()
|
|
93
|
-
return mutationOptions<${TData}, ${TError}, ${TRequest ? `{${TRequest}}` : '
|
|
93
|
+
return mutationOptions<${TData}, ${TError}, ${TRequest ? `{${TRequest}}` : 'undefined'}, TContext>({
|
|
94
94
|
mutationKey,
|
|
95
95
|
mutationFn: async(${hasMutationParams ? `{ ${argKeysStr} }` : '_'}) => {
|
|
96
96
|
return ${clientName}(${clientCallStr})
|
package/src/components/Query.tsx
CHANGED
|
@@ -36,7 +36,7 @@ function buildQueryParamsNode(
|
|
|
36
36
|
): ast.FunctionParametersNode {
|
|
37
37
|
const { paramsType, paramsCasing, pathParamsType, dataReturnType, resolver } = options
|
|
38
38
|
const responseName = resolver.resolveResponseName(node)
|
|
39
|
-
const requestName = node.requestBody?.content?.[0]?.schema ? resolver.resolveDataName(node) :
|
|
39
|
+
const requestName = node.requestBody?.content?.[0]?.schema ? resolver.resolveDataName(node) : null
|
|
40
40
|
const errorNames = resolveErrorNames(node, resolver)
|
|
41
41
|
|
|
42
42
|
const TData = dataReturnType === 'data' ? responseName : `ResponseConfig<${responseName}>`
|
|
@@ -32,7 +32,7 @@ export function getQueryOptionsParams(
|
|
|
32
32
|
},
|
|
33
33
|
): ast.FunctionParametersNode {
|
|
34
34
|
const { paramsType, paramsCasing, pathParamsType, resolver } = options
|
|
35
|
-
const requestName = node.requestBody?.content?.[0]?.schema ? resolver.resolveDataName(node) :
|
|
35
|
+
const requestName = node.requestBody?.content?.[0]?.schema ? resolver.resolveDataName(node) : null
|
|
36
36
|
|
|
37
37
|
return ast.createOperationParams(node, {
|
|
38
38
|
paramsType,
|
|
@@ -39,7 +39,7 @@ function buildSuspenseInfiniteQueryParamsNode(
|
|
|
39
39
|
},
|
|
40
40
|
): ast.FunctionParametersNode {
|
|
41
41
|
const { paramsType, paramsCasing, pathParamsType, resolver, pageParamGeneric } = options
|
|
42
|
-
const requestName = node.requestBody?.content?.[0]?.schema ? resolver.resolveDataName(node) :
|
|
42
|
+
const requestName = node.requestBody?.content?.[0]?.schema ? resolver.resolveDataName(node) : null
|
|
43
43
|
|
|
44
44
|
const optionsParam = ast.createFunctionParameter({
|
|
45
45
|
name: 'options',
|
|
@@ -104,11 +104,11 @@ export function SuspenseInfiniteQuery({
|
|
|
104
104
|
? (() => {
|
|
105
105
|
const groupName = tsResolver.resolveQueryParamsName(node, rawQueryParams[0]!)
|
|
106
106
|
const individualName = tsResolver.resolveParamName(node, rawQueryParams[0]!)
|
|
107
|
-
return groupName !== individualName ? groupName :
|
|
107
|
+
return groupName !== individualName ? groupName : null
|
|
108
108
|
})()
|
|
109
|
-
:
|
|
109
|
+
: null
|
|
110
110
|
|
|
111
|
-
const queryParamType = queryParam && queryParamsTypeName ? `${queryParamsTypeName}['${queryParam}']` :
|
|
111
|
+
const queryParamType = queryParam && queryParamsTypeName ? `${queryParamsTypeName}['${queryParam}']` : null
|
|
112
112
|
const pageParamType = queryParamType ? (isInitialPageParamDefined ? `NonNullable<${queryParamType}>` : queryParamType) : fallbackPageParamType
|
|
113
113
|
|
|
114
114
|
const returnType = 'UseSuspenseInfiniteQueryResult<TData, TError> & { queryKey: TQueryKey }'
|
|
@@ -72,11 +72,11 @@ export function SuspenseInfiniteQueryOptions({
|
|
|
72
72
|
? (() => {
|
|
73
73
|
const groupName = tsResolver.resolveQueryParamsName(node, rawQueryParams[0]!)
|
|
74
74
|
const individualName = tsResolver.resolveParamName(node, rawQueryParams[0]!)
|
|
75
|
-
return groupName !== individualName ? groupName :
|
|
75
|
+
return groupName !== individualName ? groupName : null
|
|
76
76
|
})()
|
|
77
|
-
:
|
|
77
|
+
: null
|
|
78
78
|
|
|
79
|
-
const queryParamType = queryParam && queryParamsTypeName ? `${queryParamsTypeName}['${queryParam}']` :
|
|
79
|
+
const queryParamType = queryParam && queryParamsTypeName ? `${queryParamsTypeName}['${queryParam}']` : null
|
|
80
80
|
const pageParamType = queryParamType ? (isInitialPageParamDefined ? `NonNullable<${queryParamType}>` : queryParamType) : fallbackPageParamType
|
|
81
81
|
|
|
82
82
|
const paramsNode = getQueryOptionsParams(node, { paramsType, paramsCasing, pathParamsType, resolver: tsResolver })
|
|
@@ -90,15 +90,15 @@ export function SuspenseInfiniteQueryOptions({
|
|
|
90
90
|
const enabledSource = buildEnabledCheck(queryKeyParamsNode)
|
|
91
91
|
const enabledText = enabledSource ? `enabled: !!(${enabledSource}),` : ''
|
|
92
92
|
|
|
93
|
-
const hasNewParams = nextParam
|
|
93
|
+
const hasNewParams = nextParam != null || previousParam != null
|
|
94
94
|
|
|
95
95
|
const [getNextPageParamExpr, getPreviousPageParamExpr] = (() => {
|
|
96
96
|
if (hasNewParams) {
|
|
97
|
-
const nextAccessor = nextParam ? getNestedAccessor(nextParam, 'lastPage') :
|
|
98
|
-
const prevAccessor = previousParam ? getNestedAccessor(previousParam, 'firstPage') :
|
|
97
|
+
const nextAccessor = nextParam ? getNestedAccessor(nextParam, 'lastPage') : null
|
|
98
|
+
const prevAccessor = previousParam ? getNestedAccessor(previousParam, 'firstPage') : null
|
|
99
99
|
return [
|
|
100
|
-
nextAccessor ? `getNextPageParam: (lastPage) => ${nextAccessor}` :
|
|
101
|
-
prevAccessor ? `getPreviousPageParam: (firstPage) => ${prevAccessor}` :
|
|
100
|
+
nextAccessor ? `getNextPageParam: (lastPage) => ${nextAccessor}` : null,
|
|
101
|
+
prevAccessor ? `getPreviousPageParam: (firstPage) => ${prevAccessor}` : null,
|
|
102
102
|
] as const
|
|
103
103
|
}
|
|
104
104
|
if (cursorParam) {
|
|
@@ -36,7 +36,7 @@ function buildSuspenseQueryParamsNode(
|
|
|
36
36
|
): ast.FunctionParametersNode {
|
|
37
37
|
const { paramsType, paramsCasing, pathParamsType, dataReturnType, resolver } = options
|
|
38
38
|
const responseName = resolver.resolveResponseName(node)
|
|
39
|
-
const requestName = node.requestBody?.content?.[0]?.schema ? resolver.resolveDataName(node) :
|
|
39
|
+
const requestName = node.requestBody?.content?.[0]?.schema ? resolver.resolveDataName(node) : null
|
|
40
40
|
const errorNames = resolveErrorNames(node, resolver)
|
|
41
41
|
|
|
42
42
|
const TData = dataReturnType === 'data' ? responseName : `ResponseConfig<${responseName}>`
|
|
@@ -5,6 +5,12 @@ import { defineGenerator } from '@kubb/core'
|
|
|
5
5
|
import { File, Function, jsxRendererSync } from '@kubb/renderer-jsx'
|
|
6
6
|
import type { PluginReactQuery } from '../types'
|
|
7
7
|
|
|
8
|
+
/**
|
|
9
|
+
* Scaffolds the user-editable `useCustomHookOptions` file when
|
|
10
|
+
* `pluginReactQuery({ customOptions: { ... } })` is configured. The file is
|
|
11
|
+
* only created when it does not already exist, so user edits persist across
|
|
12
|
+
* regeneration.
|
|
13
|
+
*/
|
|
8
14
|
export const customHookOptionsFileGenerator = defineGenerator<PluginReactQuery>({
|
|
9
15
|
name: 'react-query-custom-hook-options-file',
|
|
10
16
|
renderer: jsxRendererSync,
|
|
@@ -27,7 +33,7 @@ export const customHookOptionsFileGenerator = defineGenerator<PluginReactQuery>(
|
|
|
27
33
|
const hookName = resolver.resolveQueryName(firstNode)
|
|
28
34
|
const hookFile = resolver.resolveFile(
|
|
29
35
|
{ name: hookName, extname: '.ts', tag: firstNode.tags[0] ?? 'default', path: firstNode.path },
|
|
30
|
-
{ root, output, group },
|
|
36
|
+
{ root, output, group: group ?? undefined },
|
|
31
37
|
)
|
|
32
38
|
hookFilePath = hookFile.path
|
|
33
39
|
} else {
|
|
@@ -9,6 +9,12 @@ import { resolveOperationOverrides } from '../utils.ts'
|
|
|
9
9
|
type QueryOption = PluginReactQuery['resolvedOptions']['query']
|
|
10
10
|
type MutationOption = PluginReactQuery['resolvedOptions']['mutation']
|
|
11
11
|
|
|
12
|
+
/**
|
|
13
|
+
* Emits the `HookOptions` type used by `customOptions`. Enabled when
|
|
14
|
+
* `pluginReactQuery({ customOptions: { ... } })`. The generated type lists
|
|
15
|
+
* every hook keyed by name so user-supplied options stay in sync with the
|
|
16
|
+
* generated hooks at compile time.
|
|
17
|
+
*/
|
|
12
18
|
export const hookOptionsGenerator = defineGenerator<PluginReactQuery>({
|
|
13
19
|
name: 'react-query-hook-options',
|
|
14
20
|
renderer: jsxRendererSync,
|
|
@@ -19,14 +25,14 @@ export const hookOptionsGenerator = defineGenerator<PluginReactQuery>({
|
|
|
19
25
|
if (!customOptions) return null
|
|
20
26
|
|
|
21
27
|
const name = resolver.resolveHookOptionsName()
|
|
22
|
-
const resolvedFile = resolver.resolveFile({ name, extname: '.ts' }, { root, output, group })
|
|
28
|
+
const resolvedFile = resolver.resolveFile({ name, extname: '.ts' }, { root, output, group: group ?? undefined })
|
|
23
29
|
const hookOptionsFile = {
|
|
24
30
|
...resolvedFile,
|
|
25
31
|
baseName: `${name}.ts` as const,
|
|
26
32
|
path: resolvedFile.path.replace(/[^/\\]+\.ts$/, `${name}.ts`),
|
|
27
33
|
}
|
|
28
34
|
|
|
29
|
-
const imports: KubbReactNode
|
|
35
|
+
const imports: Array<KubbReactNode> = []
|
|
30
36
|
const hookOptions: Record<string, string> = {}
|
|
31
37
|
|
|
32
38
|
for (const node of nodes) {
|
|
@@ -34,7 +40,7 @@ export const hookOptionsGenerator = defineGenerator<PluginReactQuery>({
|
|
|
34
40
|
const nodeQuery: QueryOption = 'query' in opOverrides ? (opOverrides.query as QueryOption) : query
|
|
35
41
|
const nodeMutation: MutationOption = 'mutation' in opOverrides ? (opOverrides.mutation as MutationOption) : mutation
|
|
36
42
|
const nodeInfinite = 'infinite' in opOverrides ? opOverrides.infinite : infinite
|
|
37
|
-
const nodeInfiniteOptions = nodeInfinite && typeof nodeInfinite === 'object' ? nodeInfinite :
|
|
43
|
+
const nodeInfiniteOptions = nodeInfinite && typeof nodeInfinite === 'object' ? nodeInfinite : null
|
|
38
44
|
|
|
39
45
|
// query: false means "still a query but skip the useQuery hook"
|
|
40
46
|
const isQueryOp =
|
|
@@ -53,7 +59,7 @@ export const hookOptionsGenerator = defineGenerator<PluginReactQuery>({
|
|
|
53
59
|
const queryHookName = resolver.resolveQueryName(node)
|
|
54
60
|
const queryHookFile = resolver.resolveFile(
|
|
55
61
|
{ name: queryHookName, extname: '.ts', tag: node.tags[0] ?? 'default', path: node.path },
|
|
56
|
-
{ root, output, group },
|
|
62
|
+
{ root, output, group: group ?? undefined },
|
|
57
63
|
)
|
|
58
64
|
imports.push(<File.Import name={[queryOptionsName]} root={hookOptionsFile.path} path={queryHookFile.path} />)
|
|
59
65
|
hookOptions[queryHookName] = `Partial<ReturnType<typeof ${queryOptionsName}>>`
|
|
@@ -63,7 +69,7 @@ export const hookOptionsGenerator = defineGenerator<PluginReactQuery>({
|
|
|
63
69
|
const suspenseHookName = resolver.resolveSuspenseQueryName(node)
|
|
64
70
|
const suspenseHookFile = resolver.resolveFile(
|
|
65
71
|
{ name: suspenseHookName, extname: '.ts', tag: node.tags[0] ?? 'default', path: node.path },
|
|
66
|
-
{ root, output, group },
|
|
72
|
+
{ root, output, group: group ?? undefined },
|
|
67
73
|
)
|
|
68
74
|
imports.push(<File.Import name={[suspenseOptionsName]} root={hookOptionsFile.path} path={suspenseHookFile.path} />)
|
|
69
75
|
hookOptions[suspenseHookName] = `Partial<ReturnType<typeof ${suspenseOptionsName}>>`
|
|
@@ -80,7 +86,7 @@ export const hookOptionsGenerator = defineGenerator<PluginReactQuery>({
|
|
|
80
86
|
const infiniteHookName = resolver.resolveInfiniteQueryName(node)
|
|
81
87
|
const infiniteHookFile = resolver.resolveFile(
|
|
82
88
|
{ name: infiniteHookName, extname: '.ts', tag: node.tags[0] ?? 'default', path: node.path },
|
|
83
|
-
{ root, output, group },
|
|
89
|
+
{ root, output, group: group ?? undefined },
|
|
84
90
|
)
|
|
85
91
|
imports.push(<File.Import name={[infiniteOptionsName]} root={hookOptionsFile.path} path={infiniteHookFile.path} />)
|
|
86
92
|
hookOptions[infiniteHookName] = `Partial<ReturnType<typeof ${infiniteOptionsName}>>`
|
|
@@ -90,7 +96,7 @@ export const hookOptionsGenerator = defineGenerator<PluginReactQuery>({
|
|
|
90
96
|
const suspenseInfiniteHookName = resolver.resolveSuspenseInfiniteQueryName(node)
|
|
91
97
|
const suspenseInfiniteHookFile = resolver.resolveFile(
|
|
92
98
|
{ name: suspenseInfiniteHookName, extname: '.ts', tag: node.tags[0] ?? 'default', path: node.path },
|
|
93
|
-
{ root, output, group },
|
|
99
|
+
{ root, output, group: group ?? undefined },
|
|
94
100
|
)
|
|
95
101
|
imports.push(<File.Import name={[suspenseInfiniteOptionsName]} root={hookOptionsFile.path} path={suspenseInfiniteHookFile.path} />)
|
|
96
102
|
hookOptions[suspenseInfiniteHookName] = `Partial<ReturnType<typeof ${suspenseInfiniteOptionsName}>>`
|
|
@@ -104,7 +110,7 @@ export const hookOptionsGenerator = defineGenerator<PluginReactQuery>({
|
|
|
104
110
|
const mutationHookName = resolver.resolveMutationName(node)
|
|
105
111
|
const mutationHookFile = resolver.resolveFile(
|
|
106
112
|
{ name: mutationHookName, extname: '.ts', tag: node.tags[0] ?? 'default', path: node.path },
|
|
107
|
-
{ root, output, group },
|
|
113
|
+
{ root, output, group: group ?? undefined },
|
|
108
114
|
)
|
|
109
115
|
imports.push(<File.Import name={[mutationOptionsName]} root={hookOptionsFile.path} path={mutationHookFile.path} />)
|
|
110
116
|
hookOptions[mutationHookName] = `Partial<ReturnType<typeof ${mutationOptionsName}>>`
|
|
@@ -10,6 +10,12 @@ import { difference } from 'remeda'
|
|
|
10
10
|
import { InfiniteQuery, InfiniteQueryOptions, QueryKey } from '../components'
|
|
11
11
|
import type { PluginReactQuery } from '../types'
|
|
12
12
|
|
|
13
|
+
/**
|
|
14
|
+
* Built-in generator for `useInfiniteQuery` hooks. Enabled when
|
|
15
|
+
* `pluginReactQuery({ infinite: { ... } })`. Emits one `useFooInfiniteQuery`
|
|
16
|
+
* hook per query operation, wiring the configured `nextParam` /
|
|
17
|
+
* `previousParam` paths into TanStack Query's cursor-based pagination.
|
|
18
|
+
*/
|
|
13
19
|
export const infiniteQueryGenerator = defineGenerator<PluginReactQuery>({
|
|
14
20
|
name: 'react-infinite-query',
|
|
15
21
|
renderer: jsxRendererSync,
|
|
@@ -26,7 +32,7 @@ export const infiniteQueryGenerator = defineGenerator<PluginReactQuery>({
|
|
|
26
32
|
mutation !== false &&
|
|
27
33
|
!isQuery &&
|
|
28
34
|
difference(mutation ? mutation.methods : [], query ? query.methods : []).some((method) => node.method.toLowerCase() === method.toLowerCase())
|
|
29
|
-
const infiniteOptions = infinite && typeof infinite === 'object' ? infinite :
|
|
35
|
+
const infiniteOptions = infinite && typeof infinite === 'object' ? infinite : null
|
|
30
36
|
|
|
31
37
|
if (!isQuery || isMutation || !infiniteOptions) return null
|
|
32
38
|
|
|
@@ -48,10 +54,13 @@ export const infiniteQueryGenerator = defineGenerator<PluginReactQuery>({
|
|
|
48
54
|
const clientBaseName = resolver.resolveInfiniteClientName(node)
|
|
49
55
|
|
|
50
56
|
const meta = {
|
|
51
|
-
file: resolver.resolveFile(
|
|
57
|
+
file: resolver.resolveFile(
|
|
58
|
+
{ name: queryName, extname: '.ts', tag: node.tags[0] ?? 'default', path: node.path },
|
|
59
|
+
{ root, output, group: group ?? undefined },
|
|
60
|
+
),
|
|
52
61
|
fileTs: tsResolver.resolveFile(
|
|
53
62
|
{ name: node.operationId, extname: '.ts', tag: node.tags[0] ?? 'default', path: node.path },
|
|
54
|
-
{ root, output: pluginTs.options?.output ?? output, group: pluginTs.options?.group },
|
|
63
|
+
{ root, output: pluginTs.options?.output ?? output, group: pluginTs.options?.group ?? undefined },
|
|
55
64
|
),
|
|
56
65
|
}
|
|
57
66
|
|
|
@@ -61,20 +70,20 @@ export const infiniteQueryGenerator = defineGenerator<PluginReactQuery>({
|
|
|
61
70
|
order: 'body-response-first',
|
|
62
71
|
})
|
|
63
72
|
|
|
64
|
-
const pluginZod = parser === 'zod' ? driver.getPlugin(pluginZodName) :
|
|
65
|
-
const zodResolver = pluginZod ? driver.getResolver(pluginZodName) :
|
|
73
|
+
const pluginZod = parser === 'zod' ? driver.getPlugin(pluginZodName) : null
|
|
74
|
+
const zodResolver = pluginZod ? driver.getResolver(pluginZodName) : null
|
|
66
75
|
const fileZod = zodResolver
|
|
67
76
|
? zodResolver.resolveFile(
|
|
68
77
|
{ name: node.operationId, extname: '.ts', tag: node.tags[0] ?? 'default', path: node.path },
|
|
69
|
-
{ root, output: pluginZod?.options?.output ?? output, group: pluginZod?.options?.group },
|
|
78
|
+
{ root, output: pluginZod?.options?.output ?? output, group: pluginZod?.options?.group ?? undefined },
|
|
70
79
|
)
|
|
71
|
-
:
|
|
80
|
+
: null
|
|
72
81
|
const zodSchemaNames = resolveZodSchemaNames(node, zodResolver)
|
|
73
82
|
|
|
74
83
|
const clientPlugin = driver.getPlugin(pluginClientName)
|
|
75
84
|
const hasClientPlugin = clientPlugin?.name === pluginClientName
|
|
76
85
|
const shouldUseClientPlugin = hasClientPlugin && clientOptions.clientType !== 'class'
|
|
77
|
-
const clientResolver = shouldUseClientPlugin ? driver.getResolver(pluginClientName) :
|
|
86
|
+
const clientResolver = shouldUseClientPlugin ? driver.getResolver(pluginClientName) : null
|
|
78
87
|
|
|
79
88
|
const clientFile = shouldUseClientPlugin
|
|
80
89
|
? clientResolver?.resolveFile(
|
|
@@ -82,10 +91,10 @@ export const infiniteQueryGenerator = defineGenerator<PluginReactQuery>({
|
|
|
82
91
|
{
|
|
83
92
|
root,
|
|
84
93
|
output: clientPlugin?.options?.output ?? output,
|
|
85
|
-
group: clientPlugin?.options?.group,
|
|
94
|
+
group: clientPlugin?.options?.group ?? undefined,
|
|
86
95
|
},
|
|
87
96
|
)
|
|
88
|
-
:
|
|
97
|
+
: null
|
|
89
98
|
|
|
90
99
|
const resolvedClientName = shouldUseClientPlugin ? (clientResolver?.resolveName(node.operationId) ?? clientBaseName) : clientBaseName
|
|
91
100
|
|
|
@@ -10,6 +10,11 @@ import { difference } from 'remeda'
|
|
|
10
10
|
import { Mutation, MutationKey, MutationOptions } from '../components'
|
|
11
11
|
import type { PluginReactQuery } from '../types'
|
|
12
12
|
|
|
13
|
+
/**
|
|
14
|
+
* Built-in generator for `useMutation` hooks. Emits one `useFooMutation` hook
|
|
15
|
+
* per POST/PUT/DELETE operation (configurable via `mutation.methods`) plus
|
|
16
|
+
* the matching `fooMutationKey` / `fooMutationOptions` helpers.
|
|
17
|
+
*/
|
|
13
18
|
export const mutationGenerator = defineGenerator<PluginReactQuery>({
|
|
14
19
|
name: 'react-query-mutation',
|
|
15
20
|
renderer: jsxRendererSync,
|
|
@@ -38,29 +43,32 @@ export const mutationGenerator = defineGenerator<PluginReactQuery>({
|
|
|
38
43
|
const clientName = resolver.resolveClientName(node)
|
|
39
44
|
|
|
40
45
|
const meta = {
|
|
41
|
-
file: resolver.resolveFile(
|
|
46
|
+
file: resolver.resolveFile(
|
|
47
|
+
{ name: mutationHookName, extname: '.ts', tag: node.tags[0] ?? 'default', path: node.path },
|
|
48
|
+
{ root, output, group: group ?? undefined },
|
|
49
|
+
),
|
|
42
50
|
fileTs: tsResolver.resolveFile(
|
|
43
51
|
{ name: node.operationId, extname: '.ts', tag: node.tags[0] ?? 'default', path: node.path },
|
|
44
|
-
{ root, output: pluginTs.options?.output ?? output, group: pluginTs.options?.group },
|
|
52
|
+
{ root, output: pluginTs.options?.output ?? output, group: pluginTs.options?.group ?? undefined },
|
|
45
53
|
),
|
|
46
54
|
}
|
|
47
55
|
|
|
48
56
|
const importedTypeNames = resolveOperationTypeNames(node, tsResolver, { paramsCasing, order: 'body-response-first' })
|
|
49
57
|
|
|
50
|
-
const pluginZod = parser === 'zod' ? driver.getPlugin(pluginZodName) :
|
|
51
|
-
const zodResolver = pluginZod ? driver.getResolver(pluginZodName) :
|
|
58
|
+
const pluginZod = parser === 'zod' ? driver.getPlugin(pluginZodName) : null
|
|
59
|
+
const zodResolver = pluginZod ? driver.getResolver(pluginZodName) : null
|
|
52
60
|
const fileZod = zodResolver
|
|
53
61
|
? zodResolver.resolveFile(
|
|
54
62
|
{ name: node.operationId, extname: '.ts', tag: node.tags[0] ?? 'default', path: node.path },
|
|
55
|
-
{ root, output: pluginZod?.options?.output ?? output, group: pluginZod?.options?.group },
|
|
63
|
+
{ root, output: pluginZod?.options?.output ?? output, group: pluginZod?.options?.group ?? undefined },
|
|
56
64
|
)
|
|
57
|
-
:
|
|
65
|
+
: null
|
|
58
66
|
const zodSchemaNames = resolveZodSchemaNames(node, zodResolver)
|
|
59
67
|
|
|
60
68
|
const clientPlugin = driver.getPlugin(pluginClientName)
|
|
61
69
|
const hasClientPlugin = clientPlugin?.name === pluginClientName
|
|
62
70
|
const shouldUseClientPlugin = hasClientPlugin && clientOptions.clientType !== 'class'
|
|
63
|
-
const clientResolver = shouldUseClientPlugin ? driver.getResolver(pluginClientName) :
|
|
71
|
+
const clientResolver = shouldUseClientPlugin ? driver.getResolver(pluginClientName) : null
|
|
64
72
|
|
|
65
73
|
const clientFile = shouldUseClientPlugin
|
|
66
74
|
? clientResolver?.resolveFile(
|
|
@@ -68,10 +76,10 @@ export const mutationGenerator = defineGenerator<PluginReactQuery>({
|
|
|
68
76
|
{
|
|
69
77
|
root,
|
|
70
78
|
output: clientPlugin?.options?.output ?? output,
|
|
71
|
-
group: clientPlugin?.options?.group,
|
|
79
|
+
group: clientPlugin?.options?.group ?? undefined,
|
|
72
80
|
},
|
|
73
81
|
)
|
|
74
|
-
:
|
|
82
|
+
: null
|
|
75
83
|
|
|
76
84
|
const resolvedClientName = shouldUseClientPlugin ? (clientResolver?.resolveName(node.operationId) ?? clientName) : clientName
|
|
77
85
|
|
|
@@ -10,6 +10,11 @@ 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,
|
|
@@ -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
|
|
|
@@ -10,6 +10,12 @@ 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,
|
|
@@ -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
|
|