@kubb/plugin-react-query 5.0.0-beta.3 → 5.0.0-beta.31
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/README.md +34 -83
- package/dist/{components-DTGLu4UV.js → components-BVmVgpLX.js} +379 -279
- package/dist/components-BVmVgpLX.js.map +1 -0
- package/dist/{components-dAKJEn9b.cjs → components-DLUeLMsz.cjs} +409 -279
- package/dist/components-DLUeLMsz.cjs.map +1 -0
- package/dist/components.cjs +1 -1
- package/dist/components.d.ts +4 -76
- package/dist/components.js +1 -1
- package/dist/{generators-CWEQsdO9.cjs → generators--AcF4Y4n.cjs} +332 -410
- package/dist/generators--AcF4Y4n.cjs.map +1 -0
- package/dist/{generators-C_fbcjpG.js → generators-BFn9CLBS.js} +333 -411
- package/dist/generators-BFn9CLBS.js.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 +179 -26
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +30 -1
- package/dist/index.js +179 -26
- package/dist/index.js.map +1 -1
- package/dist/types-DiZPLTXl.d.ts +400 -0
- package/extension.yaml +1507 -0
- package/package.json +16 -18
- package/src/components/InfiniteQuery.tsx +24 -13
- package/src/components/InfiniteQueryOptions.tsx +37 -55
- package/src/components/Mutation.tsx +35 -15
- package/src/components/MutationOptions.tsx +14 -13
- package/src/components/Query.tsx +14 -10
- package/src/components/QueryOptions.tsx +17 -34
- package/src/components/SuspenseInfiniteQuery.tsx +19 -13
- package/src/components/SuspenseInfiniteQueryOptions.tsx +28 -52
- package/src/components/SuspenseQuery.tsx +9 -10
- package/src/generators/customHookOptionsFileGenerator.tsx +18 -14
- package/src/generators/hookOptionsGenerator.tsx +42 -49
- package/src/generators/infiniteQueryGenerator.tsx +55 -76
- package/src/generators/mutationGenerator.tsx +51 -62
- package/src/generators/queryGenerator.tsx +52 -61
- package/src/generators/suspenseInfiniteQueryGenerator.tsx +50 -63
- package/src/generators/suspenseQueryGenerator.tsx +54 -74
- package/src/plugin.ts +45 -31
- package/src/resolvers/resolverReactQuery.ts +102 -6
- package/src/types.ts +199 -61
- package/src/utils.ts +10 -33
- package/dist/components-DTGLu4UV.js.map +0 -1
- package/dist/components-dAKJEn9b.cjs.map +0 -1
- package/dist/generators-CWEQsdO9.cjs.map +0 -1
- package/dist/generators-C_fbcjpG.js.map +0 -1
- package/dist/types-DfaFRSBf.d.ts +0 -284
|
@@ -1,33 +1,28 @@
|
|
|
1
1
|
import path from 'node:path'
|
|
2
|
+
import { getOperationParameters, operationFileEntry, resolveOperationTypeNames } from '@internals/shared'
|
|
3
|
+
import { resolveZodSchemaNames } from '@internals/tanstack-query'
|
|
2
4
|
import { ast, defineGenerator } from '@kubb/core'
|
|
3
5
|
import { Client, pluginClientName } from '@kubb/plugin-client'
|
|
4
6
|
import { pluginTsName } from '@kubb/plugin-ts'
|
|
5
7
|
import { pluginZodName } from '@kubb/plugin-zod'
|
|
6
|
-
import { File,
|
|
8
|
+
import { File, jsxRendererSync } from '@kubb/renderer-jsx'
|
|
7
9
|
import { difference } from 'remeda'
|
|
8
10
|
import { InfiniteQuery, InfiniteQueryOptions, QueryKey } from '../components'
|
|
9
11
|
import type { PluginReactQuery } from '../types'
|
|
10
|
-
import { transformName } from '../utils.ts'
|
|
11
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
|
+
*/
|
|
12
19
|
export const infiniteQueryGenerator = defineGenerator<PluginReactQuery>({
|
|
13
20
|
name: 'react-infinite-query',
|
|
14
|
-
renderer:
|
|
21
|
+
renderer: jsxRendererSync,
|
|
15
22
|
operation(node, ctx) {
|
|
16
|
-
|
|
17
|
-
const {
|
|
18
|
-
|
|
19
|
-
query,
|
|
20
|
-
mutation,
|
|
21
|
-
infinite,
|
|
22
|
-
paramsCasing,
|
|
23
|
-
paramsType,
|
|
24
|
-
pathParamsType,
|
|
25
|
-
parser,
|
|
26
|
-
client: clientOptions,
|
|
27
|
-
group,
|
|
28
|
-
transformers,
|
|
29
|
-
customOptions,
|
|
30
|
-
} = ctx.options
|
|
23
|
+
if (!ast.isHttpOperationNode(node)) return null
|
|
24
|
+
const { config, driver, resolver, root } = ctx
|
|
25
|
+
const { output, query, mutation, infinite, paramsCasing, paramsType, pathParamsType, parser, client: clientOptions, group, customOptions } = ctx.options
|
|
31
26
|
|
|
32
27
|
const pluginTs = driver.getPlugin(pluginTsName)
|
|
33
28
|
if (!pluginTs) return null
|
|
@@ -38,13 +33,13 @@ export const infiniteQueryGenerator = defineGenerator<PluginReactQuery>({
|
|
|
38
33
|
mutation !== false &&
|
|
39
34
|
!isQuery &&
|
|
40
35
|
difference(mutation ? mutation.methods : [], query ? query.methods : []).some((method) => node.method.toLowerCase() === method.toLowerCase())
|
|
41
|
-
const infiniteOptions = infinite && typeof infinite === 'object' ? infinite :
|
|
36
|
+
const infiniteOptions = infinite && typeof infinite === 'object' ? infinite : null
|
|
42
37
|
|
|
43
38
|
if (!isQuery || isMutation || !infiniteOptions) return null
|
|
44
39
|
|
|
45
40
|
// Validate queryParam exists in operation's query parameters
|
|
46
41
|
const normalizeKey = (key: string) => key.replace(/\?$/, '')
|
|
47
|
-
const queryParamKeys = node
|
|
42
|
+
const queryParamKeys = getOperationParameters(node).query.map((p) => p.name)
|
|
48
43
|
const hasQueryParam = infiniteOptions.queryParam ? queryParamKeys.some((k) => normalizeKey(k) === infiniteOptions.queryParam) : false
|
|
49
44
|
// cursorParam validation against response schema keys is skipped in v5 (complex schema inspection)
|
|
50
45
|
const hasCursorParam = !infiniteOptions.cursorParam || true
|
|
@@ -53,64 +48,50 @@ export const infiniteQueryGenerator = defineGenerator<PluginReactQuery>({
|
|
|
53
48
|
|
|
54
49
|
const importPath = query ? query.importPath : '@tanstack/react-query'
|
|
55
50
|
|
|
56
|
-
const
|
|
57
|
-
const
|
|
58
|
-
const
|
|
59
|
-
const
|
|
60
|
-
const
|
|
61
|
-
const queryKeyTypeName = transformName(`${capitalize(baseName)}InfiniteQueryKey`, 'type', transformers)
|
|
62
|
-
const clientBaseName = transformName(`${baseName}Infinite`, 'function', transformers)
|
|
51
|
+
const queryName = resolver.resolveInfiniteQueryName(node)
|
|
52
|
+
const queryOptionsName = resolver.resolveInfiniteQueryOptionsName(node)
|
|
53
|
+
const queryKeyName = resolver.resolveInfiniteQueryKeyName(node)
|
|
54
|
+
const queryKeyTypeName = resolver.resolveInfiniteQueryKeyTypeName(node)
|
|
55
|
+
const clientBaseName = resolver.resolveInfiniteClientName(node)
|
|
63
56
|
|
|
64
57
|
const meta = {
|
|
65
|
-
file: resolver.resolveFile(
|
|
66
|
-
fileTs: tsResolver.resolveFile(
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
58
|
+
file: resolver.resolveFile(operationFileEntry(node, queryName), { root, output, group: group ?? undefined }),
|
|
59
|
+
fileTs: tsResolver.resolveFile(operationFileEntry(node, node.operationId), {
|
|
60
|
+
root,
|
|
61
|
+
output: pluginTs.options?.output ?? output,
|
|
62
|
+
group: pluginTs.options?.group ?? undefined,
|
|
63
|
+
}),
|
|
70
64
|
}
|
|
71
65
|
|
|
72
|
-
const
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
...pathParams.map((p) => tsResolver.resolvePathParamsName(node, p)),
|
|
81
|
-
...queryParams.map((p) => tsResolver.resolveQueryParamsName(node, p)),
|
|
82
|
-
...headerParams.map((p) => tsResolver.resolveHeaderParamsName(node, p)),
|
|
83
|
-
...node.responses.map((res) => tsResolver.resolveResponseStatusName(node, res.statusCode)),
|
|
84
|
-
].filter((name): name is string => !!name && name !== queryKeyTypeName)
|
|
85
|
-
|
|
86
|
-
const pluginZod = parser === 'zod' ? driver.getPlugin(pluginZodName) : undefined
|
|
87
|
-
const zodResolver = pluginZod ? driver.getResolver(pluginZodName) : undefined
|
|
66
|
+
const importedTypeNames = resolveOperationTypeNames(node, tsResolver, {
|
|
67
|
+
paramsCasing,
|
|
68
|
+
exclude: [queryKeyTypeName],
|
|
69
|
+
order: 'body-response-first',
|
|
70
|
+
})
|
|
71
|
+
|
|
72
|
+
const pluginZod = parser === 'zod' ? driver.getPlugin(pluginZodName) : null
|
|
73
|
+
const zodResolver = pluginZod ? driver.getResolver(pluginZodName) : null
|
|
88
74
|
const fileZod = zodResolver
|
|
89
|
-
? zodResolver.resolveFile(
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
? [zodResolver.resolveResponseName?.(node), node.requestBody?.content?.[0]?.schema ? zodResolver.resolveDataName?.(node) : undefined].filter(Boolean)
|
|
97
|
-
: []
|
|
75
|
+
? zodResolver.resolveFile(operationFileEntry(node, node.operationId), {
|
|
76
|
+
root,
|
|
77
|
+
output: pluginZod?.options?.output ?? output,
|
|
78
|
+
group: pluginZod?.options?.group ?? undefined,
|
|
79
|
+
})
|
|
80
|
+
: null
|
|
81
|
+
const zodSchemaNames = resolveZodSchemaNames(node, zodResolver)
|
|
98
82
|
|
|
99
83
|
const clientPlugin = driver.getPlugin(pluginClientName)
|
|
100
84
|
const hasClientPlugin = clientPlugin?.name === pluginClientName
|
|
101
85
|
const shouldUseClientPlugin = hasClientPlugin && clientOptions.clientType !== 'class'
|
|
102
|
-
const clientResolver = shouldUseClientPlugin ? driver.getResolver(pluginClientName) :
|
|
86
|
+
const clientResolver = shouldUseClientPlugin ? driver.getResolver(pluginClientName) : null
|
|
103
87
|
|
|
104
88
|
const clientFile = shouldUseClientPlugin
|
|
105
|
-
? clientResolver?.resolveFile(
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
},
|
|
112
|
-
)
|
|
113
|
-
: undefined
|
|
89
|
+
? clientResolver?.resolveFile(operationFileEntry(node, node.operationId), {
|
|
90
|
+
root,
|
|
91
|
+
output: clientPlugin?.options?.output ?? output,
|
|
92
|
+
group: clientPlugin?.options?.group ?? undefined,
|
|
93
|
+
})
|
|
94
|
+
: null
|
|
114
95
|
|
|
115
96
|
const resolvedClientName = shouldUseClientPlugin ? (clientResolver?.resolveName(node.operationId) ?? clientBaseName) : clientBaseName
|
|
116
97
|
|
|
@@ -119,29 +100,27 @@ export const infiniteQueryGenerator = defineGenerator<PluginReactQuery>({
|
|
|
119
100
|
baseName={meta.file.baseName}
|
|
120
101
|
path={meta.file.path}
|
|
121
102
|
meta={meta.file.meta}
|
|
122
|
-
banner={resolver.resolveBanner(
|
|
123
|
-
footer={resolver.resolveFooter(
|
|
103
|
+
banner={resolver.resolveBanner(ctx.meta, { output, config, file: { path: meta.file.path, baseName: meta.file.baseName } })}
|
|
104
|
+
footer={resolver.resolveFooter(ctx.meta, { output, config, file: { path: meta.file.path, baseName: meta.file.baseName } })}
|
|
124
105
|
>
|
|
125
|
-
{
|
|
126
|
-
<File.Import name={zodSchemaNames as string[]} root={meta.file.path} path={fileZod.path} />
|
|
127
|
-
)}
|
|
106
|
+
{fileZod && zodSchemaNames.length > 0 && <File.Import name={zodSchemaNames} root={meta.file.path} path={fileZod.path} />}
|
|
128
107
|
{clientOptions.importPath ? (
|
|
129
108
|
<>
|
|
130
|
-
{!shouldUseClientPlugin && <File.Import name={'
|
|
109
|
+
{!shouldUseClientPlugin && <File.Import name={'client'} path={clientOptions.importPath} />}
|
|
131
110
|
<File.Import name={['Client', 'RequestConfig', 'ResponseErrorConfig']} path={clientOptions.importPath} isTypeOnly />
|
|
132
111
|
{clientOptions.dataReturnType === 'full' && <File.Import name={['ResponseConfig']} path={clientOptions.importPath} isTypeOnly />}
|
|
133
112
|
</>
|
|
134
113
|
) : (
|
|
135
114
|
<>
|
|
136
|
-
{!shouldUseClientPlugin && <File.Import name={['
|
|
115
|
+
{!shouldUseClientPlugin && <File.Import name={['client']} root={meta.file.path} path={path.resolve(root, '.kubb/client.ts')} />}
|
|
137
116
|
<File.Import
|
|
138
117
|
name={['Client', 'RequestConfig', 'ResponseErrorConfig']}
|
|
139
118
|
root={meta.file.path}
|
|
140
|
-
path={path.resolve(root, '.kubb/
|
|
119
|
+
path={path.resolve(root, '.kubb/client.ts')}
|
|
141
120
|
isTypeOnly
|
|
142
121
|
/>
|
|
143
122
|
{clientOptions.dataReturnType === 'full' && (
|
|
144
|
-
<File.Import name={['ResponseConfig']} root={meta.file.path} path={path.resolve(root, '.kubb/
|
|
123
|
+
<File.Import name={['ResponseConfig']} root={meta.file.path} path={path.resolve(root, '.kubb/client.ts')} isTypeOnly />
|
|
145
124
|
)}
|
|
146
125
|
</>
|
|
147
126
|
)}
|
|
@@ -1,20 +1,27 @@
|
|
|
1
1
|
import path from 'node:path'
|
|
2
|
+
import { operationFileEntry, resolveOperationTypeNames } from '@internals/shared'
|
|
3
|
+
import { resolveZodSchemaNames } from '@internals/tanstack-query'
|
|
2
4
|
import { ast, defineGenerator } from '@kubb/core'
|
|
3
5
|
import { Client, pluginClientName } from '@kubb/plugin-client'
|
|
4
6
|
import { pluginTsName } from '@kubb/plugin-ts'
|
|
5
7
|
import { pluginZodName } from '@kubb/plugin-zod'
|
|
6
|
-
import { File,
|
|
8
|
+
import { File, jsxRendererSync } from '@kubb/renderer-jsx'
|
|
7
9
|
import { difference } from 'remeda'
|
|
8
10
|
import { Mutation, MutationKey, MutationOptions } from '../components'
|
|
9
11
|
import type { PluginReactQuery } from '../types'
|
|
10
|
-
import { transformName } from '../utils.ts'
|
|
11
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
|
+
*/
|
|
12
18
|
export const mutationGenerator = defineGenerator<PluginReactQuery>({
|
|
13
19
|
name: 'react-query-mutation',
|
|
14
|
-
renderer:
|
|
20
|
+
renderer: jsxRendererSync,
|
|
15
21
|
operation(node, ctx) {
|
|
16
|
-
|
|
17
|
-
const {
|
|
22
|
+
if (!ast.isHttpOperationNode(node)) return null
|
|
23
|
+
const { config, driver, resolver, root } = ctx
|
|
24
|
+
const { output, query, mutation, paramsCasing, paramsType, pathParamsType, parser, client: clientOptions, group, customOptions } = ctx.options
|
|
18
25
|
|
|
19
26
|
const pluginTs = driver.getPlugin(pluginTsName)
|
|
20
27
|
if (!pluginTs) return null
|
|
@@ -30,64 +37,46 @@ export const mutationGenerator = defineGenerator<PluginReactQuery>({
|
|
|
30
37
|
|
|
31
38
|
const importPath = mutation ? mutation.importPath : '@tanstack/react-query'
|
|
32
39
|
|
|
33
|
-
const
|
|
34
|
-
const
|
|
35
|
-
const
|
|
36
|
-
const
|
|
37
|
-
const
|
|
38
|
-
const mutationKeyName = transformName(`${baseName}MutationKey`, 'const', transformers)
|
|
39
|
-
const clientName = transformName(baseName, 'function', transformers)
|
|
40
|
+
const mutationHookName = resolver.resolveMutationName(node)
|
|
41
|
+
const mutationTypeName = resolver.resolveMutationTypeName(node)
|
|
42
|
+
const mutationOptionsName = resolver.resolveMutationOptionsName(node)
|
|
43
|
+
const mutationKeyName = resolver.resolveMutationKeyName(node)
|
|
44
|
+
const clientName = resolver.resolveClientName(node)
|
|
40
45
|
|
|
41
46
|
const meta = {
|
|
42
|
-
file: resolver.resolveFile(
|
|
43
|
-
fileTs: tsResolver.resolveFile(
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
+
file: resolver.resolveFile(operationFileEntry(node, mutationHookName), { root, output, group: group ?? undefined }),
|
|
48
|
+
fileTs: tsResolver.resolveFile(operationFileEntry(node, node.operationId), {
|
|
49
|
+
root,
|
|
50
|
+
output: pluginTs.options?.output ?? output,
|
|
51
|
+
group: pluginTs.options?.group ?? undefined,
|
|
52
|
+
}),
|
|
47
53
|
}
|
|
48
54
|
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
const
|
|
52
|
-
const
|
|
53
|
-
|
|
54
|
-
const importedTypeNames = [
|
|
55
|
-
node.requestBody?.content?.[0]?.schema ? tsResolver.resolveDataName(node) : undefined,
|
|
56
|
-
tsResolver.resolveResponseName(node),
|
|
57
|
-
...pathParams.map((p) => tsResolver.resolvePathParamsName(node, p)),
|
|
58
|
-
...queryParams.map((p) => tsResolver.resolveQueryParamsName(node, p)),
|
|
59
|
-
...headerParams.map((p) => tsResolver.resolveHeaderParamsName(node, p)),
|
|
60
|
-
...node.responses.map((res) => tsResolver.resolveResponseStatusName(node, res.statusCode)),
|
|
61
|
-
].filter((name): name is string => !!name)
|
|
62
|
-
|
|
63
|
-
const pluginZod = parser === 'zod' ? driver.getPlugin(pluginZodName) : undefined
|
|
64
|
-
const zodResolver = pluginZod ? driver.getResolver(pluginZodName) : undefined
|
|
55
|
+
const importedTypeNames = resolveOperationTypeNames(node, tsResolver, { paramsCasing, order: 'body-response-first' })
|
|
56
|
+
|
|
57
|
+
const pluginZod = parser === 'zod' ? driver.getPlugin(pluginZodName) : null
|
|
58
|
+
const zodResolver = pluginZod ? driver.getResolver(pluginZodName) : null
|
|
65
59
|
const fileZod = zodResolver
|
|
66
|
-
? zodResolver.resolveFile(
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
? [zodResolver.resolveResponseName?.(node), node.requestBody?.content?.[0]?.schema ? zodResolver.resolveDataName?.(node) : undefined].filter(Boolean)
|
|
74
|
-
: []
|
|
60
|
+
? zodResolver.resolveFile(operationFileEntry(node, node.operationId), {
|
|
61
|
+
root,
|
|
62
|
+
output: pluginZod?.options?.output ?? output,
|
|
63
|
+
group: pluginZod?.options?.group ?? undefined,
|
|
64
|
+
})
|
|
65
|
+
: null
|
|
66
|
+
const zodSchemaNames = resolveZodSchemaNames(node, zodResolver)
|
|
75
67
|
|
|
76
68
|
const clientPlugin = driver.getPlugin(pluginClientName)
|
|
77
69
|
const hasClientPlugin = clientPlugin?.name === pluginClientName
|
|
78
70
|
const shouldUseClientPlugin = hasClientPlugin && clientOptions.clientType !== 'class'
|
|
79
|
-
const clientResolver = shouldUseClientPlugin ? driver.getResolver(pluginClientName) :
|
|
71
|
+
const clientResolver = shouldUseClientPlugin ? driver.getResolver(pluginClientName) : null
|
|
80
72
|
|
|
81
73
|
const clientFile = shouldUseClientPlugin
|
|
82
|
-
? clientResolver?.resolveFile(
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
},
|
|
89
|
-
)
|
|
90
|
-
: undefined
|
|
74
|
+
? clientResolver?.resolveFile(operationFileEntry(node, node.operationId), {
|
|
75
|
+
root,
|
|
76
|
+
output: clientPlugin?.options?.output ?? output,
|
|
77
|
+
group: clientPlugin?.options?.group ?? undefined,
|
|
78
|
+
})
|
|
79
|
+
: null
|
|
91
80
|
|
|
92
81
|
const resolvedClientName = shouldUseClientPlugin ? (clientResolver?.resolveName(node.operationId) ?? clientName) : clientName
|
|
93
82
|
|
|
@@ -96,34 +85,34 @@ export const mutationGenerator = defineGenerator<PluginReactQuery>({
|
|
|
96
85
|
baseName={meta.file.baseName}
|
|
97
86
|
path={meta.file.path}
|
|
98
87
|
meta={meta.file.meta}
|
|
99
|
-
banner={resolver.resolveBanner(
|
|
100
|
-
footer={resolver.resolveFooter(
|
|
88
|
+
banner={resolver.resolveBanner(ctx.meta, { output, config, file: { path: meta.file.path, baseName: meta.file.baseName } })}
|
|
89
|
+
footer={resolver.resolveFooter(ctx.meta, { output, config, file: { path: meta.file.path, baseName: meta.file.baseName } })}
|
|
101
90
|
>
|
|
102
|
-
{
|
|
103
|
-
<File.Import name={zodSchemaNames as string[]} root={meta.file.path} path={fileZod.path} />
|
|
104
|
-
)}
|
|
91
|
+
{fileZod && zodSchemaNames.length > 0 && <File.Import name={zodSchemaNames} root={meta.file.path} path={fileZod.path} />}
|
|
105
92
|
{clientOptions.importPath ? (
|
|
106
93
|
<>
|
|
107
|
-
{!shouldUseClientPlugin && <File.Import name={'
|
|
94
|
+
{!shouldUseClientPlugin && <File.Import name={'client'} path={clientOptions.importPath} />}
|
|
108
95
|
<File.Import name={['Client', 'RequestConfig', 'ResponseErrorConfig']} path={clientOptions.importPath} isTypeOnly />
|
|
109
96
|
{clientOptions.dataReturnType === 'full' && <File.Import name={['ResponseConfig']} path={clientOptions.importPath} isTypeOnly />}
|
|
110
97
|
</>
|
|
111
98
|
) : (
|
|
112
99
|
<>
|
|
113
|
-
{!shouldUseClientPlugin && <File.Import name={['
|
|
100
|
+
{!shouldUseClientPlugin && <File.Import name={['client']} root={meta.file.path} path={path.resolve(root, '.kubb/client.ts')} />}
|
|
114
101
|
<File.Import
|
|
115
102
|
name={['Client', 'RequestConfig', 'ResponseErrorConfig']}
|
|
116
103
|
root={meta.file.path}
|
|
117
|
-
path={path.resolve(root, '.kubb/
|
|
104
|
+
path={path.resolve(root, '.kubb/client.ts')}
|
|
118
105
|
isTypeOnly
|
|
119
106
|
/>
|
|
120
107
|
{clientOptions.dataReturnType === 'full' && (
|
|
121
|
-
<File.Import name={['ResponseConfig']} root={meta.file.path} path={path.resolve(root, '.kubb/
|
|
108
|
+
<File.Import name={['ResponseConfig']} root={meta.file.path} path={path.resolve(root, '.kubb/client.ts')} isTypeOnly />
|
|
122
109
|
)}
|
|
123
110
|
</>
|
|
124
111
|
)}
|
|
125
112
|
{shouldUseClientPlugin && clientFile && <File.Import name={[resolvedClientName]} root={meta.file.path} path={clientFile.path} />}
|
|
126
|
-
{!shouldUseClientPlugin &&
|
|
113
|
+
{!shouldUseClientPlugin && node.requestBody?.content?.some((e) => e.contentType === 'multipart/form-data') && (
|
|
114
|
+
<File.Import name={['buildFormData']} root={meta.file.path} path={path.resolve(root, '.kubb/config.ts')} />
|
|
115
|
+
)}
|
|
127
116
|
{customOptions && <File.Import name={[customOptions.name]} path={customOptions.importPath} />}
|
|
128
117
|
{meta.fileTs && importedTypeNames.length > 0 && (
|
|
129
118
|
<File.Import name={Array.from(new Set(importedTypeNames))} root={meta.file.path} path={meta.fileTs.path} isTypeOnly />
|
|
@@ -1,20 +1,27 @@
|
|
|
1
1
|
import path from 'node:path'
|
|
2
|
+
import { operationFileEntry, resolveOperationTypeNames } from '@internals/shared'
|
|
3
|
+
import { resolveZodSchemaNames } from '@internals/tanstack-query'
|
|
2
4
|
import { ast, defineGenerator } from '@kubb/core'
|
|
3
5
|
import { Client, pluginClientName } from '@kubb/plugin-client'
|
|
4
6
|
import { pluginTsName } from '@kubb/plugin-ts'
|
|
5
7
|
import { pluginZodName } from '@kubb/plugin-zod'
|
|
6
|
-
import { File,
|
|
8
|
+
import { File, jsxRendererSync } from '@kubb/renderer-jsx'
|
|
7
9
|
import { difference } from 'remeda'
|
|
8
10
|
import { Query, QueryKey, QueryOptions } from '../components'
|
|
9
11
|
import type { PluginReactQuery } from '../types'
|
|
10
|
-
import { transformName } from '../utils.ts'
|
|
11
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
|
+
*/
|
|
12
18
|
export const queryGenerator = defineGenerator<PluginReactQuery>({
|
|
13
19
|
name: 'react-query',
|
|
14
|
-
renderer:
|
|
20
|
+
renderer: jsxRendererSync,
|
|
15
21
|
operation(node, ctx) {
|
|
16
|
-
|
|
17
|
-
const {
|
|
22
|
+
if (!ast.isHttpOperationNode(node)) return null
|
|
23
|
+
const { config, driver, resolver, root } = ctx
|
|
24
|
+
const { output, query, mutation, paramsCasing, paramsType, pathParamsType, parser, client: clientOptions, group, customOptions } = ctx.options
|
|
18
25
|
|
|
19
26
|
const pluginTs = driver.getPlugin(pluginTsName)
|
|
20
27
|
if (!pluginTs) return null
|
|
@@ -31,64 +38,50 @@ export const queryGenerator = defineGenerator<PluginReactQuery>({
|
|
|
31
38
|
|
|
32
39
|
const importPath = query ? query.importPath : '@tanstack/react-query'
|
|
33
40
|
|
|
34
|
-
const
|
|
35
|
-
const
|
|
36
|
-
const
|
|
37
|
-
const
|
|
38
|
-
const
|
|
39
|
-
const queryKeyTypeName = transformName(`${capitalize(baseName)}QueryKey`, 'type', transformers)
|
|
40
|
-
const clientName = transformName(baseName, 'function', transformers)
|
|
41
|
+
const queryName = resolver.resolveQueryName(node)
|
|
42
|
+
const queryOptionsName = resolver.resolveQueryOptionsName(node)
|
|
43
|
+
const queryKeyName = resolver.resolveQueryKeyName(node)
|
|
44
|
+
const queryKeyTypeName = resolver.resolveQueryKeyTypeName(node)
|
|
45
|
+
const clientName = resolver.resolveClientName(node)
|
|
41
46
|
|
|
42
47
|
const meta = {
|
|
43
|
-
file: resolver.resolveFile(
|
|
44
|
-
fileTs: tsResolver.resolveFile(
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
+
file: resolver.resolveFile(operationFileEntry(node, queryName), { root, output, group: group ?? undefined }),
|
|
49
|
+
fileTs: tsResolver.resolveFile(operationFileEntry(node, node.operationId), {
|
|
50
|
+
root,
|
|
51
|
+
output: pluginTs.options?.output ?? output,
|
|
52
|
+
group: pluginTs.options?.group ?? undefined,
|
|
53
|
+
}),
|
|
48
54
|
}
|
|
49
55
|
|
|
50
|
-
const
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
...pathParams.map((p) => tsResolver.resolvePathParamsName(node, p)),
|
|
59
|
-
...queryParams.map((p) => tsResolver.resolveQueryParamsName(node, p)),
|
|
60
|
-
...headerParams.map((p) => tsResolver.resolveHeaderParamsName(node, p)),
|
|
61
|
-
...node.responses.map((res) => tsResolver.resolveResponseStatusName(node, res.statusCode)),
|
|
62
|
-
].filter((name): name is string => !!name && name !== queryKeyTypeName)
|
|
63
|
-
|
|
64
|
-
const pluginZod = parser === 'zod' ? driver.getPlugin(pluginZodName) : undefined
|
|
65
|
-
const zodResolver = pluginZod ? driver.getResolver(pluginZodName) : undefined
|
|
56
|
+
const importedTypeNames = resolveOperationTypeNames(node, tsResolver, {
|
|
57
|
+
paramsCasing,
|
|
58
|
+
exclude: [queryKeyTypeName],
|
|
59
|
+
order: 'body-response-first',
|
|
60
|
+
})
|
|
61
|
+
|
|
62
|
+
const pluginZod = parser === 'zod' ? driver.getPlugin(pluginZodName) : null
|
|
63
|
+
const zodResolver = pluginZod ? driver.getResolver(pluginZodName) : null
|
|
66
64
|
const fileZod = zodResolver
|
|
67
|
-
? zodResolver.resolveFile(
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
? [zodResolver.resolveResponseName?.(node), node.requestBody?.content?.[0]?.schema ? zodResolver.resolveDataName?.(node) : undefined].filter(Boolean)
|
|
75
|
-
: []
|
|
65
|
+
? zodResolver.resolveFile(operationFileEntry(node, node.operationId), {
|
|
66
|
+
root,
|
|
67
|
+
output: pluginZod?.options?.output ?? output,
|
|
68
|
+
group: pluginZod?.options?.group ?? undefined,
|
|
69
|
+
})
|
|
70
|
+
: null
|
|
71
|
+
const zodSchemaNames = resolveZodSchemaNames(node, zodResolver)
|
|
76
72
|
|
|
77
73
|
const clientPlugin = driver.getPlugin(pluginClientName)
|
|
78
74
|
const hasClientPlugin = clientPlugin?.name === pluginClientName
|
|
79
75
|
const shouldUseClientPlugin = hasClientPlugin && clientOptions.clientType !== 'class'
|
|
80
|
-
const clientResolver = shouldUseClientPlugin ? driver.getResolver(pluginClientName) :
|
|
76
|
+
const clientResolver = shouldUseClientPlugin ? driver.getResolver(pluginClientName) : null
|
|
81
77
|
|
|
82
78
|
const clientFile = shouldUseClientPlugin
|
|
83
|
-
? clientResolver?.resolveFile(
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
},
|
|
90
|
-
)
|
|
91
|
-
: undefined
|
|
79
|
+
? clientResolver?.resolveFile(operationFileEntry(node, node.operationId), {
|
|
80
|
+
root,
|
|
81
|
+
output: clientPlugin?.options?.output ?? output,
|
|
82
|
+
group: clientPlugin?.options?.group ?? undefined,
|
|
83
|
+
})
|
|
84
|
+
: null
|
|
92
85
|
|
|
93
86
|
const resolvedClientName = shouldUseClientPlugin ? (clientResolver?.resolveName(node.operationId) ?? clientName) : clientName
|
|
94
87
|
|
|
@@ -97,29 +90,27 @@ export const queryGenerator = defineGenerator<PluginReactQuery>({
|
|
|
97
90
|
baseName={meta.file.baseName}
|
|
98
91
|
path={meta.file.path}
|
|
99
92
|
meta={meta.file.meta}
|
|
100
|
-
banner={resolver.resolveBanner(
|
|
101
|
-
footer={resolver.resolveFooter(
|
|
93
|
+
banner={resolver.resolveBanner(ctx.meta, { output, config, file: { path: meta.file.path, baseName: meta.file.baseName } })}
|
|
94
|
+
footer={resolver.resolveFooter(ctx.meta, { output, config, file: { path: meta.file.path, baseName: meta.file.baseName } })}
|
|
102
95
|
>
|
|
103
|
-
{
|
|
104
|
-
<File.Import name={zodSchemaNames as string[]} root={meta.file.path} path={fileZod.path} />
|
|
105
|
-
)}
|
|
96
|
+
{fileZod && zodSchemaNames.length > 0 && <File.Import name={zodSchemaNames} root={meta.file.path} path={fileZod.path} />}
|
|
106
97
|
{clientOptions.importPath ? (
|
|
107
98
|
<>
|
|
108
|
-
{!shouldUseClientPlugin && <File.Import name={'
|
|
99
|
+
{!shouldUseClientPlugin && <File.Import name={'client'} path={clientOptions.importPath} />}
|
|
109
100
|
<File.Import name={['Client', 'RequestConfig', 'ResponseErrorConfig']} path={clientOptions.importPath} isTypeOnly />
|
|
110
101
|
{clientOptions.dataReturnType === 'full' && <File.Import name={['ResponseConfig']} path={clientOptions.importPath} isTypeOnly />}
|
|
111
102
|
</>
|
|
112
103
|
) : (
|
|
113
104
|
<>
|
|
114
|
-
{!shouldUseClientPlugin && <File.Import name={['
|
|
105
|
+
{!shouldUseClientPlugin && <File.Import name={['client']} root={meta.file.path} path={path.resolve(root, '.kubb/client.ts')} />}
|
|
115
106
|
<File.Import
|
|
116
107
|
name={['Client', 'RequestConfig', 'ResponseErrorConfig']}
|
|
117
108
|
root={meta.file.path}
|
|
118
|
-
path={path.resolve(root, '.kubb/
|
|
109
|
+
path={path.resolve(root, '.kubb/client.ts')}
|
|
119
110
|
isTypeOnly
|
|
120
111
|
/>
|
|
121
112
|
{clientOptions.dataReturnType === 'full' && (
|
|
122
|
-
<File.Import name={['ResponseConfig']} root={meta.file.path} path={path.resolve(root, '.kubb/
|
|
113
|
+
<File.Import name={['ResponseConfig']} root={meta.file.path} path={path.resolve(root, '.kubb/client.ts')} isTypeOnly />
|
|
123
114
|
)}
|
|
124
115
|
</>
|
|
125
116
|
)}
|