Skip to content

@kubb/plugin-zod

Generate Zod validation schemas from your OpenAPI schema.

TIP

Support for Zod v4 when using Kubb v3.8.1, see Zod 4 migration guide

Installation

shell
bun add -d @kubb/plugin-zod
shell
pnpm add -D @kubb/plugin-zod
shell
npm install --save-dev @kubb/plugin-zod
shell
yarn add -D @kubb/plugin-zod

Options

output

Specify the export location for the files and define the behavior of the output.

output.path

Path to the output folder or file that contains the generated code.

TIP

if output.path is a file, group cannot be used.

Type:string
Required:true
Default:'zod'

output.barrelType

Specify what to export and optionally disable barrel file generation.

TIP

Using propagate will prevent a plugin from creating a barrel file, but it will still propagate, allowing output.barrelType to export the specific function or type.

Type:'all' | 'named' | 'propagate' | false
Required:false
Default:'named'
typescript
export * from "./gen/petService.ts"
typescript
export { PetService } from "./gen/petService.ts"
typescript
typescript

output.banner

Add a banner comment at the top of every generated file.

Type:string | (oas: Oas) => string
Required:false

Add a footer comment at the end of every generated file.

Type:string | (oas: Oas) => string
Required:false

output.override

Whether Kubb overrides existing external files that can be generated if they already exist.

Type:boolean
Required:false
Default:false

contentType

Define which content type to use.

By default, Kubb uses the first JSON-valid media type.

Type:'application/json' | (string & {})
Required:false

group

Grouping combines files in a folder based on a specific type.

For example, with this configuration:

kubb.config.ts
typescript
group: {
  type: 'tag',
  name({ group }){
    return `${group}Controller`
  }
}

This generates the following structure:

.
├── src/
│   └── petController/
│   │   ├── addPet.ts
│   │   └── getPet.ts
│   └── storeController/
│       ├── createStore.ts
│       └── getStoreById.ts
├── petStore.yaml
├── kubb.config.ts
└── package.json

group.type

Specify the property to group files by. Required when group is defined.

Type:'tag'
Required:true*

NOTE

Required: true* means this is required only when the group option is used. The group option itself is optional.

  • 'tag': Uses the first tag from operation.getTags().at(0)?.name

group.name

Return the name of a group based on the group name, this will be used for the file and name generation.

Type:(context: GroupContext) => string
Required:false
Default:(ctx) => '${ctx.group}Controller'

importPath

Type:string
Required:false
Default:'zod'

typed

Use TypeScript(@kubb/plugin-ts) to add type annotation.

IMPORTANT

We rely on ToZod from the creator of Zod to create a schema based on a type. Kubb contains its own version to those kind of conversions.

Type:boolean
Required:false
Default:false

inferred

Return Zod generated schema as type with z.infer.

Type:boolean
Required:false
Default:false

dateType

Choose to use date or datetime as JavaScript Date instead of string.
See DateTimes.

Type:false | 'string' | 'stringOffset' | 'stringLocal' | 'date'
Required:false
Default:'string'
typescript
z.string();
typescript
z.string().datetime();
typescript
z.string().datetime({ offset: true });
typescript
z.string().datetime({ local: true });
typescript
z.date();

unknownType

Which type to use when the Swagger/OpenAPI file is not providing more information.

Type:'any' | 'unknown' | 'void'
Required:false
Default:'any'
typescript
z.any();
typescript
z.unknown();
typescript
z.void()

emptySchemaType

Which type to use for empty schema values.

Type:'any' | 'unknown' | 'void'
Required:false
Default:unknownType
typescript
z.any()
typescript
z.unknown()
typescript
z.void()

coercion

Use of z.coerce.string() instead of z.string(). Coercion for primitives

Type:boolean | { dates?: boolean, strings?: boolean, numbers?: boolean}
Required:false
Default:false'
typescript
z.coerce.string();
z.coerce.date();
z.coerce.number();
typescript
z.string();
z.date();
z.number();
typescript
z.string();
z.date();
z.coerce.number();

operations

Type:boolean
Required:false
Default:false

mapper

Type:Record<string, string>
Required:false

version

Which version of Zod should be used.

Type:'3' | '4'
Required:false
Default:'3'

guidType

Which validator to use for OpenAPI format: uuid.

