Skip to content

Core API

@kubb/core is the low-level foundation of Kubb. It exports every primitive you need to embed Kubb programmatically, write a custom plugin, implement a new storage backend, or extend the generation pipeline.

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

TIP

Most users do not install @kubb/core directly. The top-level kubb package re-exports it with adapterOas and parserTs pre-installed. Use @kubb/core directly when embedding Kubb programmatically or writing a plugin.

typescript
import { defineConfig } from 'kubb'
import {
  defineGenerator,
  defineParser,
  definePlugin,
  defineResolver,
  defineLogger,
  defineMiddleware,
  createAdapter,
  createKubb,
  createStorage,
  fsStorage,
  memoryStorage,
  FileManager,
  FileProcessor,
  KubbDriver,
  AsyncEventEmitter,
  URLPath,
  isInputPath,
  hasBuildError,
  logLevel,
  ast,
} from '@kubb/core'

NOTE

@kubb/core re-exports the entire @kubb/ast module under the ast namespace. You can equivalently import helpers directly from @kubb/ast.

Configuration

defineConfig

defineConfig is the primary way to add TypeScript type-checking to a kubb.config.ts file. It is exported from the kubb package (not @kubb/core) and automatically applies production-ready defaults: adapterOas as the adapter, [parserTs, parserTsx] as parsers, and [middlewareBarrel()] as middleware.

typescript
import {  } from 'kubb'

export default ({
  : { : './petStore.yaml' },
  : { : './src/gen' },
})

The function form receives the CLI options at runtime, which lets you toggle behavior based on flags like --watch:

typescript
import {  } from 'kubb'

export default (({  }) => ({
  : { : './petStore.yaml' },
  : { : './src/gen', : ! },
}))

IMPORTANT

defineConfig is only exported from the kubb package. The @kubb/core package exports the raw UserConfig type but does not provide a defineConfig with defaults.

TIP

The output.barrelType default of 'named' applies only when middlewareBarrel is present in the middleware list. Providing a custom middleware list without middlewareBarrel leaves barrelType untouched.

Build

createKubb

createKubb is the entry point for driving Kubb programmatically. It accepts a UserConfig and returns a Kubb instance. Calling .build() on the instance runs the full generation pipeline and returns a BuildOutput object.

Use createKubb when you need to orchestrate multiple builds, inspect diagnostics, or integrate Kubb output into a larger toolchain. For a single one-off build, chain the call directly: await createKubb(config).build().

typescript
// @module: esnext
import { createKubb, hasBuildError } from '@kubb/core'
import { pluginTs } from '@kubb/plugin-ts'
import { pluginClient } from '@kubb/plugin-client'

const kubb = createKubb({
  input: { path: './petStore.yaml' },
  output: { path: './gen' },
  plugins: [pluginTs(), pluginClient()],
})

const { files, storage, driver, diagnostics } = await kubb.safeBuild()

if (hasBuildError(diagnostics)) {
  for (const diagnostic of diagnostics) {
    if (diagnostic.severity === 'error') {
      console.error(`${diagnostic.plugin ?? 'kubb'}: ${diagnostic.message}`)
    }
  }
  process.exit(1)
}

// Per-plugin timings are carried as `timing` diagnostics.
for (const { plugin, duration } of diagnostics.filter((diagnostic) => diagnostic.kind === 'timing')) {
  console.log(`${plugin}: ${duration}ms`)
}
console.log(`Generated ${files.length} files`)
const paths = await storage.getKeys()
paths.forEach((path) => console.log(`  ${path}`))

Kubb instance members (all getters are read-only)

Member Type Description
.setup() () => Promise<void> Resolves config and initializes the driver. build() calls this automatically.
.build() () => Promise<BuildOutput> Runs the full pipeline and throws a BuildError when any diagnostic is an error.
.safeBuild() () => Promise<BuildOutput> Runs the full pipeline and collects problems in BuildOutput.diagnostics instead of throwing.
.hooks AsyncEventEmitter<KubbHooks> Read-only getter. Shared event emitter; attach listeners before calling build().
.storage Storage Read-only getter. Final source code keyed by absolute path. Populated after build.
.driver KubbDriver Read-only getter. Available after setup(). Throws if accessed before setup().
.config Config Read-only getter. Resolved config; available after setup(). Throws if accessed before setup().

