@kubb/plugin-vue-query 5.0.0-beta.3 → 5.0.0-beta.30
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 +26 -5
- package/dist/{components-D1UhYFgY.js → components-B4IlVmNa.js} +244 -353
- package/dist/components-B4IlVmNa.js.map +1 -0
- package/dist/{components-qfOFRSoM.cjs → components-CIedagno.cjs} +269 -354
- package/dist/components-CIedagno.cjs.map +1 -0
- package/dist/components.cjs +1 -1
- package/dist/components.d.ts +3 -67
- package/dist/components.js +1 -1
- package/dist/{generators-CbnIVBgY.js → generators-ClYptnDj.js} +144 -132
- package/dist/generators-ClYptnDj.js.map +1 -0
- package/dist/{generators-C4gs_P1i.cjs → generators-D7kNtBBo.cjs} +142 -130
- package/dist/generators-D7kNtBBo.cjs.map +1 -0
- package/dist/generators.cjs +1 -1
- package/dist/generators.d.ts +17 -1
- package/dist/generators.js +1 -1
- package/dist/index.cjs +100 -17
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +29 -1
- package/dist/index.js +100 -17
- package/dist/index.js.map +1 -1
- package/dist/types-D-LjzI_Q.d.ts +270 -0
- package/extension.yaml +1273 -0
- package/package.json +16 -18
- package/src/components/InfiniteQuery.tsx +11 -48
- package/src/components/InfiniteQueryOptions.tsx +38 -50
- package/src/components/Mutation.tsx +33 -42
- package/src/components/Query.tsx +11 -49
- package/src/components/QueryKey.tsx +8 -61
- package/src/components/QueryOptions.tsx +14 -67
- package/src/generators/infiniteQueryGenerator.tsx +46 -51
- package/src/generators/mutationGenerator.tsx +41 -49
- package/src/generators/queryGenerator.tsx +43 -49
- package/src/plugin.ts +43 -15
- package/src/resolvers/resolverVueQuery.ts +61 -4
- package/src/types.ts +129 -53
- package/src/utils.ts +44 -25
- package/dist/components-D1UhYFgY.js.map +0 -1
- package/dist/components-qfOFRSoM.cjs.map +0 -1
- package/dist/generators-C4gs_P1i.cjs.map +0 -1
- package/dist/generators-CbnIVBgY.js.map +0 -1
- package/dist/types-nVDTfuS1.d.ts +0 -194
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { ast } from '@kubb/core'
|
|
1
|
+
import type { ast } from '@kubb/core'
|
|
3
2
|
import type { ResolverTs } from '@kubb/plugin-ts'
|
|
4
3
|
import { functionPrinter } from '@kubb/plugin-ts'
|
|
5
4
|
import { File, Function, Type } from '@kubb/renderer-jsx'
|
|
6
5
|
import type { KubbReactNode } from '@kubb/renderer-jsx/types'
|
|
6
|
+
import { queryKeyTransformer } from '@internals/tanstack-query'
|
|
7
7
|
import type { Transformer } from '../types.ts'
|
|
8
|
-
import { buildQueryKeyParams } from '../utils.ts'
|
|
8
|
+
import { buildQueryKeyParams, wrapWithMaybeRefOrGetter } from '../utils.ts'
|
|
9
9
|
|
|
10
10
|
type Props = {
|
|
11
11
|
name: string
|
|
@@ -14,71 +14,22 @@ type Props = {
|
|
|
14
14
|
tsResolver: ResolverTs
|
|
15
15
|
paramsCasing: 'camelcase' | undefined
|
|
16
16
|
pathParamsType: 'object' | 'inline'
|
|
17
|
-
transformer: Transformer | undefined
|
|
17
|
+
transformer: Transformer | null | undefined
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
const declarationPrinter = functionPrinter({ mode: 'declaration' })
|
|
21
|
-
const callPrinter = functionPrinter({ mode: 'call' })
|
|
22
21
|
|
|
23
|
-
function
|
|
24
|
-
const wrappedParams = paramsNode.params.map((param) => {
|
|
25
|
-
if ('kind' in param && (param as ast.ParameterGroupNode).kind === 'ParameterGroup') {
|
|
26
|
-
const group = param as ast.ParameterGroupNode
|
|
27
|
-
return {
|
|
28
|
-
...group,
|
|
29
|
-
properties: group.properties.map((p) => ({
|
|
30
|
-
...p,
|
|
31
|
-
type: p.type ? ast.createParamsType({ variant: 'reference', name: `MaybeRefOrGetter<${printType(p.type)}>` }) : p.type,
|
|
32
|
-
})),
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
const fp = param as ast.FunctionParameterNode
|
|
36
|
-
return {
|
|
37
|
-
...fp,
|
|
38
|
-
type: fp.type ? ast.createParamsType({ variant: 'reference', name: `MaybeRefOrGetter<${printType(fp.type)}>` }) : fp.type,
|
|
39
|
-
}
|
|
40
|
-
})
|
|
41
|
-
return ast.createFunctionParameters({ params: wrappedParams })
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
function printType(typeNode: ast.ParamsTypeNode | undefined): string {
|
|
45
|
-
if (!typeNode) return 'unknown'
|
|
46
|
-
if (typeNode.variant === 'reference') return typeNode.name
|
|
47
|
-
if (typeNode.variant === 'member') return `${typeNode.base}['${typeNode.key}']`
|
|
48
|
-
if (typeNode.variant === 'struct') {
|
|
49
|
-
const parts = typeNode.properties.map((p) => {
|
|
50
|
-
const typeStr = printType(p.type)
|
|
51
|
-
const key = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(p.name) ? p.name : JSON.stringify(p.name)
|
|
52
|
-
return p.optional ? `${key}?: ${typeStr}` : `${key}: ${typeStr}`
|
|
53
|
-
})
|
|
54
|
-
return `{ ${parts.join('; ')} }`
|
|
55
|
-
}
|
|
56
|
-
return 'unknown'
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
function getParams(
|
|
22
|
+
export function buildQueryKeyParamsNode(
|
|
60
23
|
node: ast.OperationNode,
|
|
61
24
|
options: { pathParamsType: 'object' | 'inline'; paramsCasing: 'camelcase' | undefined; resolver: ResolverTs },
|
|
62
25
|
): ast.FunctionParametersNode {
|
|
63
26
|
return wrapWithMaybeRefOrGetter(buildQueryKeyParams(node, options))
|
|
64
27
|
}
|
|
65
28
|
|
|
66
|
-
|
|
67
|
-
const
|
|
68
|
-
const hasQueryParams = node.parameters.some((p) => p.in === 'query')
|
|
69
|
-
const hasRequestBody = !!node.requestBody?.content?.[0]?.schema
|
|
70
|
-
|
|
71
|
-
return [
|
|
72
|
-
path.toObject({ type: 'path', stringify: true }),
|
|
73
|
-
hasQueryParams ? '...(params ? [params] : [])' : undefined,
|
|
74
|
-
hasRequestBody ? '...(data ? [data] : [])' : undefined,
|
|
75
|
-
].filter(Boolean) as string[]
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
export function QueryKey({ name, node, tsResolver, paramsCasing, pathParamsType, typeName, transformer = getTransformer }: Props): KubbReactNode {
|
|
79
|
-
const paramsNode = getParams(node, { pathParamsType, paramsCasing, resolver: tsResolver })
|
|
29
|
+
export function QueryKey({ name, node, tsResolver, paramsCasing, pathParamsType, typeName, transformer }: Props): KubbReactNode {
|
|
30
|
+
const paramsNode = buildQueryKeyParamsNode(node, { pathParamsType, paramsCasing, resolver: tsResolver })
|
|
80
31
|
const paramsSignature = declarationPrinter.print(paramsNode) ?? ''
|
|
81
|
-
const keys = transformer({
|
|
32
|
+
const keys = (transformer ?? queryKeyTransformer)({
|
|
82
33
|
node,
|
|
83
34
|
casing: paramsCasing,
|
|
84
35
|
})
|
|
@@ -98,7 +49,3 @@ export function QueryKey({ name, node, tsResolver, paramsCasing, pathParamsType,
|
|
|
98
49
|
</>
|
|
99
50
|
)
|
|
100
51
|
}
|
|
101
|
-
|
|
102
|
-
QueryKey.getParams = getParams
|
|
103
|
-
QueryKey.getTransformer = getTransformer
|
|
104
|
-
QueryKey.callPrinter = callPrinter
|
|
@@ -3,9 +3,10 @@ import type { ResolverTs } from '@kubb/plugin-ts'
|
|
|
3
3
|
import { functionPrinter } from '@kubb/plugin-ts'
|
|
4
4
|
import { File, Function } from '@kubb/renderer-jsx'
|
|
5
5
|
import type { KubbReactNode } from '@kubb/renderer-jsx/types'
|
|
6
|
+
import { buildEnabledCheck } from '@internals/tanstack-query'
|
|
6
7
|
import type { PluginVueQuery } from '../types.ts'
|
|
7
|
-
import { resolveErrorNames } from '../utils.ts'
|
|
8
|
-
import {
|
|
8
|
+
import { resolveErrorNames, resolveSuccessNames, wrapWithMaybeRefOrGetter } from '../utils.ts'
|
|
9
|
+
import { buildQueryKeyParamsNode } from './QueryKey.tsx'
|
|
9
10
|
|
|
10
11
|
type Props = {
|
|
11
12
|
name: string
|
|
@@ -32,7 +33,7 @@ export function getQueryOptionsParams(
|
|
|
32
33
|
},
|
|
33
34
|
): ast.FunctionParametersNode {
|
|
34
35
|
const { paramsType, paramsCasing, pathParamsType, resolver } = options
|
|
35
|
-
const requestName = node.requestBody?.content?.[0]?.schema ? resolver.resolveDataName(node) :
|
|
36
|
+
const requestName = node.requestBody?.content?.[0]?.schema ? resolver.resolveDataName(node) : null
|
|
36
37
|
|
|
37
38
|
const baseParams = ast.createOperationParams(node, {
|
|
38
39
|
paramsType,
|
|
@@ -51,65 +52,7 @@ export function getQueryOptionsParams(
|
|
|
51
52
|
],
|
|
52
53
|
})
|
|
53
54
|
|
|
54
|
-
return
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
function wrapOperationParamsWithMaybeRef(paramsNode: ast.FunctionParametersNode): ast.FunctionParametersNode {
|
|
58
|
-
const wrappedParams = paramsNode.params.map((param) => {
|
|
59
|
-
if ('kind' in param && (param as ast.ParameterGroupNode).kind === 'ParameterGroup') {
|
|
60
|
-
const group = param as ast.ParameterGroupNode
|
|
61
|
-
return {
|
|
62
|
-
...group,
|
|
63
|
-
properties: group.properties.map((p) => ({
|
|
64
|
-
...p,
|
|
65
|
-
type: p.type ? ast.createParamsType({ variant: 'reference', name: `MaybeRefOrGetter<${printType(p.type)}>` }) : p.type,
|
|
66
|
-
})),
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
const fp = param as ast.FunctionParameterNode
|
|
70
|
-
// Don't wrap 'config' param — it's not reactive
|
|
71
|
-
if (fp.name === 'config') return fp
|
|
72
|
-
return {
|
|
73
|
-
...fp,
|
|
74
|
-
type: fp.type ? ast.createParamsType({ variant: 'reference', name: `MaybeRefOrGetter<${printType(fp.type)}>` }) : fp.type,
|
|
75
|
-
}
|
|
76
|
-
})
|
|
77
|
-
return ast.createFunctionParameters({ params: wrappedParams })
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
function printType(typeNode: ast.ParamsTypeNode | undefined): string {
|
|
81
|
-
if (!typeNode) return 'unknown'
|
|
82
|
-
if (typeNode.variant === 'reference') return typeNode.name
|
|
83
|
-
if (typeNode.variant === 'member') return `${typeNode.base}['${typeNode.key}']`
|
|
84
|
-
if (typeNode.variant === 'struct') {
|
|
85
|
-
const parts = typeNode.properties.map((p) => {
|
|
86
|
-
const typeStr = printType(p.type)
|
|
87
|
-
const key = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(p.name) ? p.name : JSON.stringify(p.name)
|
|
88
|
-
return p.optional ? `${key}?: ${typeStr}` : `${key}: ${typeStr}`
|
|
89
|
-
})
|
|
90
|
-
return `{ ${parts.join('; ')} }`
|
|
91
|
-
}
|
|
92
|
-
return 'unknown'
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
export function buildEnabledCheck(paramsNode: ast.FunctionParametersNode): string {
|
|
96
|
-
const required: string[] = []
|
|
97
|
-
for (const param of paramsNode.params) {
|
|
98
|
-
if ('kind' in param && (param as ast.ParameterGroupNode).kind === 'ParameterGroup') {
|
|
99
|
-
const group = param as ast.ParameterGroupNode
|
|
100
|
-
for (const child of group.properties) {
|
|
101
|
-
if (!child.optional && child.default === undefined) {
|
|
102
|
-
required.push(child.name)
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
} else {
|
|
106
|
-
const fp = param as ast.FunctionParameterNode
|
|
107
|
-
if (!fp.optional && fp.default === undefined) {
|
|
108
|
-
required.push(fp.name)
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
return required.join(' && ')
|
|
55
|
+
return wrapWithMaybeRefOrGetter(baseParams, (name) => name === 'config')
|
|
113
56
|
}
|
|
114
57
|
|
|
115
58
|
export function QueryOptions({
|
|
@@ -123,7 +66,8 @@ export function QueryOptions({
|
|
|
123
66
|
pathParamsType,
|
|
124
67
|
queryKeyName,
|
|
125
68
|
}: Props): KubbReactNode {
|
|
126
|
-
const
|
|
69
|
+
const successNames = resolveSuccessNames(node, tsResolver)
|
|
70
|
+
const responseName = successNames.length > 0 ? successNames.join(' | ') : tsResolver.resolveResponseName(node)
|
|
127
71
|
const errorNames = resolveErrorNames(node, tsResolver)
|
|
128
72
|
|
|
129
73
|
const TData = dataReturnType === 'data' ? responseName : `ResponseConfig<${responseName}>`
|
|
@@ -136,11 +80,16 @@ export function QueryOptions({
|
|
|
136
80
|
// Transform: wrap non-config params with toValue(), add signal to config
|
|
137
81
|
const clientCallStr = rawParamsCall.replace(/\bconfig\b(?=[^,]*$)/, '{ ...config, signal: config.signal ?? signal }')
|
|
138
82
|
|
|
139
|
-
const queryKeyParamsNode =
|
|
83
|
+
const queryKeyParamsNode = buildQueryKeyParamsNode(node, { pathParamsType, paramsCasing, resolver: tsResolver })
|
|
140
84
|
const queryKeyParamsCall = callPrinter.print(queryKeyParamsNode) ?? ''
|
|
141
85
|
|
|
142
86
|
const enabledSource = buildEnabledCheck(queryKeyParamsNode)
|
|
143
|
-
const enabledText = enabledSource
|
|
87
|
+
const enabledText = enabledSource
|
|
88
|
+
? `enabled: () => ${enabledSource
|
|
89
|
+
.split(' && ')
|
|
90
|
+
.map((n) => `!!toValue(${n.trim()})`)
|
|
91
|
+
.join(' && ')},`
|
|
92
|
+
: ''
|
|
144
93
|
|
|
145
94
|
return (
|
|
146
95
|
<File.Source name={name} isExportable isIndexable>
|
|
@@ -189,5 +138,3 @@ function addToValueCalls(callStr: string): string {
|
|
|
189
138
|
|
|
190
139
|
return result
|
|
191
140
|
}
|
|
192
|
-
|
|
193
|
-
QueryOptions.getParams = getQueryOptionsParams
|
|
@@ -1,20 +1,27 @@
|
|
|
1
1
|
import path from 'node:path'
|
|
2
|
-
import {
|
|
2
|
+
import { getOperationParameters, resolveOperationTypeNames } from '@internals/shared'
|
|
3
|
+
import { resolveZodSchemaNames } from '@internals/tanstack-query'
|
|
4
|
+
import { 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 { PluginVueQuery } from '../types'
|
|
10
|
-
import { transformName } from '../utils.ts'
|
|
11
12
|
|
|
13
|
+
/**
|
|
14
|
+
* Built-in generator for `useInfiniteQuery` composables. Enabled when
|
|
15
|
+
* `pluginVueQuery({ infinite: { ... } })`. Emits one `useFooInfiniteQuery`
|
|
16
|
+
* composable per query operation, wiring the configured cursor path into
|
|
17
|
+
* TanStack Query's cursor-based pagination.
|
|
18
|
+
*/
|
|
12
19
|
export const infiniteQueryGenerator = defineGenerator<PluginVueQuery>({
|
|
13
20
|
name: 'vue-query-infinite',
|
|
14
|
-
renderer:
|
|
21
|
+
renderer: jsxRendererSync,
|
|
15
22
|
operation(node, ctx) {
|
|
16
|
-
const {
|
|
17
|
-
const { output, query, mutation, infinite, paramsCasing, paramsType, pathParamsType, parser, client: clientOptions, group
|
|
23
|
+
const { config, driver, resolver, root } = ctx
|
|
24
|
+
const { output, query, mutation, infinite, paramsCasing, paramsType, pathParamsType, parser, client: clientOptions, group } = ctx.options
|
|
18
25
|
|
|
19
26
|
const pluginTs = driver.getPlugin(pluginTsName)
|
|
20
27
|
if (!pluginTs) return null
|
|
@@ -25,13 +32,13 @@ export const infiniteQueryGenerator = defineGenerator<PluginVueQuery>({
|
|
|
25
32
|
mutation !== false &&
|
|
26
33
|
!isQuery &&
|
|
27
34
|
difference(mutation ? mutation.methods : [], query ? query.methods : []).some((method) => node.method.toLowerCase() === method.toLowerCase())
|
|
28
|
-
const infiniteOptions = infinite && typeof infinite === 'object' ? infinite :
|
|
35
|
+
const infiniteOptions = infinite && typeof infinite === 'object' ? infinite : null
|
|
29
36
|
|
|
30
37
|
if (!isQuery || isMutation || !infiniteOptions) return null
|
|
31
38
|
|
|
32
39
|
// Validate queryParam exists in operation's query parameters
|
|
33
40
|
const normalizeKey = (key: string) => key.replace(/\?$/, '')
|
|
34
|
-
const queryParamKeys = node
|
|
41
|
+
const queryParamKeys = getOperationParameters(node).query.map((p) => p.name)
|
|
35
42
|
const hasQueryParam = infiniteOptions.queryParam ? queryParamKeys.some((k) => normalizeKey(k) === infiniteOptions.queryParam) : false
|
|
36
43
|
// cursorParam validation against response schema keys is skipped in v5 (complex schema inspection)
|
|
37
44
|
const hasCursorParam = !infiniteOptions.cursorParam || true
|
|
@@ -40,53 +47,43 @@ export const infiniteQueryGenerator = defineGenerator<PluginVueQuery>({
|
|
|
40
47
|
|
|
41
48
|
const importPath = query ? query.importPath : '@tanstack/vue-query'
|
|
42
49
|
|
|
43
|
-
const
|
|
44
|
-
const
|
|
45
|
-
const
|
|
46
|
-
const
|
|
47
|
-
const
|
|
48
|
-
const queryKeyTypeName = transformName(`${capitalize(baseName)}InfiniteQueryKey`, 'type', transformers)
|
|
49
|
-
const clientBaseName = transformName(`${baseName}Infinite`, 'function', transformers)
|
|
50
|
+
const queryName = resolver.resolveInfiniteQueryName(node)
|
|
51
|
+
const queryOptionsName = resolver.resolveInfiniteQueryOptionsName(node)
|
|
52
|
+
const queryKeyName = resolver.resolveInfiniteQueryKeyName(node)
|
|
53
|
+
const queryKeyTypeName = resolver.resolveInfiniteQueryKeyTypeName(node)
|
|
54
|
+
const clientBaseName = resolver.resolveInfiniteClientName(node)
|
|
50
55
|
|
|
51
56
|
const meta = {
|
|
52
|
-
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
|
+
),
|
|
53
61
|
fileTs: tsResolver.resolveFile(
|
|
54
62
|
{ name: node.operationId, extname: '.ts', tag: node.tags[0] ?? 'default', path: node.path },
|
|
55
|
-
{ root, output: pluginTs.options?.output ?? output, group: pluginTs.options?.group },
|
|
63
|
+
{ root, output: pluginTs.options?.output ?? output, group: pluginTs.options?.group ?? undefined },
|
|
56
64
|
),
|
|
57
65
|
}
|
|
58
66
|
|
|
59
|
-
const
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
...pathParams.map((p) => tsResolver.resolvePathParamsName(node, p)),
|
|
68
|
-
...queryParams.map((p) => tsResolver.resolveQueryParamsName(node, p)),
|
|
69
|
-
...headerParams.map((p) => tsResolver.resolveHeaderParamsName(node, p)),
|
|
70
|
-
...node.responses.map((res) => tsResolver.resolveResponseStatusName(node, res.statusCode)),
|
|
71
|
-
].filter((name): name is string => !!name && name !== queryKeyTypeName)
|
|
72
|
-
|
|
73
|
-
const pluginZod = parser === 'zod' ? driver.getPlugin(pluginZodName) : undefined
|
|
74
|
-
const zodResolver = pluginZod ? driver.getResolver(pluginZodName) : undefined
|
|
67
|
+
const importedTypeNames = resolveOperationTypeNames(node, tsResolver, {
|
|
68
|
+
paramsCasing,
|
|
69
|
+
exclude: [queryKeyTypeName],
|
|
70
|
+
order: 'body-response-first',
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
const pluginZod = parser === 'zod' ? driver.getPlugin(pluginZodName) : null
|
|
74
|
+
const zodResolver = pluginZod ? driver.getResolver(pluginZodName) : null
|
|
75
75
|
const fileZod = zodResolver
|
|
76
76
|
? zodResolver.resolveFile(
|
|
77
77
|
{ name: node.operationId, extname: '.ts', tag: node.tags[0] ?? 'default', path: node.path },
|
|
78
|
-
{ root, output: pluginZod?.options?.output ?? output, group: pluginZod?.options?.group },
|
|
78
|
+
{ root, output: pluginZod?.options?.output ?? output, group: pluginZod?.options?.group ?? undefined },
|
|
79
79
|
)
|
|
80
|
-
:
|
|
81
|
-
const zodSchemaNames =
|
|
82
|
-
zodResolver && parser === 'zod'
|
|
83
|
-
? [zodResolver.resolveResponseName?.(node), node.requestBody?.content?.[0]?.schema ? zodResolver.resolveDataName?.(node) : undefined].filter(Boolean)
|
|
84
|
-
: []
|
|
80
|
+
: null
|
|
81
|
+
const zodSchemaNames = resolveZodSchemaNames(node, zodResolver)
|
|
85
82
|
|
|
86
83
|
const clientPlugin = driver.getPlugin(pluginClientName)
|
|
87
84
|
const hasClientPlugin = clientPlugin?.name === pluginClientName
|
|
88
85
|
const shouldUseClientPlugin = hasClientPlugin && clientOptions.clientType !== 'class'
|
|
89
|
-
const clientResolver = shouldUseClientPlugin ? driver.getResolver(pluginClientName) :
|
|
86
|
+
const clientResolver = shouldUseClientPlugin ? driver.getResolver(pluginClientName) : null
|
|
90
87
|
|
|
91
88
|
const clientFile = shouldUseClientPlugin
|
|
92
89
|
? clientResolver?.resolveFile(
|
|
@@ -94,10 +91,10 @@ export const infiniteQueryGenerator = defineGenerator<PluginVueQuery>({
|
|
|
94
91
|
{
|
|
95
92
|
root,
|
|
96
93
|
output: clientPlugin?.options?.output ?? output,
|
|
97
|
-
group: clientPlugin?.options?.group,
|
|
94
|
+
group: clientPlugin?.options?.group ?? undefined,
|
|
98
95
|
},
|
|
99
96
|
)
|
|
100
|
-
:
|
|
97
|
+
: null
|
|
101
98
|
|
|
102
99
|
const resolvedClientName = shouldUseClientPlugin ? (clientResolver?.resolveName(node.operationId) ?? clientBaseName) : clientBaseName
|
|
103
100
|
|
|
@@ -106,29 +103,27 @@ export const infiniteQueryGenerator = defineGenerator<PluginVueQuery>({
|
|
|
106
103
|
baseName={meta.file.baseName}
|
|
107
104
|
path={meta.file.path}
|
|
108
105
|
meta={meta.file.meta}
|
|
109
|
-
banner={resolver.resolveBanner(
|
|
110
|
-
footer={resolver.resolveFooter(
|
|
106
|
+
banner={resolver.resolveBanner(ctx.meta, { output, config, file: { path: meta.file.path, baseName: meta.file.baseName } })}
|
|
107
|
+
footer={resolver.resolveFooter(ctx.meta, { output, config, file: { path: meta.file.path, baseName: meta.file.baseName } })}
|
|
111
108
|
>
|
|
112
|
-
{
|
|
113
|
-
<File.Import name={zodSchemaNames as string[]} root={meta.file.path} path={fileZod.path} />
|
|
114
|
-
)}
|
|
109
|
+
{fileZod && zodSchemaNames.length > 0 && <File.Import name={zodSchemaNames} root={meta.file.path} path={fileZod.path} />}
|
|
115
110
|
{clientOptions.importPath ? (
|
|
116
111
|
<>
|
|
117
|
-
{!shouldUseClientPlugin && <File.Import name={'
|
|
112
|
+
{!shouldUseClientPlugin && <File.Import name={'client'} path={clientOptions.importPath} />}
|
|
118
113
|
<File.Import name={['Client', 'RequestConfig', 'ResponseErrorConfig']} path={clientOptions.importPath} isTypeOnly />
|
|
119
114
|
{clientOptions.dataReturnType === 'full' && <File.Import name={['ResponseConfig']} path={clientOptions.importPath} isTypeOnly />}
|
|
120
115
|
</>
|
|
121
116
|
) : (
|
|
122
117
|
<>
|
|
123
|
-
{!shouldUseClientPlugin && <File.Import name={['
|
|
118
|
+
{!shouldUseClientPlugin && <File.Import name={['client']} root={meta.file.path} path={path.resolve(root, '.kubb/client.ts')} />}
|
|
124
119
|
<File.Import
|
|
125
120
|
name={['Client', 'RequestConfig', 'ResponseErrorConfig']}
|
|
126
121
|
root={meta.file.path}
|
|
127
|
-
path={path.resolve(root, '.kubb/
|
|
122
|
+
path={path.resolve(root, '.kubb/client.ts')}
|
|
128
123
|
isTypeOnly
|
|
129
124
|
/>
|
|
130
125
|
{clientOptions.dataReturnType === 'full' && (
|
|
131
|
-
<File.Import name={['ResponseConfig']} root={meta.file.path} path={path.resolve(root, '.kubb/
|
|
126
|
+
<File.Import name={['ResponseConfig']} root={meta.file.path} path={path.resolve(root, '.kubb/client.ts')} isTypeOnly />
|
|
132
127
|
)}
|
|
133
128
|
</>
|
|
134
129
|
)}
|
|
@@ -1,20 +1,26 @@
|
|
|
1
1
|
import path from 'node:path'
|
|
2
|
-
import {
|
|
2
|
+
import { resolveOperationTypeNames } from '@internals/shared'
|
|
3
|
+
import { resolveZodSchemaNames } from '@internals/tanstack-query'
|
|
4
|
+
import { 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 } from '../components'
|
|
9
11
|
import type { PluginVueQuery } from '../types'
|
|
10
|
-
import { transformName } from '../utils.ts'
|
|
11
12
|
|
|
13
|
+
/**
|
|
14
|
+
* Built-in generator for `useMutation` composables. Emits one
|
|
15
|
+
* `useFooMutation` composable per POST/PUT/DELETE operation (configurable
|
|
16
|
+
* via `mutation.methods`) plus the matching `fooMutationKey` helper.
|
|
17
|
+
*/
|
|
12
18
|
export const mutationGenerator = defineGenerator<PluginVueQuery>({
|
|
13
19
|
name: 'vue-query-mutation',
|
|
14
|
-
renderer:
|
|
20
|
+
renderer: jsxRendererSync,
|
|
15
21
|
operation(node, ctx) {
|
|
16
|
-
const {
|
|
17
|
-
const { output, query, mutation, paramsCasing, paramsType, pathParamsType, parser, client: clientOptions, group
|
|
22
|
+
const { config, driver, resolver, root } = ctx
|
|
23
|
+
const { output, query, mutation, paramsCasing, paramsType, pathParamsType, parser, client: clientOptions, group } = ctx.options
|
|
18
24
|
|
|
19
25
|
const pluginTs = driver.getPlugin(pluginTsName)
|
|
20
26
|
if (!pluginTs) return null
|
|
@@ -30,52 +36,38 @@ export const mutationGenerator = defineGenerator<PluginVueQuery>({
|
|
|
30
36
|
|
|
31
37
|
const importPath = mutation ? mutation.importPath : '@tanstack/vue-query'
|
|
32
38
|
|
|
33
|
-
const
|
|
34
|
-
const
|
|
35
|
-
const
|
|
36
|
-
const
|
|
37
|
-
const mutationKeyName = transformName(`${baseName}MutationKey`, 'const', transformers)
|
|
38
|
-
const clientName = transformName(baseName, 'function', transformers)
|
|
39
|
+
const mutationHookName = resolver.resolveMutationName(node)
|
|
40
|
+
const mutationTypeName = resolver.resolveMutationTypeName(node)
|
|
41
|
+
const mutationKeyName = resolver.resolveMutationKeyName(node)
|
|
42
|
+
const clientName = resolver.resolveClientName(node)
|
|
39
43
|
|
|
40
44
|
const meta = {
|
|
41
|
-
file: resolver.resolveFile(
|
|
45
|
+
file: resolver.resolveFile(
|
|
46
|
+
{ name: mutationHookName, extname: '.ts', tag: node.tags[0] ?? 'default', path: node.path },
|
|
47
|
+
{ root, output, group: group ?? undefined },
|
|
48
|
+
),
|
|
42
49
|
fileTs: tsResolver.resolveFile(
|
|
43
50
|
{ name: node.operationId, extname: '.ts', tag: node.tags[0] ?? 'default', path: node.path },
|
|
44
|
-
{ root, output: pluginTs.options?.output ?? output, group: pluginTs.options?.group },
|
|
51
|
+
{ root, output: pluginTs.options?.output ?? output, group: pluginTs.options?.group ?? undefined },
|
|
45
52
|
),
|
|
46
53
|
}
|
|
47
54
|
|
|
48
|
-
const
|
|
49
|
-
|
|
50
|
-
const
|
|
51
|
-
const
|
|
52
|
-
|
|
53
|
-
const importedTypeNames = [
|
|
54
|
-
node.requestBody?.content?.[0]?.schema ? tsResolver.resolveDataName(node) : undefined,
|
|
55
|
-
tsResolver.resolveResponseName(node),
|
|
56
|
-
...pathParams.map((p) => tsResolver.resolvePathParamsName(node, p)),
|
|
57
|
-
...queryParams.map((p) => tsResolver.resolveQueryParamsName(node, p)),
|
|
58
|
-
...headerParams.map((p) => tsResolver.resolveHeaderParamsName(node, p)),
|
|
59
|
-
...node.responses.map((res) => tsResolver.resolveResponseStatusName(node, res.statusCode)),
|
|
60
|
-
].filter((name): name is string => !!name)
|
|
61
|
-
|
|
62
|
-
const pluginZod = parser === 'zod' ? driver.getPlugin(pluginZodName) : undefined
|
|
63
|
-
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
|
|
64
59
|
const fileZod = zodResolver
|
|
65
60
|
? zodResolver.resolveFile(
|
|
66
61
|
{ name: node.operationId, extname: '.ts', tag: node.tags[0] ?? 'default', path: node.path },
|
|
67
|
-
{ root, output: pluginZod?.options?.output ?? output, group: pluginZod?.options?.group },
|
|
62
|
+
{ root, output: pluginZod?.options?.output ?? output, group: pluginZod?.options?.group ?? undefined },
|
|
68
63
|
)
|
|
69
|
-
:
|
|
70
|
-
const zodSchemaNames =
|
|
71
|
-
zodResolver && parser === 'zod'
|
|
72
|
-
? [zodResolver.resolveResponseName?.(node), node.requestBody?.content?.[0]?.schema ? zodResolver.resolveDataName?.(node) : undefined].filter(Boolean)
|
|
73
|
-
: []
|
|
64
|
+
: null
|
|
65
|
+
const zodSchemaNames = resolveZodSchemaNames(node, zodResolver)
|
|
74
66
|
|
|
75
67
|
const clientPlugin = driver.getPlugin(pluginClientName)
|
|
76
68
|
const hasClientPlugin = clientPlugin?.name === pluginClientName
|
|
77
69
|
const shouldUseClientPlugin = hasClientPlugin && clientOptions.clientType !== 'class'
|
|
78
|
-
const clientResolver = shouldUseClientPlugin ? driver.getResolver(pluginClientName) :
|
|
70
|
+
const clientResolver = shouldUseClientPlugin ? driver.getResolver(pluginClientName) : null
|
|
79
71
|
|
|
80
72
|
const clientFile = shouldUseClientPlugin
|
|
81
73
|
? clientResolver?.resolveFile(
|
|
@@ -83,10 +75,10 @@ export const mutationGenerator = defineGenerator<PluginVueQuery>({
|
|
|
83
75
|
{
|
|
84
76
|
root,
|
|
85
77
|
output: clientPlugin?.options?.output ?? output,
|
|
86
|
-
group: clientPlugin?.options?.group,
|
|
78
|
+
group: clientPlugin?.options?.group ?? undefined,
|
|
87
79
|
},
|
|
88
80
|
)
|
|
89
|
-
:
|
|
81
|
+
: null
|
|
90
82
|
|
|
91
83
|
const resolvedClientName = shouldUseClientPlugin ? (clientResolver?.resolveName(node.operationId) ?? clientName) : clientName
|
|
92
84
|
|
|
@@ -95,35 +87,35 @@ export const mutationGenerator = defineGenerator<PluginVueQuery>({
|
|
|
95
87
|
baseName={meta.file.baseName}
|
|
96
88
|
path={meta.file.path}
|
|
97
89
|
meta={meta.file.meta}
|
|
98
|
-
banner={resolver.resolveBanner(
|
|
99
|
-
footer={resolver.resolveFooter(
|
|
90
|
+
banner={resolver.resolveBanner(ctx.meta, { output, config, file: { path: meta.file.path, baseName: meta.file.baseName } })}
|
|
91
|
+
footer={resolver.resolveFooter(ctx.meta, { output, config, file: { path: meta.file.path, baseName: meta.file.baseName } })}
|
|
100
92
|
>
|
|
101
|
-
{
|
|
102
|
-
<File.Import name={zodSchemaNames as string[]} root={meta.file.path} path={fileZod.path} />
|
|
103
|
-
)}
|
|
93
|
+
{fileZod && zodSchemaNames.length > 0 && <File.Import name={zodSchemaNames} root={meta.file.path} path={fileZod.path} />}
|
|
104
94
|
{clientOptions.importPath ? (
|
|
105
95
|
<>
|
|
106
|
-
{!shouldUseClientPlugin && <File.Import name={'
|
|
96
|
+
{!shouldUseClientPlugin && <File.Import name={'client'} path={clientOptions.importPath} />}
|
|
107
97
|
<File.Import name={['Client', 'RequestConfig', 'ResponseErrorConfig']} path={clientOptions.importPath} isTypeOnly />
|
|
108
98
|
{clientOptions.dataReturnType === 'full' && <File.Import name={['ResponseConfig']} path={clientOptions.importPath} isTypeOnly />}
|
|
109
99
|
</>
|
|
110
100
|
) : (
|
|
111
101
|
<>
|
|
112
|
-
{!shouldUseClientPlugin && <File.Import name={['
|
|
102
|
+
{!shouldUseClientPlugin && <File.Import name={['client']} root={meta.file.path} path={path.resolve(root, '.kubb/client.ts')} />}
|
|
113
103
|
<File.Import
|
|
114
104
|
name={['Client', 'RequestConfig', 'ResponseErrorConfig']}
|
|
115
105
|
root={meta.file.path}
|
|
116
|
-
path={path.resolve(root, '.kubb/
|
|
106
|
+
path={path.resolve(root, '.kubb/client.ts')}
|
|
117
107
|
isTypeOnly
|
|
118
108
|
/>
|
|
119
109
|
{clientOptions.dataReturnType === 'full' && (
|
|
120
|
-
<File.Import name={['ResponseConfig']} root={meta.file.path} path={path.resolve(root, '.kubb/
|
|
110
|
+
<File.Import name={['ResponseConfig']} root={meta.file.path} path={path.resolve(root, '.kubb/client.ts')} isTypeOnly />
|
|
121
111
|
)}
|
|
122
112
|
</>
|
|
123
113
|
)}
|
|
124
114
|
<File.Import name={['MaybeRefOrGetter']} path="vue" isTypeOnly />
|
|
125
115
|
{shouldUseClientPlugin && clientFile && <File.Import name={[resolvedClientName]} root={meta.file.path} path={clientFile.path} />}
|
|
126
|
-
{!shouldUseClientPlugin &&
|
|
116
|
+
{!shouldUseClientPlugin && node.requestBody?.content?.some((e) => e.contentType === 'multipart/form-data') && (
|
|
117
|
+
<File.Import name={['buildFormData']} root={meta.file.path} path={path.resolve(root, '.kubb/config.ts')} />
|
|
118
|
+
)}
|
|
127
119
|
{meta.fileTs && importedTypeNames.length > 0 && (
|
|
128
120
|
<File.Import name={Array.from(new Set(importedTypeNames))} root={meta.file.path} path={meta.fileTs.path} isTypeOnly />
|
|
129
121
|
)}
|