@kubb/plugin-zod 5.0.0-alpha.9 → 5.0.0-beta.4
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/LICENSE +17 -10
- package/README.md +1 -3
- package/dist/index.cjs +1061 -105
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +369 -4
- package/dist/index.js +1053 -104
- package/dist/index.js.map +1 -1
- package/extension.yaml +502 -0
- package/package.json +44 -70
- package/src/components/Operations.tsx +25 -18
- package/src/components/Zod.tsx +21 -121
- package/src/constants.ts +5 -0
- package/src/generators/zodGenerator.tsx +174 -160
- package/src/index.ts +11 -2
- package/src/plugin.ts +67 -156
- package/src/printers/printerZod.ts +339 -0
- package/src/printers/printerZodMini.ts +295 -0
- package/src/resolvers/resolverZod.ts +57 -0
- package/src/types.ts +130 -115
- package/src/utils.ts +222 -0
- package/dist/components-B7zUFnAm.cjs +0 -890
- package/dist/components-B7zUFnAm.cjs.map +0 -1
- package/dist/components-eECfXVou.js +0 -842
- package/dist/components-eECfXVou.js.map +0 -1
- package/dist/components.cjs +0 -4
- package/dist/components.d.ts +0 -56
- package/dist/components.js +0 -2
- package/dist/generators-BjPDdJUz.cjs +0 -301
- package/dist/generators-BjPDdJUz.cjs.map +0 -1
- package/dist/generators-lTWPS6oN.js +0 -290
- package/dist/generators-lTWPS6oN.js.map +0 -1
- package/dist/generators.cjs +0 -4
- package/dist/generators.d.ts +0 -508
- package/dist/generators.js +0 -2
- package/dist/templates/ToZod.source.cjs +0 -7
- package/dist/templates/ToZod.source.cjs.map +0 -1
- package/dist/templates/ToZod.source.d.ts +0 -7
- package/dist/templates/ToZod.source.js +0 -6
- package/dist/templates/ToZod.source.js.map +0 -1
- package/dist/types-CoCoOc2u.d.ts +0 -172
- package/src/components/index.ts +0 -2
- package/src/generators/index.ts +0 -2
- package/src/generators/operationsGenerator.tsx +0 -50
- package/src/parser.ts +0 -909
- package/src/templates/ToZod.source.ts +0 -4
- package/templates/ToZod.ts +0 -61
package/src/utils.ts
ADDED
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
import { stringify, toRegExpString } from '@internals/utils'
|
|
2
|
+
import { ast } from '@kubb/core'
|
|
3
|
+
import type { PluginZod, ResolverZod } from './types.ts'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Returns `true` when the given coercion option enables coercion for the specified type.
|
|
7
|
+
*/
|
|
8
|
+
export function shouldCoerce(coercion: PluginZod['resolvedOptions']['coercion'] | undefined, type: 'dates' | 'strings' | 'numbers'): boolean {
|
|
9
|
+
if (coercion === undefined || coercion === false) return false
|
|
10
|
+
if (coercion === true) return true
|
|
11
|
+
|
|
12
|
+
return !!coercion[type]
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Collects all resolved schema names for an operation's parameters and responses
|
|
17
|
+
* into a single lookup object, useful for building imports and type references.
|
|
18
|
+
*/
|
|
19
|
+
export function buildSchemaNames(node: ast.OperationNode, { params, resolver }: { params: Array<ast.ParameterNode>; resolver: ResolverZod }) {
|
|
20
|
+
const pathParam = params.find((p) => p.in === 'path')
|
|
21
|
+
const queryParam = params.find((p) => p.in === 'query')
|
|
22
|
+
const headerParam = params.find((p) => p.in === 'header')
|
|
23
|
+
|
|
24
|
+
const responses: Record<number | string, string> = {}
|
|
25
|
+
const errors: Record<number | string, string> = {}
|
|
26
|
+
|
|
27
|
+
for (const res of node.responses) {
|
|
28
|
+
const name = resolver.resolveResponseStatusName(node, res.statusCode)
|
|
29
|
+
const statusNum = Number(res.statusCode)
|
|
30
|
+
|
|
31
|
+
if (!Number.isNaN(statusNum)) {
|
|
32
|
+
responses[statusNum] = name
|
|
33
|
+
if (statusNum >= 400) {
|
|
34
|
+
errors[statusNum] = name
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
responses['default'] = resolver.resolveResponseName(node)
|
|
40
|
+
|
|
41
|
+
return {
|
|
42
|
+
request: node.requestBody?.content?.[0]?.schema ? resolver.resolveDataName(node) : undefined,
|
|
43
|
+
parameters: {
|
|
44
|
+
path: pathParam ? resolver.resolvePathParamsName(node, pathParam) : undefined,
|
|
45
|
+
query: queryParam ? resolver.resolveQueryParamsName(node, queryParam) : undefined,
|
|
46
|
+
header: headerParam ? resolver.resolveHeaderParamsName(node, headerParam) : undefined,
|
|
47
|
+
},
|
|
48
|
+
responses,
|
|
49
|
+
errors,
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Format a default value as a code-level literal.
|
|
55
|
+
* Objects become `{}`, primitives become their string representation, strings are quoted.
|
|
56
|
+
*/
|
|
57
|
+
export function formatDefault(value: unknown): string {
|
|
58
|
+
if (typeof value === 'string') return stringify(value)
|
|
59
|
+
if (typeof value === 'object' && value !== null) return '{}'
|
|
60
|
+
|
|
61
|
+
return String(value ?? '')
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Format a primitive enum/literal value.
|
|
66
|
+
* Strings are quoted; numbers and booleans are emitted raw.
|
|
67
|
+
*/
|
|
68
|
+
export function formatLiteral(v: string | number | boolean): string {
|
|
69
|
+
if (typeof v === 'string') return stringify(v)
|
|
70
|
+
|
|
71
|
+
return String(v)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Numeric constraint limits for Zod schemas (min, max, and exclusive bounds).
|
|
76
|
+
*/
|
|
77
|
+
export type NumericConstraints = {
|
|
78
|
+
min?: number
|
|
79
|
+
max?: number
|
|
80
|
+
exclusiveMinimum?: number
|
|
81
|
+
exclusiveMaximum?: number
|
|
82
|
+
multipleOf?: number
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Length constraint limits for string and array schemas (min, max, and regex pattern).
|
|
87
|
+
*/
|
|
88
|
+
export type LengthConstraints = {
|
|
89
|
+
min?: number
|
|
90
|
+
max?: number
|
|
91
|
+
pattern?: string
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Modifier options for applying chainable methods to Zod schema values.
|
|
96
|
+
*/
|
|
97
|
+
export type ModifierOptions = {
|
|
98
|
+
value: string
|
|
99
|
+
nullable?: boolean
|
|
100
|
+
optional?: boolean
|
|
101
|
+
nullish?: boolean
|
|
102
|
+
defaultValue?: unknown
|
|
103
|
+
description?: string
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Build `.min()` / `.max()` / `.gt()` / `.lt()` constraint chains for numbers
|
|
108
|
+
* using the standard chainable Zod v4 API.
|
|
109
|
+
*/
|
|
110
|
+
export function numberConstraints({ min, max, exclusiveMinimum, exclusiveMaximum, multipleOf }: NumericConstraints): string {
|
|
111
|
+
return [
|
|
112
|
+
min !== undefined ? `.min(${min})` : '',
|
|
113
|
+
max !== undefined ? `.max(${max})` : '',
|
|
114
|
+
exclusiveMinimum !== undefined ? `.gt(${exclusiveMinimum})` : '',
|
|
115
|
+
exclusiveMaximum !== undefined ? `.lt(${exclusiveMaximum})` : '',
|
|
116
|
+
multipleOf !== undefined ? `.multipleOf(${multipleOf})` : '',
|
|
117
|
+
].join('')
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Build `.min()` / `.max()` / `.regex()` chains for strings/arrays
|
|
122
|
+
* using the standard chainable Zod v4 API.
|
|
123
|
+
*/
|
|
124
|
+
export function lengthConstraints({ min, max, pattern }: LengthConstraints): string {
|
|
125
|
+
return [
|
|
126
|
+
min !== undefined ? `.min(${min})` : '',
|
|
127
|
+
max !== undefined ? `.max(${max})` : '',
|
|
128
|
+
pattern !== undefined ? `.regex(${toRegExpString(pattern, null)})` : '',
|
|
129
|
+
].join('')
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Build `.check(z.minimum(), z.maximum())` for `zod/mini` numeric constraints.
|
|
134
|
+
*/
|
|
135
|
+
export function numberChecksMini({ min, max, exclusiveMinimum, exclusiveMaximum, multipleOf }: NumericConstraints): string {
|
|
136
|
+
const checks: string[] = []
|
|
137
|
+
if (min !== undefined) checks.push(`z.minimum(${min})`)
|
|
138
|
+
if (max !== undefined) checks.push(`z.maximum(${max})`)
|
|
139
|
+
if (exclusiveMinimum !== undefined) checks.push(`z.minimum(${exclusiveMinimum}, { exclusive: true })`)
|
|
140
|
+
if (exclusiveMaximum !== undefined) checks.push(`z.maximum(${exclusiveMaximum}, { exclusive: true })`)
|
|
141
|
+
if (multipleOf !== undefined) checks.push(`z.multipleOf(${multipleOf})`)
|
|
142
|
+
return checks.length ? `.check(${checks.join(', ')})` : ''
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Build `.check(z.minLength(), z.maxLength(), z.regex())` for `zod/mini` length constraints.
|
|
147
|
+
*/
|
|
148
|
+
export function lengthChecksMini({ min, max, pattern }: LengthConstraints): string {
|
|
149
|
+
const checks: string[] = []
|
|
150
|
+
if (min !== undefined) checks.push(`z.minLength(${min})`)
|
|
151
|
+
if (max !== undefined) checks.push(`z.maxLength(${max})`)
|
|
152
|
+
if (pattern !== undefined) checks.push(`z.regex(${toRegExpString(pattern, null)})`)
|
|
153
|
+
return checks.length ? `.check(${checks.join(', ')})` : ''
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Apply nullable / optional / nullish modifiers and an optional `.describe()` call
|
|
158
|
+
* to a schema value string using the chainable Zod v4 API.
|
|
159
|
+
*/
|
|
160
|
+
export function applyModifiers({ value, nullable, optional, nullish, defaultValue, description }: ModifierOptions): string {
|
|
161
|
+
let result = value
|
|
162
|
+
if (nullish || (nullable && optional)) {
|
|
163
|
+
result = `${result}.nullish()`
|
|
164
|
+
} else if (optional) {
|
|
165
|
+
result = `${result}.optional()`
|
|
166
|
+
} else if (nullable) {
|
|
167
|
+
result = `${result}.nullable()`
|
|
168
|
+
}
|
|
169
|
+
if (defaultValue !== undefined) {
|
|
170
|
+
result = `${result}.default(${formatDefault(defaultValue)})`
|
|
171
|
+
}
|
|
172
|
+
if (description) {
|
|
173
|
+
result = `${result}.describe(${stringify(description)})`
|
|
174
|
+
}
|
|
175
|
+
return result
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Apply nullable / optional / nullish modifiers using the functional `zod/mini` API
|
|
180
|
+
* (`z.nullable()`, `z.optional()`, `z.nullish()`).
|
|
181
|
+
*/
|
|
182
|
+
export function applyMiniModifiers({ value, nullable, optional, nullish, defaultValue }: Omit<ModifierOptions, 'description'>): string {
|
|
183
|
+
let result = value
|
|
184
|
+
if (nullish) {
|
|
185
|
+
result = `z.nullish(${result})`
|
|
186
|
+
} else {
|
|
187
|
+
if (nullable) {
|
|
188
|
+
result = `z.nullable(${result})`
|
|
189
|
+
}
|
|
190
|
+
if (optional) {
|
|
191
|
+
result = `z.optional(${result})`
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
if (defaultValue !== undefined) {
|
|
195
|
+
result = `z._default(${result}, ${formatDefault(defaultValue)})`
|
|
196
|
+
}
|
|
197
|
+
return result
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
type BuildGroupedParamsSchemaOptions = {
|
|
201
|
+
params: Array<ast.ParameterNode>
|
|
202
|
+
optional?: boolean
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Builds an `object` schema node grouping the given parameter nodes.
|
|
207
|
+
* The `primitive: 'object'` marker ensures the Zod printer emits `z.object(…)` rather than a record.
|
|
208
|
+
*/
|
|
209
|
+
export function buildGroupedParamsSchema({ params, optional }: BuildGroupedParamsSchemaOptions): ast.SchemaNode {
|
|
210
|
+
return ast.createSchema({
|
|
211
|
+
type: 'object',
|
|
212
|
+
optional,
|
|
213
|
+
primitive: 'object',
|
|
214
|
+
properties: params.map((param) =>
|
|
215
|
+
ast.createProperty({
|
|
216
|
+
name: param.name,
|
|
217
|
+
required: param.required,
|
|
218
|
+
schema: param.schema,
|
|
219
|
+
}),
|
|
220
|
+
),
|
|
221
|
+
})
|
|
222
|
+
}
|