BuildOutput fields

Field Type Description
files Array<FileNode> Generated files with paths, names, and content
storage Storage Generated source code accessible via the Storage API
driver KubbDriver Plugin driver instance for advanced introspection
diagnostics Array<Diagnostic> Problems collected during the build, plus a timing diagnostic per plugin

Each Diagnostic carries a code, a severity (error, warning, or info), a message, and the plugin that produced it. Failed-plugin diagnostics also keep the original error on cause, and timing diagnostics (kind: 'timing') carry a duration in milliseconds.

WARNING

After safeBuild(), check hasBuildError(diagnostics) before processing files. Plugins can fail without safeBuild() throwing. build() throws a BuildError in that case instead.

Plugin authoring

Plugins are the primary extension point in Kubb. Each plugin owns its file naming, output folder, lifecycle hooks, and the generators that walk the AST and emit FileNode objects.

definePlugin

definePlugin wraps a factory function and returns a typed Plugin. All lifecycle handlers live under a single hooks object, inspired by Astro integrations.

typescript
import {  } from '@kubb/core'

export const  = ((: { ?: string } = {}) => ({
  : 'plugin-example',
  : {
    'kubb:plugin:setup'() {
      // Register resolvers, generators, and options here.
    },
  },
}))

Plugin shape

Property Type Required Description
name string Yes Unique plugin identifier (e.g., plugin-ts)
dependencies Array<string> No Names of other plugins this one requires
options unknown No User-supplied options passed through to generators
hooks { 'kubb:plugin:setup'?: ...; ... } Yes Lifecycle handlers (see Plugin API)

KubbPluginSetupContext methods (passed to kubb:plugin:setup)

Method Signature Purpose
addGenerator (generator: Generator) => void Register a generator for this plugin
setResolver (resolver: Partial<Resolver>) => void Set or partially override the file naming resolver
setTransformer (visitor: Visitor) => void Set the AST transformer (pre-processes nodes before generators)
setRenderer (renderer: RendererFactory) => void Set the renderer factory for JSX-based generators
setOptions (options: ResolvedOptions) => void Set the resolved options used by generators
injectFile (file: UserFileNode) => void Inject a raw file into the build output, bypassing generation
updateConfig (config: Partial<Config>) => void Merge a partial config update into the current build config
config Config The resolved build configuration at setup time
options TOptions The plugin's own options as passed by the user

IMPORTANT

Plugin names should follow the convention plugin-<feature> (e.g., plugin-react-query, plugin-zod). See Creating plugins for naming conventions.

defineGenerator

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

Each generator method returns TElement | Array<FileNode> | void. Returning a renderer element (e.g., JSX from @kubb/renderer-jsx) requires declaring a renderer factory on the generator. Returning Array<FileNode> directly or calling ctx.upsertFile() manually and returning void works without a renderer.

typescript
import {  } from '@kubb/core'
import { , ,  } from '@kubb/ast'

const  = ({
  : 'my-generator',
  (, ) {
    return [
      ({
        : `${.}.ts`,
        : `./${.}.ts`,
        : [
          ({
            : [(`export const op = '${.}'`)],
          }),
        ],
      }),
    ]
  },
})

Generator methods

Method Input Output When to use
schema() SchemaNode (per data schema) TElement | Array<FileNode> | void Generate types, validators, factories; called once per schema
operation() OperationNode (per API operation) TElement | Array<FileNode> | void Generate hooks, clients, handlers; called once per operation
operations() Array<OperationNode> (all operations) TElement | Array<FileNode> | void Generate index or barrel files; called once after all operations

GeneratorContext properties (the ctx argument passed to each method)

