@kubb/plugin-zod 5.0.0-alpha.8 → 5.0.0-beta.3
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/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 -479
- 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/types.ts
CHANGED
|
@@ -1,172 +1,187 @@
|
|
|
1
|
-
import type { Group, Output, PluginFactoryOptions,
|
|
2
|
-
import type {
|
|
3
|
-
import type {
|
|
4
|
-
|
|
1
|
+
import type { ast, Exclude, Generator, Group, Include, Output, Override, PluginFactoryOptions, Resolver } from '@kubb/core'
|
|
2
|
+
import type { PrinterZodNodes } from './printers/printerZod.ts'
|
|
3
|
+
import type { PrinterZodMiniNodes } from './printers/printerZodMini.ts'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Resolver for Zod that provides naming methods for schema types.
|
|
7
|
+
*/
|
|
8
|
+
export type ResolverZod = Resolver &
|
|
9
|
+
ast.OperationParamsResolver & {
|
|
10
|
+
/**
|
|
11
|
+
* Resolves a camelCase schema function name with a `Schema` suffix.
|
|
12
|
+
*/
|
|
13
|
+
resolveSchemaName(this: ResolverZod, name: string): string
|
|
14
|
+
/**
|
|
15
|
+
* Resolves the schema type name (inferred type from schema).
|
|
16
|
+
*
|
|
17
|
+
* @example Schema type names
|
|
18
|
+
* `resolver.resolveSchemaTypeName('pet') // → 'Pet'`
|
|
19
|
+
*/
|
|
20
|
+
resolveSchemaTypeName(this: ResolverZod, name: string): string
|
|
21
|
+
/**
|
|
22
|
+
* Resolves the generated type name from the schema.
|
|
23
|
+
*
|
|
24
|
+
* @example Type names
|
|
25
|
+
* `resolver.resolveTypeName('pet') // → 'Pet'`
|
|
26
|
+
*/
|
|
27
|
+
resolveTypeName(this: ResolverZod, name: string): string
|
|
28
|
+
/**
|
|
29
|
+
* Resolves the output file name for a schema.
|
|
30
|
+
*/
|
|
31
|
+
resolvePathName(this: ResolverZod, name: string, type?: 'file' | 'function' | 'type' | 'const'): string
|
|
32
|
+
/**
|
|
33
|
+
* Resolves the name for an operation response by status code.
|
|
34
|
+
*
|
|
35
|
+
* @example Response status names
|
|
36
|
+
* `resolver.resolveResponseStatusName(node, 200) // → 'listPetsStatus200Schema'`
|
|
37
|
+
*/
|
|
38
|
+
resolveResponseStatusName(this: ResolverZod, node: ast.OperationNode, statusCode: ast.StatusCode): string
|
|
39
|
+
/**
|
|
40
|
+
* Resolves the name for the collection of all operation responses.
|
|
41
|
+
*
|
|
42
|
+
* @example Responses collection names
|
|
43
|
+
* `resolver.resolveResponsesName(node) // → 'listPetsResponsesSchema'`
|
|
44
|
+
*/
|
|
45
|
+
resolveResponsesName(this: ResolverZod, node: ast.OperationNode): string
|
|
46
|
+
/**
|
|
47
|
+
* Resolves the name for the union of all operation responses.
|
|
48
|
+
*
|
|
49
|
+
* @example Response union names
|
|
50
|
+
* `resolver.resolveResponseName(node) // → 'listPetsResponseSchema'`
|
|
51
|
+
*/
|
|
52
|
+
resolveResponseName(this: ResolverZod, node: ast.OperationNode): string
|
|
53
|
+
/**
|
|
54
|
+
* Resolves the name for an operation's grouped path parameters type.
|
|
55
|
+
*
|
|
56
|
+
* @example Path parameters names
|
|
57
|
+
* `resolver.resolvePathParamsName(node, param) // → 'deletePetPathPetIdSchema'`
|
|
58
|
+
*/
|
|
59
|
+
resolvePathParamsName(this: ResolverZod, node: ast.OperationNode, param: ast.ParameterNode): string
|
|
60
|
+
/**
|
|
61
|
+
* Resolves the name for an operation's grouped query parameters type.
|
|
62
|
+
*
|
|
63
|
+
* @example Query parameters names
|
|
64
|
+
* `resolver.resolveQueryParamsName(node, param) // → 'findPetsByStatusQueryStatusSchema'`
|
|
65
|
+
*/
|
|
66
|
+
resolveQueryParamsName(this: ResolverZod, node: ast.OperationNode, param: ast.ParameterNode): string
|
|
67
|
+
/**
|
|
68
|
+
* Resolves the name for an operation's grouped header parameters type.
|
|
69
|
+
*
|
|
70
|
+
* @example Header parameters names
|
|
71
|
+
* `resolver.resolveHeaderParamsName(node, param) // → 'deletePetHeaderApiKeySchema'`
|
|
72
|
+
*/
|
|
73
|
+
resolveHeaderParamsName(this: ResolverZod, node: ast.OperationNode, param: ast.ParameterNode): string
|
|
74
|
+
}
|
|
5
75
|
|
|
6
76
|
export type Options = {
|
|
7
77
|
/**
|
|
8
78
|
* @default 'zod'
|
|
9
79
|
*/
|
|
10
|
-
output?: Output
|
|
11
|
-
/**
|
|
12
|
-
* Define which contentType should be used.
|
|
13
|
-
* By default, the first JSON valid mediaType is used
|
|
14
|
-
*/
|
|
15
|
-
contentType?: contentType
|
|
80
|
+
output?: Output
|
|
16
81
|
/**
|
|
17
82
|
* Group the Zod schemas based on the provided name.
|
|
18
83
|
*/
|
|
19
84
|
group?: Group
|
|
20
85
|
/**
|
|
21
|
-
*
|
|
86
|
+
* Tags, operations, or paths to exclude from generation.
|
|
22
87
|
*/
|
|
23
88
|
exclude?: Array<Exclude>
|
|
24
89
|
/**
|
|
25
|
-
*
|
|
90
|
+
* Tags, operations, or paths to include in generation.
|
|
26
91
|
*/
|
|
27
92
|
include?: Array<Include>
|
|
28
93
|
/**
|
|
29
|
-
*
|
|
94
|
+
* Override options for specific tags, operations, or paths.
|
|
30
95
|
*/
|
|
31
96
|
override?: Array<Override<ResolvedOptions>>
|
|
32
97
|
/**
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
* Accepts relative and absolute paths.
|
|
36
|
-
* Path is used as-is; relative paths are based on the generated file location.
|
|
98
|
+
* Import path for Zod package.
|
|
99
|
+
*
|
|
37
100
|
* @default 'zod'
|
|
38
101
|
*/
|
|
39
|
-
importPath?: string
|
|
40
|
-
|
|
102
|
+
importPath?: 'zod' | 'zod/mini' | (string & {})
|
|
41
103
|
/**
|
|
42
|
-
*
|
|
43
|
-
* - false falls back to a simple z.string() format.
|
|
44
|
-
* - 'string' uses z.string().datetime() for datetime validation.
|
|
45
|
-
* - 'stringOffset' uses z.string().datetime({ offset: true }) for datetime with timezone offset validation.
|
|
46
|
-
* - 'stringLocal' uses z.string().datetime({ local: true }) for local datetime validation.
|
|
47
|
-
* - 'date' uses z.date() for JavaScript Date objects.
|
|
48
|
-
* @default 'string'
|
|
49
|
-
* @note 'stringOffset' will become the default in Kubb v3.
|
|
50
|
-
*/
|
|
51
|
-
dateType?: false | 'string' | 'stringOffset' | 'stringLocal' | 'date'
|
|
52
|
-
/**
|
|
53
|
-
* Choose to use `number` or `bigint` for integer fields with `int64` format.
|
|
54
|
-
* - 'number' uses the JavaScript `number` type (matches JSON.parse() runtime behavior).
|
|
55
|
-
* - 'bigint' uses the JavaScript `bigint` type (accurate for values exceeding Number.MAX_SAFE_INTEGER).
|
|
56
|
-
* @note in v5 of Kubb 'bigint' will become the default to better align with OpenAPI's int64 specification.
|
|
57
|
-
* @default 'number'
|
|
58
|
-
*/
|
|
59
|
-
integerType?: 'number' | 'bigint'
|
|
60
|
-
/**
|
|
61
|
-
* Which type to use when the Swagger/OpenAPI file is not providing more information.
|
|
62
|
-
* - 'any' allows any value.
|
|
63
|
-
* - 'unknown' requires type narrowing before use.
|
|
64
|
-
* - 'void' represents no value.
|
|
65
|
-
* @default 'any'
|
|
66
|
-
*/
|
|
67
|
-
unknownType?: 'any' | 'unknown' | 'void'
|
|
68
|
-
/**
|
|
69
|
-
* Which type to use for empty schema values.
|
|
70
|
-
* - 'any' allows any value.
|
|
71
|
-
* - 'unknown' requires type narrowing before use.
|
|
72
|
-
* - 'void' represents no value.
|
|
73
|
-
* @default `unknownType`
|
|
74
|
-
*/
|
|
75
|
-
emptySchemaType?: 'any' | 'unknown' | 'void'
|
|
76
|
-
/**
|
|
77
|
-
* Use TypeScript(`@kubb/plugin-ts`) to add type annotation.
|
|
104
|
+
* Add TypeScript type annotations to generated schemas.
|
|
78
105
|
*/
|
|
79
106
|
typed?: boolean
|
|
80
107
|
/**
|
|
81
|
-
* Return
|
|
108
|
+
* Return schemas as inferred types using `z.infer`.
|
|
82
109
|
*/
|
|
83
110
|
inferred?: boolean
|
|
84
111
|
/**
|
|
85
|
-
*
|
|
86
|
-
* can also be an object to enable coercion for dates, strings, and numbers
|
|
112
|
+
* Apply coercion to string values or configure coercion per type.
|
|
87
113
|
*/
|
|
88
|
-
coercion?:
|
|
89
|
-
| boolean
|
|
90
|
-
| {
|
|
91
|
-
dates?: boolean
|
|
92
|
-
strings?: boolean
|
|
93
|
-
numbers?: boolean
|
|
94
|
-
}
|
|
95
|
-
operations?: boolean
|
|
96
|
-
mapper?: Record<string, string>
|
|
97
|
-
transformers?: {
|
|
98
|
-
/**
|
|
99
|
-
* Customize the names based on the type that is provided by the plugin.
|
|
100
|
-
*/
|
|
101
|
-
name?: (name: ResolveNameParams['name'], type?: ResolveNameParams['type']) => string
|
|
102
|
-
/**
|
|
103
|
-
* Receive schema and baseName(propertyName) and return FakerMeta array
|
|
104
|
-
* TODO TODO add docs
|
|
105
|
-
* @beta
|
|
106
|
-
*/
|
|
107
|
-
schema?: (
|
|
108
|
-
props: {
|
|
109
|
-
schema: SchemaObject | null
|
|
110
|
-
name: string | null
|
|
111
|
-
parentName: string | null
|
|
112
|
-
},
|
|
113
|
-
defaultSchemas: Schema[],
|
|
114
|
-
) => Schema[] | undefined
|
|
115
|
-
}
|
|
114
|
+
coercion?: boolean | { dates?: boolean; strings?: boolean; numbers?: boolean }
|
|
116
115
|
/**
|
|
117
|
-
*
|
|
118
|
-
* - '3' uses Zod v3.x syntax and features.
|
|
119
|
-
* - '4' uses Zod v4.x syntax and features.
|
|
120
|
-
* @default '3'
|
|
116
|
+
* Generate operation-level schemas (grouped by operationId).
|
|
121
117
|
*/
|
|
122
|
-
|
|
118
|
+
operations?: boolean
|
|
123
119
|
/**
|
|
124
|
-
*
|
|
125
|
-
*
|
|
126
|
-
* - 'guid' uses GUID validation (Zod v4 only).
|
|
120
|
+
* Validator to use for UUID format: `uuid` or `guid`.
|
|
121
|
+
*
|
|
127
122
|
* @default 'uuid'
|
|
128
123
|
*/
|
|
129
124
|
guidType?: 'uuid' | 'guid'
|
|
130
125
|
/**
|
|
131
|
-
* Use Zod Mini's functional API for better tree-shaking
|
|
132
|
-
*
|
|
133
|
-
* Requires Zod v4 or later. When `mini: true`, `version` is set to '4' and `importPath` will default to 'zod/mini'.
|
|
126
|
+
* Use Zod Mini's functional API for better tree-shaking.
|
|
127
|
+
*
|
|
134
128
|
* @default false
|
|
135
129
|
*/
|
|
136
130
|
mini?: boolean
|
|
137
131
|
/**
|
|
138
|
-
* Callback
|
|
132
|
+
* Callback to wrap the generated schema output.
|
|
139
133
|
*
|
|
140
|
-
*
|
|
141
|
-
* or `extendApi(z.object({ ... }), { example: { some: "complex-example", ...otherOpenApiProperties }})`
|
|
142
|
-
* while going from openapi -> zod -> openapi
|
|
134
|
+
* Useful for adding metadata like `.openapi()` or extension helpers.
|
|
143
135
|
*/
|
|
144
|
-
wrapOutput?: (arg: { output: string; schema:
|
|
136
|
+
wrapOutput?: (arg: { output: string; schema: ast.SchemaNode }) => string | undefined
|
|
145
137
|
/**
|
|
146
|
-
*
|
|
138
|
+
* Apply casing to parameter names.
|
|
139
|
+
*/
|
|
140
|
+
paramsCasing?: 'camelcase'
|
|
141
|
+
/**
|
|
142
|
+
* Additional generators alongside the default generators.
|
|
147
143
|
*/
|
|
148
144
|
generators?: Array<Generator<PluginZod>>
|
|
145
|
+
/**
|
|
146
|
+
* Override naming conventions for schema names and types.
|
|
147
|
+
*/
|
|
148
|
+
resolver?: Partial<ResolverZod> & ThisType<ResolverZod>
|
|
149
|
+
/**
|
|
150
|
+
* Override printer node handlers to customize rendering of specific schema types.
|
|
151
|
+
*/
|
|
152
|
+
printer?: {
|
|
153
|
+
nodes?: PrinterZodNodes | PrinterZodMiniNodes
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* AST visitor to transform schema and operation nodes.
|
|
157
|
+
*/
|
|
158
|
+
transformer?: ast.Visitor
|
|
149
159
|
}
|
|
150
160
|
|
|
151
161
|
type ResolvedOptions = {
|
|
152
|
-
output: Output
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
integerType: NonNullable<Options['integerType']>
|
|
158
|
-
unknownType: NonNullable<Options['unknownType']>
|
|
159
|
-
emptySchemaType: NonNullable<Options['emptySchemaType']>
|
|
162
|
+
output: Output
|
|
163
|
+
exclude: Array<Exclude>
|
|
164
|
+
include: Array<Include> | undefined
|
|
165
|
+
override: Array<Override<ResolvedOptions>>
|
|
166
|
+
group: Group | undefined
|
|
160
167
|
typed: NonNullable<Options['typed']>
|
|
161
168
|
inferred: NonNullable<Options['inferred']>
|
|
162
|
-
mapper: NonNullable<Options['mapper']>
|
|
163
169
|
importPath: NonNullable<Options['importPath']>
|
|
164
170
|
coercion: NonNullable<Options['coercion']>
|
|
165
171
|
operations: NonNullable<Options['operations']>
|
|
166
|
-
wrapOutput: Options['wrapOutput']
|
|
167
|
-
version: NonNullable<Options['version']>
|
|
168
172
|
guidType: NonNullable<Options['guidType']>
|
|
169
173
|
mini: NonNullable<Options['mini']>
|
|
174
|
+
wrapOutput: Options['wrapOutput']
|
|
175
|
+
paramsCasing: Options['paramsCasing']
|
|
176
|
+
printer: Options['printer']
|
|
170
177
|
}
|
|
171
178
|
|
|
172
|
-
export type PluginZod = PluginFactoryOptions<'plugin-zod', Options, ResolvedOptions,
|
|
179
|
+
export type PluginZod = PluginFactoryOptions<'plugin-zod', Options, ResolvedOptions, ResolverZod>
|
|
180
|
+
|
|
181
|
+
declare global {
|
|
182
|
+
namespace Kubb {
|
|
183
|
+
interface PluginRegistry {
|
|
184
|
+
'plugin-zod': PluginZod
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
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
|
+
}
|