Skip to content
Kit

Parsers

defineExtension with kind parser defines a parser from one object with meta and a build function. A parser converts a generated file AST into the source string written to disk. Covers the Parser interface and adding your own.

A parser turns a FileNode into source code.

For TypeScript and JavaScript output use the built-in @kubb/parser-ts. It is added by default when you import defineConfig from the kubb package. Build a custom parser only when you target a different language, such as Python, Kotlin, or Rust.

defineExtension

defineExtension with kind: 'parser' takes a definition object and returns a factory. build receives the caller's options, or an empty object when omitted, and returns the parser methods. Declare extensions with extNames:

parserText.ts
import { defineExtension } from 'kubb/kit'

export const parserText = defineExtension({
  kind: 'parser',
  meta: { name: 'text', version: '1.0.0' },
  build() {
    return {
      extNames: ['.txt'],
      parse(file) {
        return file.sources
          .flatMap((source) => source.nodes ?? [])
          .map((node) => (node.kind === 'Text' ? node.value : ''))
          .join('\n')
      },
      print(...nodes) {
        return nodes.map(String).join('\n')
      },
    }
  },
})

The parser's name comes from meta.name. Kubb checks meta.compatibility before the build, the same way it does for plugins. See Extensions.

defineParser (deprecated)

defineParser is deprecated. Use defineExtension with kind: 'parser' instead.

defineParser takes the same definition object as defineExtension, without kind. To move over, rename the call and add kind: 'parser'. See Extensions.

Wire it into your config:

kubb.config.ts
import { defineConfig } from 'kubb/config'
import { parserTs, parserTsx } from '@kubb/parser-ts'
import { parserText } from './parserText.ts'

export default defineConfig({
  input: './petStore.yaml',
  output: { path: './src/gen' },
  parsers: [parserTs(), parserTsx(), parserText()],
})

Parser anatomy

Every parser the factory returns matches the Parser interface from kubb/kit. build returns every field except name and meta:

PropertyTypeRequiredWhen calledPurpose
namestringYesUnique parser identifier, filled from meta.name. Use the output language or format, such as 'typescript'.
extNamesArray<FileNode['extname']> | undefinedYesFile extensions this parser handles. Set to undefined to register a catch-all fallback.
parse(file: FileNode) => stringYesAfter all plugins runSerializes the file's sources into the final output string. Must return synchronously.
print(...nodes: TNode[]) => stringYesBy plugins, while they generate filesRenders compiler AST nodes to source text. The node type is parser-specific, for example ts.Node for parserTs.
copy(file: FileNode, source: string) => UserFileNodeNoFor each copy fileDescribes a copied template's raw content as nodes, for example its imports as ImportNodes, in the same shape injectFile takes. Kubb prints the result with parse. Omit it to write copied files verbatim.
If two parsers register the same extension, the last one in the parsers array wins. Order matters.

When no parser matches a file's extension, Kubb writes the file's source strings joined together.

Parser naming convention

Parsers share the layout of plugins and adapters:

SurfacePatternExample
npm package@<scope>/parser-<name> or kubb-parser-<name>@kubb/parser-ts
Parser runtime nameThe output language or format (lowercase)'typescript', 'markdown'
Factory exportparser<Name> (camelCase)parserTs, parserMd

Call the parser factory when registering it in parsers.

Parsers compose by extension. parserTs (.ts, .js) and parserTsx (.tsx, .jsx) ship in the same @kubb/parser-ts package and register side by side.