Property Type Purpose
ctx.config Config Resolved Kubb configuration
ctx.root string Absolute path to the output directory for the current plugin
ctx.getMode (output: { path: string }) => 'single' | 'split' Returns 'single' when output.path has a file extension
ctx.options TResolvedOptions Per-node resolved options (after exclude/include/override filtering)
ctx.plugin Plugin The owning plugin descriptor
ctx.resolver Resolver Resolver for the current plugin
ctx.transformer Visitor | undefined Composed transformer for the current plugin
ctx.driver KubbDriver Plugin driver for cross-plugin access
ctx.hooks AsyncEventEmitter<KubbHooks> Event bus; subscribe to KubbHooks events
ctx.adapter Adapter The adapter that parsed the input spec
ctx.meta InputMeta Document metadata from the adapter. Carries title, version, baseURL, and the pre-computed circularNames and enumNames arrays.
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 | undefined Get a plugin by name
ctx.requirePlugin() (name: string) => Plugin Get a plugin by name or throw a descriptive error
ctx.getResolver() (name: string) => Resolver Get a resolver by plugin name
ctx.info() (message: string) => void Emit an info message via the build event system
ctx.warn() (message: string) => void Emit a warning via the build event system
ctx.error() (error: string | Error) => void Emit an error via the build event system

TIP

Return an empty array [] to skip a node without error. Return void to handle file writing manually via ctx.upsertFile().

defineResolver

defineResolver creates a resolver that controls file naming and path resolution for a plugin. The builder is a zero-argument function; use this to call sibling resolver methods.

The builder must return at least { name, pluginName }. All other resolver methods (default, resolveOptions, resolvePath, resolveFile, resolveBanner, resolveFooter) receive built-in defaults and can be individually overridden.

typescript
import {  } from '@kubb/core'
import type { ,  } from '@kubb/core'

// Extend the base Resolver with plugin-specific naming methods.
type  =  & {
  (: { : string }): string
}

type  = <'plugin-example', object, object, >

export const  = <>(() => ({
  : 'default',
  : 'plugin-example',
  () {
    return this.(., 'function')
  },
}))

Auto-injected resolver defaults

Method Default behavior
default camelCase for function/file, PascalCase for type
resolveOptions Applies exclude, include, and override filters
resolvePath Resolves to output.path, with optional tag/path-based subdirectories
resolveFile Constructs a full FileNode using default + resolvePath
resolveBanner Returns output.banner or the standard "Generated by Kubb" header
resolveFooter Returns output.footer when set

defineParser

defineParser creates a parser that converts generated file ASTs to formatted source strings. Each parser declares which file extensions it handles via extNames.

The built-in parsers, @kubb/parser-ts and its TSX variant, handle TypeScript and TSX files. Implement defineParser to add support for other languages or custom output formats.

defineLogger

defineLogger wraps a logger definition into a typed Logger object. The install method receives context, an AsyncEventEmitter<KubbHooks>, and subscribes to lifecycle events to produce log output.

typescript
import {  } from '@kubb/core'

export const  = ({
  : 'my-logger',
  () {
    .('kubb:info', ({  }) => .('', ))
    .('kubb:warn', ({  }) => .('', ))
    .('kubb:error', ({  }) => .('', .))
  },
})

Log levels (set via logLevel in config)

Level Usage Output
silent Production, CI No output
info Normal development Status messages
verbose Debugging builds Timing info, plugin details

defineMiddleware

defineMiddleware creates a middleware factory using the hook-style hooks API. Middleware handlers fire after all plugin handlers for any given event, making them ideal for post-processing, logging, and auditing.

The factory can accept typed options. Per-build state (such as accumulators) belongs inside the factory closure so that each createKubb invocation gets its own isolated instance.

typescript
import {  } from '@kubb/core'

export const  = (() => ({
  : 'log-middleware',
  : {
    'kubb:build:end'({  }) {
      .(`Build complete with ${.} files`)
    },
  },
}))

Middleware can also accept options:

typescript
import {  } from '@kubb/core'

export const  = ((: { : string } = { : '' }) => {
  const  = new <string>()
  return {
    : 'prefix-middleware',
    : {
      'kubb:plugin:end'({  }) {
        .(`${.}${.}`)
      },
    },
  }
})

Usage in kubb.config.ts:

typescript
// @filename: logMiddleware.ts
import {  } from '@kubb/core'

export const  = (() => ({
  : 'log-middleware',
  : {
    'kubb:build:end'({  }) {
      .(`Build complete with ${.} files`)
    },
  },
}))

// @filename: kubb.config.ts
import {  } from 'kubb'
import {  } from './logMiddleware'

export default ({
  : { : './petStore.yaml' },
  : { : './src/gen' },
  : [()],
})
typescript
import {  } from '@kubb/core'

