@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.
Files changed (46) hide show
  1. package/LICENSE +17 -10
  2. package/README.md +1 -3
  3. package/dist/index.cjs +1061 -105
  4. package/dist/index.cjs.map +1 -1
  5. package/dist/index.d.ts +369 -4
  6. package/dist/index.js +1053 -104
  7. package/dist/index.js.map +1 -1
  8. package/extension.yaml +502 -0
  9. package/package.json +44 -70
  10. package/src/components/Operations.tsx +25 -18
  11. package/src/components/Zod.tsx +21 -121
  12. package/src/constants.ts +5 -0
  13. package/src/generators/zodGenerator.tsx +174 -160
  14. package/src/index.ts +11 -2
  15. package/src/plugin.ts +67 -156
  16. package/src/printers/printerZod.ts +339 -0
  17. package/src/printers/printerZodMini.ts +295 -0
  18. package/src/resolvers/resolverZod.ts +57 -0
  19. package/src/types.ts +130 -115
  20. package/src/utils.ts +222 -0
  21. package/dist/components-B7zUFnAm.cjs +0 -890
  22. package/dist/components-B7zUFnAm.cjs.map +0 -1
  23. package/dist/components-eECfXVou.js +0 -842
  24. package/dist/components-eECfXVou.js.map +0 -1
  25. package/dist/components.cjs +0 -4
  26. package/dist/components.d.ts +0 -56
  27. package/dist/components.js +0 -2
  28. package/dist/generators-BjPDdJUz.cjs +0 -301
  29. package/dist/generators-BjPDdJUz.cjs.map +0 -1
  30. package/dist/generators-lTWPS6oN.js +0 -290
  31. package/dist/generators-lTWPS6oN.js.map +0 -1
  32. package/dist/generators.cjs +0 -4
  33. package/dist/generators.d.ts +0 -508
  34. package/dist/generators.js +0 -2
  35. package/dist/templates/ToZod.source.cjs +0 -7
  36. package/dist/templates/ToZod.source.cjs.map +0 -1
  37. package/dist/templates/ToZod.source.d.ts +0 -7
  38. package/dist/templates/ToZod.source.js +0 -6
  39. package/dist/templates/ToZod.source.js.map +0 -1
  40. package/dist/types-CoCoOc2u.d.ts +0 -172
  41. package/src/components/index.ts +0 -2
  42. package/src/generators/index.ts +0 -2
  43. package/src/generators/operationsGenerator.tsx +0 -50
  44. package/src/parser.ts +0 -909
  45. package/src/templates/ToZod.source.ts +0 -4
  46. package/templates/ToZod.ts +0 -61
