Skip to content
Kit

Generators

defineGenerator declares a named generator unit that walks the AST and emits files. Covers the schema, operation, and operations methods and the GeneratorContext passed to each.

defineGenerator

defineGenerator declares a named generator unit consumed by a plugin. Generators walk the AST and emit files. Kubb calls each method for the matching node type.

Each generator method returns TElement | Array<FileNode> | void. Returning a renderer element (for example JSX from kubb/jsx) requires a renderer factory on the generator.

my-generator.ts
import { ast, defineGenerator } from 'kubb/kit'

const myGenerator = defineGenerator({
  name: 'my-generator',
  operation(node, ctx) {
    return [
      ast.factory.createFile({
        baseName: `${node.operationId}.ts`,
        path: `./${node.operationId}.ts`,
        sources: [
          ast.factory.createSource({
            nodes: [ast.factory.createText(`export const op = '${node.operationId}'`)],
          }),
        ],
      }),
    ]
  },
})

Generator methods

MethodInputOutputWhen to use
schema()SchemaNode (per data schema)TElement | Array<FileNode> | voidGenerate types, validators, factories. Called once per schema
operation()OperationNode (per API operation)TElement | Array<FileNode> | voidGenerate hooks, clients, handlers. Called once per operation
operations()Array<OperationNode> (all operations)TElement | Array<FileNode> | voidGenerate index or barrel files. Called once after all operations

Scoping with match

Add a match(node, ctx) predicate to skip schema or operation for nodes a generator does not apply to. A false result skips that node. Omitting match runs the generator for every node. match does not filter operations().

scoped-generator.ts
import { ast, defineGenerator } from 'kubb/kit'

const getOnlyGenerator = defineGenerator({
  name: 'get-only-generator',
  match(node, ctx) {
    return node.kind === 'Operation' && ast.isHttpOperationNode(node) && node.method.toLowerCase() === 'get'
  },
  operation(node, ctx) {
    // node is already known to be a GET operation here
    return
  },
})

GeneratorContext properties (the ctx argument passed to each method)

PropertyTypePurpose
ctx.configConfigResolved Kubb configuration
ctx.rootstringAbsolute path to the output directory for the current plugin
ctx.optionsTResolvedOptionsPer-node resolved options (after exclude/include/override filtering)
ctx.pluginPluginThe owning plugin descriptor
ctx.resolverResolverResolver for the current plugin
ctx.driverKubbDriverPlugin driver for cross-plugin access
ctx.hooksHookable<KubbHooks>Event bus for KubbHooks events
ctx.adapterAdapterThe adapter that parsed the input spec
ctx.metaInputMetaDocument metadata from the adapter. Carries title, version, baseURL, every declared servers entry and securitySchemes entry, and the pre-computed circularNames and enumNames arrays.
ctx.cacheNodeCacheCache scoped to the node being generated, shared by every plugin generating from that node in the current pass. Exposes readItem, writeItem, and ensureItem
ctx.addFile()(...files: FileNode[]) => Promise<void>Add files, skipping any that already exist
ctx.upsertFile()(...files: FileNode[]) => Promise<void>Add or merge files (concatenates sources and imports)
ctx.getPlugin()(name: string) => Plugin | undefinedGet a plugin by name
ctx.requirePlugin()(name: string) => PluginGet a plugin by name or throw a descriptive error
ctx.getResolver()(name: string) => ResolverGet a resolver by plugin name
ctx.info()(message: string, options?: { code?, help?, location? }) => voidEmit an info message via the build event system
ctx.warn()(message: string, options?: { code?, help?, location? }) => voidEmit a warning via the build event system. options sets the fix and the source pointer
ctx.error()(error: string | Error, options?: { code?, help?, location? }) => voidEmit an error via the build event system. A Diagnostics.Error keeps its code, help, and location