export const  = (() => ({
  : 'log-middleware',
  : {
    'kubb:build:end'({  }) {
      .(`Build complete with ${.} files`)
    },
  },
}))

createAdapter

createAdapter is the factory for implementing custom adapters that translate non-OpenAPI specs into Kubb's universal AST. Built-in adapters include @kubb/adapter-oas for OpenAPI and Swagger documents.

Common use cases for custom adapters include GraphQL schemas, gRPC definitions, AsyncAPI specifications, and custom domain-specific languages.

IMPORTANT

Adapters must parse their input format to Kubb's InputNode structure. See Adapter API for complete documentation.

Storage

Storage backends control where generated files are written. Kubb provides filesystem and in-memory implementations out of the box. Use createStorage to implement any custom backend.

createStorage

createStorage takes a builder function (options: TOptions) => Storage and returns a factory (options?: TOptions) => Storage. Call the returned factory to instantiate the storage (optionally with options).

typescript
import {  } from '@kubb/core'

export const  = (() => {
  const  = new <string, string>()
  return {
    : 'memory',
    async () {
      return .()
    },
    async () {
      return .() ?? null
    },
    async (, ) {
      .(, )
    },
    async () {
      .()
    },
    async () {
      const  = [....()]
      return  ? .(() => .()) : 
    },
    async () {
      if (!) return .()
      for (const  of .()) if (.()) .()
    },
    async () {
      .()
    },
  }
})

TIP

Use memoryStorage for tests and dry-runs. Use fsStorage for normal development and CI/CD.

Storage interface

Method Params Returns Purpose
hasItem() key: string Promise<boolean> Check whether an item exists
getItem() key: string Promise<string | null> Retrieve an item's content
setItem() key: string, value: string Promise<void> Write an item
removeItem() key: string Promise<void> Delete an item
getKeys() base?: string Promise<string[]> List keys, optionally filtered by prefix
clear() base?: string Promise<void> Delete all items, optionally scoped by prefix
dispose?() (none) Promise<void> Optional teardown hook called after the build completes

fsStorage

fsStorage is the built-in filesystem storage backend. Kubb uses it by default when no storage option is set in the config. It creates output directories automatically and respects output.path.

memoryStorage

memoryStorage is the built-in in-memory storage backend. It writes nothing to disk, making it ideal for testing plugins, CI validation, and dry-run scenarios.

NOTE

Both fsStorage and memoryStorage are exported from @kubb/core and can be passed directly to the storage field at the root of your config.

Files & rendering

FileManager

FileManager is the high-level API for managing generated files within the build pipeline. The plugin driver creates and owns one FileManager instance, accessible via driver.fileManager. Inside generators, prefer the context helpers ctx.addFile() and ctx.upsertFile() over accessing the file manager directly.

Key methods

  • add(): Add one or more files. When a file at the same path already exists, the new entry replaces it instead of merging.
  • upsert(): Add or merge files, concatenating sources, imports, and exports when an entry at the same path already exists.
  • getByPath(): Retrieve a file by its absolute path
  • deleteByPath(): Remove a file by its absolute path
  • clear(): Remove all files
  • setOnUpsert(callback | null): Register a single callback invoked with the resolved FileNode on every add / upsert. The build loop uses this to drain newly written files into FileProcessor without scanning the whole cache. Pass null to detach.
  • files: Getter returning all stored files sorted by path length. The sort runs lazily on read, so high-volume upsert calls stay O(1).

Streaming model

FileManager does not expose a stream() method of its own. It streams through setOnUpsert: every addFile() / upsertFile() call invokes the registered callback with the resolved FileNode. The build driver attaches its own callback, so files flow directly into FileProcessor, get parsed one at a time, and land in Storage without buffering. The full cache is only iterated when a consumer reads files, for example inside a middleware that listens on kubb:plugins:end.

FileProcessor

FileProcessor is the lower-level pipeline that processes each FileNode before writing. It runs the registered parsers, falls back to joining raw source strings when no parser claims a file's extension, and yields the result one file at a time. The build pipeline handles this automatically. You rarely need to use FileProcessor directly.

Streaming