@@ -0,0 +1,295 @@
1
+ import { stringify } from '@internals/utils'
2
+
3
+ import { ast } from '@kubb/core'
4
+ import type { PluginZod, ResolverZod } from '../types.ts'
5
+ import { applyMiniModifiers, formatLiteral, lengthChecksMini, numberChecksMini } from '../utils.ts'
6
+
7
+ /**
8
+ * Partial map of node-type overrides for the Zod Mini printer.
9
+ *
10
+ * Each key is a `SchemaType` string (e.g. `'date'`, `'string'`). The function
11
+ * replaces the built-in handler for that node type. Use `this.transform` to
12
+ * recurse into nested schema nodes, and `this.options` to read printer options.
13
+ *
14
+ * @example Override the `date` handler
15
+ * ```ts
16
+ * pluginZod({
17
+ * mini: true,
18
+ * printer: {
19
+ * nodes: {
20
+ * date(node) {
21
+ * return 'z.iso.date()'
22
+ * },
23
+ * },
24
+ * },
25
+ * })
26
+ * ```
27
+ */
28
+ export type PrinterZodMiniNodes = ast.PrinterPartial<string, PrinterZodMiniOptions>
29
+
30
+ export type PrinterZodMiniOptions = {
31
+ /**
32
+ * Use `z.guid()` or `z.uuid()` for UUID/GUID validation.
33
+ *
34
+ * @default 'uuid'
35
+ */
36
+ guidType?: PluginZod['resolvedOptions']['guidType']
37
+ /**
38
+ * Hook to transform generated Zod schema before output.
39
+ */
40
+ wrapOutput?: PluginZod['resolvedOptions']['wrapOutput']
41
+ /**
42
+ * Transforms raw schema names into valid JavaScript identifiers.
43
+ */
44
+ resolver?: ResolverZod
45
+ /**
46
+ * Properties to exclude using `.omit({ key: true })`.
47
+ */
48
+ keysToOmit?: Array<string>
49
+ /**
50
+ * Schema names that form circular dependency chains.
51
+ * Properties referencing these emit lazy getters wrapping refs in `z.lazy(() => …)`.
52
+ */
53
+ cyclicSchemas?: ReadonlySet<string>
54
+ /**
55
+ * Custom handler map for node type overrides.
56
+ */
57
+ nodes?: PrinterZodMiniNodes
58
+ }
59
+
60
+ /**
61
+ * Factory options for the Zod Mini printer, defining input/output types and configuration.
62
+ */
63
+ export type PrinterZodMiniFactory = ast.PrinterFactoryOptions<'zod-mini', PrinterZodMiniOptions, string, string>
64
+ /**
65
+ * Zod v4 **Mini** printer built with `definePrinter`.
66
+ *
67
+ * Converts a `SchemaNode` AST into a Zod v4 code string using the functional API
68
+ * (`z.optional(z.string())`) for improved tree-shaking. See {@link printerZod} for the chainable API.
69
+ *
70
+ * @example Functional Mini API
71
+ * ```ts
72
+ * const printer = printerZodMini({})
73
+ * const code = printer.print(optionalStringNode) // "z.optional(z.string())"
74
+ * ```
75
+ */
76
+ export const printerZodMini = ast.definePrinter<PrinterZodMiniFactory>((options) => {
77
+ return {
78
+ name: 'zod-mini',
79
+ options,
80
+ nodes: {
81
+ any: () => 'z.any()',
82
+ unknown: () => 'z.unknown()',
83
+ void: () => 'z.void()',
84
+ never: () => 'z.never()',
85
+ boolean: () => 'z.boolean()',
86
+ null: () => 'z.null()',
87
+ string(node) {
88
+ return `z.string()${lengthChecksMini(node)}`
89
+ },
90
+ number(node) {
91
+ return `z.number()${numberChecksMini(node)}`
92
+ },
93
+ integer(node) {
94
+ return `z.int()${numberChecksMini(node)}`
95
+ },
96
+ bigint(node) {
97
+ return `z.bigint()${numberChecksMini(node)}`
98
+ },
99
+ date(node) {
100
+ if (node.representation === 'string') {
101
+ return 'z.iso.date()'
102
+ }
103
+
104
+ return 'z.date()'
105
+ },
106
+ datetime() {
107
+ // Mini mode: datetime validation via z.string() (z.iso.datetime not available in mini)
108
+ return 'z.string()'
109
+ },
110
+ time(node) {
111
+ if (node.representation === 'string') {
112
+ return 'z.iso.time()'
113
+ }
114
+
115
+ return 'z.date()'
116
+ },
117
+ uuid(node) {
118
+ const base = this.options.guidType === 'guid' ? 'z.guid()' : 'z.uuid()'
119
+
120
+ return `${base}${lengthChecksMini(node)}`
121
+ },
122
+ email(node) {
123
+ return `z.email()${lengthChecksMini(node)}`
124
+ },
125
+ url(node) {
126
+ return `z.url()${lengthChecksMini(node)}`
127
+ },
128
+ ipv4: () => 'z.ipv4()',
129
+ ipv6: () => 'z.ipv6()',
130
+ blob: () => 'z.instanceof(File)',
131
+ enum(node) {
132
+ const values = node.namedEnumValues?.map((v) => v.value) ?? node.enumValues ?? []
133
+ const nonNullValues = values.filter((v): v is string | number | boolean => v !== null)
134
+
135
+ // asConst-style enum: use z.union([z.literal(…), …])
136
+ if (node.namedEnumValues?.length) {
137
+ const literals = nonNullValues.map((v) => `z.literal(${formatLiteral(v)})`)
138
+ if (literals.length === 1) return literals[0]!
139
+ return `z.union([${literals.join(', ')}])`
140
+ }
141
+
142
+ // Regular enum: use z.enum([…])
143
+ return `z.enum([${nonNullValues.map(formatLiteral).join(', ')}])`
144
+ },
145
+
146
+ ref(node) {
147
+ if (!node.name) return undefined
148
+ const refName = node.ref ? (ast.extractRefName(node.ref) ?? node.name) : node.name
149
+ const resolvedName = node.ref ? (this.options.resolver?.default(refName, 'function') ?? refName) : node.name
150
+
151
+ if (node.ref && this.options.cyclicSchemas?.has(refName)) {
152
+ return `z.lazy(() => ${resolvedName})`
153
+ }
154
+
155
+ return resolvedName
156
+ },
157
+ object(node) {
158
+ const properties = node.properties
159
+ .map((prop) => {
160
+ const { name: propName, schema } = prop
161
+
162
+ const meta = ast.syncSchemaRef(schema)
163
+
164
+ const isNullable = meta.nullable
165
+ const isOptional = schema.optional
166
+ const isNullish = schema.nullish
167
+
168
+ const hasSelfRef = this.options.cyclicSchemas != null && ast.containsCircularRef(schema, { circularSchemas: this.options.cyclicSchemas })
169
+ // Inside a getter the getter itself defers evaluation, so suppress
170
+ // z.lazy() wrapping on nested refs by temporarily clearing cyclicSchemas.
171
+ if (hasSelfRef) this.options.cyclicSchemas = undefined
172
+ const baseOutput = this.transform(schema) ?? this.transform(ast.createSchema({ type: 'unknown' }))!
173
+ if (hasSelfRef) this.options.cyclicSchemas = options.cyclicSchemas
174
+
175
+ const wrappedOutput = this.options.wrapOutput ? this.options.wrapOutput({ output: baseOutput, schema }) || baseOutput : baseOutput
176
+
177
+ const value = applyMiniModifiers({
178
+ value: wrappedOutput,
179
+ nullable: isNullable,
180
+ optional: isOptional,
181
+ nullish: isNullish,
182
+ defaultValue: meta.default,
183
+ })
184
+
185
+ if (hasSelfRef) {
186
+ return `get "${propName}"() { return ${value} }`
187
+ }
188
+ return `"${propName}": ${value}`
189
+ })
190
+ .join(',\n ')
191
+
192
+ return `z.object({\n ${properties}\n })`
193
+ },
194
+ array(node) {
195
+ const items = (node.items ?? []).map((item) => this.transform(item)).filter(Boolean)
196
+ const inner = items.join(', ') || this.transform(ast.createSchema({ type: 'unknown' }))!
197
+ let result = `z.array(${inner})${lengthChecksMini(node)}`
198
+
199
+ if (node.unique) {
200
+ result += `.refine(items => new Set(items).size === items.length, { message: "Array entries must be unique" })`
201
+ }
202
+
203
+ return result
204
+ },
205
+ tuple(node) {
206
+ const items = (node.items ?? []).map((item) => this.transform(item)).filter(Boolean)
207
+
208
+ return `z.tuple([${items.join(', ')}])`
209
+ },
210
+ union(node) {
211
+ const nodeMembers = node.members ?? []
212
+ const members = nodeMembers.map((m) => this.transform(m)).filter(Boolean)
213
+ if (members.length === 0) return ''
214
+ if (members.length === 1) return members[0]!
215
+ if (node.discriminatorPropertyName && !nodeMembers.some((m) => m.type === 'intersection')) {
216
+ // z.discriminatedUnion requires ZodObject members; intersections (ZodIntersection) are not
217
+ // assignable to $ZodDiscriminant, so fall back to z.union when any member is an intersection.
218
+ return `z.discriminatedUnion(${stringify(node.discriminatorPropertyName)}, [${members.join(', ')}])`
219
+ }
220
+
221
+ return `z.union([${members.join(', ')}])`
222
+ },
223
+ intersection(node) {
224
+ const members = node.members ?? []
225
+ if (members.length === 0) return ''
226
+
227
+ const [first, ...rest] = members
228
+ if (!first) return ''
229
+
230
+ let base = this.transform(first)
231
+ if (!base) return ''
232
+
233
+ for (const member of rest) {
234
+ if (member.primitive === 'string') {
235
+ const s = ast.narrowSchema(member, 'string')
236
+ const c = lengthChecksMini(s ?? {})
237
+ if (c) {
238
+ base += c
239
+ continue
240
+ }
241
+ } else if (member.primitive === 'number' || member.primitive === 'integer') {
242
+ const n = ast.narrowSchema(member, 'number') ?? ast.narrowSchema(member, 'integer')
243
+ const c = numberChecksMini(n ?? {})
244
+ if (c) {
245
+ base += c
246
+ continue
247
+ }
248
+ } else if (member.primitive === 'array') {
249
+ const a = ast.narrowSchema(member, 'array')
250
+ const c = lengthChecksMini(a ?? {})
251
+ if (c) {
252
+ base += c
253
+ continue
254
+ }
255
+ }
256
+ const transformed = this.transform(member)
257
+ if (transformed) base = `z.intersection(${base}, ${transformed})`
258
+ }
259
+
260
+ return base
261
+ },
262
+ ...options.nodes,
263
+ },
264
+ print(node) {
265
+ const { keysToOmit } = this.options
266
+
267
+ let base = this.transform(node)
268
+ if (!base) return null
269
+
270
+ const meta = ast.syncSchemaRef(node)
271
+
272
+ if (keysToOmit?.length && meta.primitive === 'object' && !(meta.type === 'union' && meta.discriminatorPropertyName)) {
273
+ // Mirror printerTs `nonNullable: true`: when omitting keys, the resulting
274
+ // schema is a new non-nullable object type — skip optional/nullable/nullish.
275
+ // Discriminated unions (z.discriminatedUnion) do not support .omit(), so skip them.
276
+
277
+ // If this is a lazy reference, apply omit inside the lazy function
278
+ const lazyMatch = base.match(/^z\.lazy\(\(\)\s*=>\s*(.+)\)$/)
279
+ if (lazyMatch) {
280
+ base = `z.lazy(() => ${lazyMatch[1]}.omit({ ${keysToOmit.map((k: string) => `"${k}": true`).join(', ')} }))`
281
+ } else {
282
+ base = `${base}.omit({ ${keysToOmit.map((k: string) => `"${k}": true`).join(', ')} })`
283
+ }
284
+ }
285
+
286
+ return applyMiniModifiers({
287
+ value: base,
288
+ nullable: meta.nullable,
289
+ optional: meta.optional,
290
+ nullish: meta.nullish,
291
+ defaultValue: meta.default,
292
+ })
293
+ },
294
+ }
295
+ })
@@ -0,0 +1,57 @@
1
+ import { camelCase, pascalCase } from '@internals/utils'
2
+ import { defineResolver } from '@kubb/core'
3
+ import type { PluginZod } from '../types.ts'
4
+
5
+ /**
6
+ * Naming convention resolver for Zod plugin.
7
+ *
8
+ * Provides default naming helpers using camelCase with a `Schema` suffix for schemas.
9
+ *
10
+ * @example
11
+ * `resolverZod.default('list pets', 'function') // → 'listPetsSchema'`
12
+ */
13
+ export const resolverZod = defineResolver<PluginZod>((ctx) => {
14
+ return {
15
+ name: 'default',
16
+ pluginName: 'plugin-zod',
17
+ default(name, type) {
18
+ return camelCase(name, { isFile: type === 'file', suffix: type ? 'schema' : undefined })
19
+ },
20
+ resolveSchemaName(name) {
21
+ return camelCase(name, { suffix: 'schema' })
22
+ },
23
+ resolveSchemaTypeName(name) {
24
+ return pascalCase(name, { suffix: 'schema' })
25
+ },
26
+ resolveTypeName(name) {
27
+ return pascalCase(name)
28
+ },
29
+ resolvePathName(name, type) {
30
+ return ctx.default(name, type)
31
+ },
32
+ resolveParamName(node, param) {
33
+ return ctx.resolveSchemaName(`${node.operationId} ${param.in} ${param.name}`)
34
+ },
35
+ resolveResponseStatusName(node, statusCode) {
36
+ return ctx.resolveSchemaName(`${node.operationId} Status ${statusCode}`)
37
+ },
38
+ resolveDataName(node) {
39
+ return ctx.resolveSchemaName(`${node.operationId} Data`)
40
+ },
41
+ resolveResponsesName(node) {
42
+ return ctx.resolveSchemaName(`${node.operationId} Responses`)
43
+ },
44
+ resolveResponseName(node) {
45
+ return ctx.resolveSchemaName(`${node.operationId} Response`)
46
+ },
47
+ resolvePathParamsName(node, param) {
48
+ return ctx.resolveParamName(node, param)
49
+ },
50
+ resolveQueryParamsName(node, param) {
51
+ return ctx.resolveParamName(node, param)
52
+ },
53
+ resolveHeaderParamsName(node, param) {
54
+ return ctx.resolveParamName(node, param)
55
+ },
56
+ }
57
+ })
package/src/types.ts CHANGED
@@ -1,172 +1,187 @@
1
- import type { Group, Output, PluginFactoryOptions, ResolveNameParams } from '@kubb/core'
2
- import type { contentType, Oas, SchemaObject } from '@kubb/oas'
3
- import type { Exclude, Include, Override, ResolvePathOptions, Schema } from '@kubb/plugin-oas'
4
- import type { Generator } from '@kubb/plugin-oas/generators'
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<Oas>
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
- * Array containing exclude parameters to exclude/skip tags/operations/methods/paths.
86
+ * Tags, operations, or paths to exclude from generation.
22
87
  */
