Beta You're reading the docs for Kubb v5, which is currently in beta. View the stable v4 docs
Skip to content

Override a printer

A printer is the last step of Kubb's pipeline. Adapters turn a spec into the AST, macros rewrite the nodes, and a printer turns each schema node into code for one output target. @kubb/plugin-ts prints TypeScript type nodes, @kubb/plugin-zod prints Zod expressions, and @kubb/plugin-faker prints Faker expressions.

These three plugins expose their printer through a printer.nodes option, a partial map of schema types to handlers. A handler replaces the built-in output for one schema type, so you can print a date schema as the JavaScript Date object or append .openapi(...) metadata to every Zod object without forking the plugin.

Shape

The map is keyed by the schema type discriminant, such as 'string', 'integer', 'date', 'enum', or 'object'. Supply only the handlers you want to replace and the built-in ones fill in the rest.

Type definition
typescript
type PrinterNodes = Partial<{
  [K in SchemaType]: (this: Context, node: SchemaNodeByType[K]) => Output | null
}>

Handlers run with a this context, so write them as regular functions rather than arrow functions. this.transform(node) recurses into a nested schema node through the full handler map, overrides included. this.base(node) runs the built-in handler your override replaced, so you can wrap its output instead of rebuilding it. this.options reads the resolved printer options, such as arrayType on @kubb/plugin-ts.

TypeScript types

@kubb/plugin-ts builds TypeScript AST nodes, so a handler returns a ts.TypeNode created with the compiler's factory. This override prints date schemas as the JavaScript Date object instead of string.

date.ts
typescript
import ts from 'typescript'
import {  } from '@kubb/plugin-ts'

({
  : {
    : {
      () {
        return ts..('Date', [])
      },
    },
  },
})

Zod schemas

@kubb/plugin-zod prints expression strings, so a handler returns the Zod code as a string. With mini: true the same overrides target the Zod Mini printer instead.

date.ts
typescript
import {  } from '@kubb/plugin-zod'

({
  : {
    : {
      () {
        return 'z.iso.date()'
      },
    },
  },
})

Use this.base to keep the default output and decorate it. This override appends .openapi(...) to every object schema, and nested nodes still print through the regular handlers.

openapi.ts
typescript
import {  } from '@kubb/plugin-zod'

({
  : {
    : {
      () {
        return `${this.()}.openapi(${.({ : . })})`
      },
    },
  },
})

Faker mocks

@kubb/plugin-faker also prints strings, one Faker expression per schema node. This override generates floats where the spec declares integers.

integer.ts
typescript
import {  } from '@kubb/plugin-faker'

({
  : {
    : {
      () {
        return 'faker.number.float()'
      },
    },
  },
})

Printer override or macro

A macro rewrites the node itself, before anything prints. Retype integer schemas to string with a macro and plugin-ts, plugin-zod, and plugin-faker all follow, because they print the rewritten node. A printer override changes what one plugin emits for a node type. The node stays as it is, and so does the output of every other plugin.

Reach for a printer override when the output cannot be described as another schema node. No schema node prints as Date, and none carries an .openapi(...) call, so a macro cannot produce either.

TIP

The two compose. The macros option on the same plugin rewrites nodes first, then the printer prints the result, overrides included.

Writing your own printer

Plugin authors create complete printers with ast.createPrinter from kubb/kit. The builder receives resolved options and returns the handler map, an overrides field that user-supplied handlers flow into, and an optional top-level print that wraps the output in a declaration. Pass user overrides through overrides rather than spreading them into nodes, otherwise this.base cannot find the original handler.

printer.ts
typescript
import {  } from 'kubb/kit'

type  = .<'docs', { ?: boolean }, string>

export const  = .<>(() => ({
  : 'docs',
  ,
  : {
    : () => 'string',
    : () => 'number',
    () {
      const  = ..(() => `${.}: ${this.(.)}`).(', ')
      return `{ ${} }`
    },
  },
}))

See the Kit API reference for the helper and Parsers concepts for how parsers consume printers.