FileProcessor.stream(files, options) returns a synchronous Generator<ParsedFile> that yields { file, source, processed, total, percentage } for each file. The generator is synchronous on purpose: it removes a microtask per file from the hot path and lets the build driver pull parsed files as fast as FileManager produces them.

stream.ts
typescript
import { FileProcessor } from '@kubb/core'
import { createFile, createSource, createText } from '@kubb/ast'

const processor = new FileProcessor()
const files = [createFile({ baseName: 'a.ts', path: 'a.ts', sources: [createSource({ nodes: [createText('export {}')] })] })]

for (const { file, source, processed, total } of processor.stream(files)) {
  console.log(`[${processed}/${total}] ${file.path}`)
  console.log(source)
}

Use FileProcessor.run(files, options) for the fire-and-forget variant. It iterates the same generator internally and emits start, update, and end events on the FileProcessor.events emitter.

jsxRenderer (via @kubb/renderer-jsx)

For JSX-based rendering, import jsxRenderer directly from @kubb/renderer-jsx. @kubb/core no longer re-exports a createRenderer factory.

typescript
import {  } from '@kubb/renderer-jsx'

const  = ()

Pass the renderer to ctx.setRenderer() inside a kubb:plugin:setup hook to enable JSX-based generators for your plugin.

jsxRendererSync (via @kubb/renderer-jsx)

jsxRendererSync is a React-free recursive renderer. It accepts the same JSX components as jsxRenderer but skips the React reconciliation pass, so it generates code 2 to 4× faster. Its stream() returns a synchronous Generator<FileNode> and avoids a microtask per file. Use it when generation throughput matters and the plugin does not depend on React-specific behavior. jsxRenderer is still available for plugins that do.

typescript
import {  } from '@kubb/renderer-jsx'

const  = ()

Plugin driver

KubbDriver

KubbDriver orchestrates the entire generation pipeline. It executes plugins in dependency order, emits lifecycle events, manages the FileManager, and routes path/name resolution through each plugin's resolver.

Access the driver via ctx.driver inside generator context methods, or from the build result via result.driver.

Key members

Property Type Purpose
driver.plugins Map<string, Plugin> All installed plugins keyed by name
driver.fileManager FileManager Central file store (add, upsert, getByPath)
driver.config Config Resolved Kubb configuration
driver.hooks AsyncEventEmitter<KubbHooks> Lifecycle event bus for listening and emitting
driver.getPlugin() (name: string) => Plugin | undefined Look up a plugin by name (typed via PluginRegistry)
driver.getResolver() (name: string) => Resolver Look up a plugin's resolver by name

TIP

Subscribe to lifecycle events via driver.hooks.on(event, handler) to observe the full build pipeline from outside of a plugin.

Utilities

AsyncEventEmitter

AsyncEventEmitter is the typed, async-friendly event emitter that drives all KubbHooks. It is type-safe, supports await, and provides error propagation and event filtering.

@kubb/core re-exports AsyncEventEmitter from @internals/utils. You can use it directly if you need to listen to events from a Kubb instance before calling .build().

URLPath

URLPath is a helper class for working with OpenAPI path strings. Its primary use is detecting whether a given path string is a remote URL rather than a local file path.

typescript
import {  } from '@kubb/core'

new ('https://petstore.swagger.io/v2/swagger.json'). // true
new ('./petStore.yaml'). // false

isInputPath

isInputPath is a TypeScript type guard that narrows config.input to InputPath (the { path: string } form) rather than InputData (the { data: ... } form).

typescript
import { isInputPath, type UserConfig } from '@kubb/core'

declare const config: UserConfig

if (isInputPath(config)) {
  const filePath = config.input.path // narrowed to string
} else {
  const spec = config.input.data // narrowed to object | string
}

logLevel

logLevel is a constants object that enumerates the valid log level values. Pass one of these values to the logLevel field in your config or CLI flags.

Level Usage Output
silent Production, CI No output
info Normal development Status messages
verbose Debugging builds Timing info, plugin details

TIP

Use verbose when profiling plugin performance. To write a log file, pick the file reporter with --reporter file.

Public types

@kubb/core re-exports every public type from its types.ts barrel. Import them to type your own plugins, adapters, parsers, and build runners.

Configuration