23
88
  exclude?: Array<Exclude>
24
89
  /**
25
- * Array containing include parameters to include tags/operations/methods/paths.
90
+ * Tags, operations, or paths to include in generation.
26
91
  */
27
92
  include?: Array<Include>
28
93
  /**
29
- * Array containing override parameters to override `options` based on tags/operations/methods/paths.
94
+ * Override options for specific tags, operations, or paths.
30
95
  */
31
96
  override?: Array<Override<ResolvedOptions>>
32
97
  /**
33
- * Path to Zod
34
- * It used as `import { z } from '${importPath}'`.
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
- * Choose to use date or datetime as JavaScript Date instead of string.
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 Zod generated schema as type with z.infer<TYPE>
108
+ * Return schemas as inferred types using `z.infer`.
82
109
  */
83
110
  inferred?: boolean
84
111
  /**
85
- * Use of z.coerce.string() instead of z.string()
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
- * Which version of Zod should be used.
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
- version?: '3' | '4'
118
+ operations?: boolean
123
119
  /**
124
- * Which Zod GUID validator to use for OpenAPI `format: uuid`.
125
- * - 'uuid' uses UUID validation.
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 support.
132
- * When enabled, generates functional syntax (e.g., `z.optional(z.string())`) instead of chainable methods (e.g., `z.string().optional()`).
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 function to wrap the output of the generated zod schema
132
+ * Callback to wrap the generated schema output.
139
133
  *
140
- * This is useful for edge case scenarios where you might leverage something like `z.object({ ... }).openapi({ example: { some: "complex-example" }})`
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: SchemaObject }) => string | undefined
136
+ wrapOutput?: (arg: { output: string; schema: ast.SchemaNode }) => string | undefined
145
137
  /**
146
- * Define some generators next to the zod generators
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<Oas>
153
- group: Options['group']
154
- override: NonNullable<Options['override']>
155
- transformers: NonNullable<Options['transformers']>
156
- dateType: NonNullable<Options['dateType']>
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, never, ResolvePathOptions>
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
+ }