Type:'uuid' | 'guid'
Required:false
Default:'uuid'

NOTE

guid is only used with version: '4'. With version: '3', Kubb falls back to uuid.

typescript
z.uuid()
typescript
z.guid()

mini beta new in 4.8.0

Use Zod Mini's functional API for better tree-shaking support.

When enabled, generates functional syntax (e.g., z.optional(z.string())) instead of chainable methods (e.g., z.string().optional()).

Requires Zod v4 or later. When mini: true, version will be set to '4' and importPath will default to 'zod/mini'.

WARNING

This feature is currently in beta. The API may change in future releases.

TIP

Zod Mini provides a smaller bundle size with better tree-shaking. See Zod Mini documentation for more details.

Type:boolean
Required:false
Default:false
typescript
// Import from zod/mini
import { z } from 'zod/mini'

// Functional syntax for better tree-shaking
z.optional(z.string())
z.nullable(z.number())
z.array(z.string()).check(z.minLength(1), z.maxLength(10))
typescript
// Import from zod or zod/v4
import { z } from 'zod'

// Chainable method syntax
z.string().optional()
z.number().nullable()
z.array(z.string()).min(1).max(10)

include

Array containing include parameters to include tags, operations, methods, paths, or content types.

Type:Array<Include>
Required:false
Include
typescript
export type Include = {
  type: 'tag' | 'operationId' | 'path' | 'method' | 'contentType'
  pattern: string | RegExp
}

exclude

Array containing exclude parameters to exclude or skip tags, operations, methods, paths, or content types.

Type:Array<Exclude>
Required:false
Exclude
typescript
export type Exclude = {
  type: 'tag' | 'operationId' | 'path' | 'method' | 'contentType'
  pattern: string | RegExp
}

override

Array containing override parameters to override options based on tags, operations, methods, paths, or content types.

Type:Array<Override>
Required:false
Override
typescript
export type Override = {
  type: 'tag' | 'operationId' | 'path' | 'method' | 'contentType'
  pattern: string | RegExp
  options: PluginOptions
}

generators

See Generators for more information on how to use generators.

Type:Array<Generator<PluginZod>>
Required:false

transformers

transformers.name

Customize the names based on the type that is provided by the plugin.

Type:(name: string, type?: ResolveType) => string
Required:false
typescript
type ResolveType = "file" | "function" | "type" | "const";

transformers.schema

Customize the schema based on the type that is provided by the plugin.

Type:(props: { schema?: SchemaObject; name?: string; parentName?: string}, defaultSchemas: Schema[],) => Schema[] | undefined
Required:false

wrapOutput

Modify the generated zod schema.

TIP

This is useful for cases where you need to extend the generated zod output with additional properties from an OpenAPI schema. E.g. in the case of OpenAPI -> Zod -> OpenAPI, you could include the examples from the schema for a given property and then ultimately provide a modified schema to a router that supports zod and OpenAPI spec generation.

Conditionally append .openapi() to the generated schema
typescript
wrapOutput: ({ output, schema }) => {
  const metadata: ZodOpenAPIMetadata = {};

  if (schema.example) {
    metadata.example = schema.example;
  }

  if (Object.keys(metadata).length > 0) {
    return `${output}.openapi(${JSON.stringify(metadata)})`;
  }
};
Type:(arg: { output: string; schema: SchemaObject }) => string | undefined
Required:false

Example

typescript
import { 
defineConfig
} from "@kubb/core";
import {
pluginOas
} from "@kubb/plugin-oas";
import {
pluginTs
} from "@kubb/plugin-ts";
import {
pluginZod
} from "@kubb/plugin-zod";
export default
defineConfig
({
input
: {
path
: "./petStore.yaml",
},
output
: {
path
: "./src/gen",
},
plugins
: [
pluginOas
(),
pluginTs
(),
pluginZod
({
output
: {
path
: "./zod",
},
group
: {
type
: "tag",
name
: ({
group
}) => `${
group
}Schemas` },
typed
: true,
dateType
: "stringOffset",
unknownType
: "unknown",
importPath
: "zod",
wrapOutput
: ({
output
,
schema
}) =>
`${
output
}.openapi({ description: 'This is a custom extension' })`,
}), ], });

See Also

Released under the MIT License.