Type Purpose
Config / UserConfig Resolved and user-facing configuration shapes
PossibleConfig Every accepted form of a Kubb config (object, fn, array, sync/async)
CLIOptions Flags passed to the CLI (--config, --watch, --logLevel)
InputPath / InputData Two discriminants of Config['input']
Output Output configuration (path, clean, barrel)
Group Grouping strategy for generated files (tag or path)
BarrelType 'all' | 'named' | 'propagate' for barrel file generation

Plugins

Type Purpose
Plugin Final plugin object returned from definePlugin
PluginFactoryOptions Generic parameter pack used to type a plugin
NormalizedPlugin Internal representation after driver normalization
KubbPluginSetupContext Context passed to kubb:plugin:setup
KubbBuildStartContext Context passed to kubb:build:start
KubbBuildEndContext Context passed to kubb:build:end
KubbHooks Map of every lifecycle event the driver emits
Kubb Kubb instance returned from createKubb
BuildOutput Return shape of kubb.build()

Lifecycle hook context types

Type Event Shape
KubbLifecycleStartContext kubb:lifecycle:start { version: string }
KubbConfigEndContext kubb:config:end { configs: Config[] }
KubbGenerationStartContext kubb:generation:start { config: Config }
KubbGenerationEndContext kubb:generation:end { config, storage, diagnostics?, status?, hrStart?, filesCreated? }
KubbPluginStartContext kubb:plugin:start { plugin: Plugin }
KubbPluginEndContext kubb:plugin:end { plugin, duration, success, error? }
KubbHookStartContext kubb:hook:start { id?, command, args? }
KubbHookLineContext kubb:hook:line { id, line }
KubbHookEndContext kubb:hook:end { id?, command, args?, success, error, stdout?, stderr? }
KubbFilesProcessingStartContext kubb:files:processing:start { files: FileNode[] }
KubbFilesProcessingUpdateContext kubb:files:processing:update { files: Array<KubbFileProcessingUpdate> }
KubbFileProcessingUpdate (per-item, inside files[]) { processed, total, percentage, source?, file, config }
KubbFilesProcessingEndContext kubb:files:processing:end { files: FileNode[] }
KubbInfoContext kubb:info { message: string, info?: string }
KubbErrorContext kubb:error { error: Error, meta?: Record<string, unknown> }
KubbDiagnosticContext kubb:diagnostic { diagnostic: Diagnostic }
KubbSuccessContext kubb:success { message: string, info?: string }
KubbWarnContext kubb:warn { message: string, info?: string }

Adapters & parsers

Type Purpose
Adapter Final adapter object returned from createAdapter
AdapterFactoryOptions Generic parameter pack for an adapter
AdapterSource { type: 'path' }, { type: 'data' }, or { type: 'paths' }
Parser Final parser object returned from defineParser

Resolvers

Type Purpose
Resolver Base constraint for resolvers returned from defineResolver
ResolverContext Shared context for path/file/name resolution
ResolverPathParams Parameters for Resolver.resolvePath
ResolverFileParams Parameters for Resolver.resolveFile
ResolveNameParams Parameters for customizing names by kind (file, function, type, const)
ResolveBannerContext Context for banner/footer resolution (output, config, per-file file)
ResolveBannerFile Per-file context (path, baseName, isBarrel, isAggregation)
BannerMeta InputMeta extended with per-file fields, passed to a banner/footer function
ResolveOptionsContext Context for resolveOptions (include/exclude/override)

Generators & files

Type Purpose
Generator Generator object returned from defineGenerator
GeneratorContext Context passed to schema(), operation(), and operations() methods
FileMetaBase Minimal meta shape for file nodes ({ pluginName? })

Filters

Type Purpose
PatternFilter { type; pattern } shape shared by include, exclude, and override
PatternOverride Filter plus partial option overrides
Include Filter narrowing generation to matching nodes
Exclude Filter preventing matching nodes from being generated
Override Filter pairing a match with per-node option overrides

Logging, storage, rendering

Type Purpose
Logger / UserLogger Logger interface returned from defineLogger
LoggerOptions { logLevel } passed to a logger
LoggerContext Event bus shared with the logger (AsyncEventEmitter<KubbHooks>)
Storage Shape returned by createStorage
Renderer / RendererFactory Interfaces for custom renderers passed to ctx.setRenderer()

See also