JSPM

@kubb/fabric-core

0.7.3
  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 39093
  • Score
    100M100P100Q156067F
  • License MIT

Core functionality for Kubb's plugin-based code generation system, providing the foundation for transforming OpenAPI specifications.

Package Exports

  • @kubb/fabric-core
  • @kubb/fabric-core/package.json
  • @kubb/fabric-core/parsers
  • @kubb/fabric-core/parsers/typescript
  • @kubb/fabric-core/plugins
  • @kubb/fabric-core/types

Readme


Kubb Fabric is a language-agnostic toolkit for generating code and files using JSX and TypeScript. It offers a lightweight layer for file generation while orchestrating the overall process of creating and managing files.

[!WARNING] Fabric is under active development. Until a stable 1.0 release, minor versions may occasionally include breaking changes. Please check release notes and PR titles for breaking changes.

Features

  • 🎨 Declarative file generation β€” Create files effortlessly using JSX or JavaScript syntax.
  • πŸ“¦ Cross-runtime support β€” Works seamlessly with Node.js and Bun.
  • 🧩 Built-in debugging utilities β€” Simplify development and inspect generation flows with ease.
  • ⚑ Fast and lightweight β€” Minimal overhead, maximum performance.

Write a TypeScript file

Below is a minimal example showing how createFabric works together with plugins and parsers via fabric.use.

import { createFabric } from '@kubb/fabric-core'
import { fsPlugin } from '@kubb/fabric-core/plugins'
import { typescriptParser } from '@kubb/fabric-core/parsers'

const fabric = createFabric()

fabric.use(fsPlugin, {
  dryRun: false,
  onBeforeWrite: (path, data) => {
    console.log('About to write:', path)
  },
  clean: { path: './generated' },
})

fabric.use(typescriptParser)

await fabric.addFile({
  baseName: 'index.ts',
  path: './generated/index.ts',
  sources: [
    { value: 'export const x = 1', isExportable: true },
  ],
})

await fabric.write()

Creates a file generated/index.ts with the following content:

export const x = 1

API Reference

Core

createFabric(options?): Fabric

Returns a Fabric instance with:

  • fabric.use(pluginOrParser, ...options) => Fabric β€” register plugins and parsers.
  • fabric.addFile(...files) β€” queue in-memory files to generate.
  • fabric.files β€” getter with all queued files.
  • fabric.context β€” internal context holding events, options, FileManager, installed plugins/parsers.

Events (emitted by the core during processing)

Fabric emits events throughout its lifecycle that plugins and custom code can listen to. These events provide hooks for monitoring progress, transforming files, and performing custom operations.

Lifecycle Events

  • lifecycle:start β€” Emitted when Fabric begins execution
  • lifecycle:end β€” Emitted when Fabric completes execution
  • lifecycle:render { fabric } β€” Emitted when rendering starts (with reactPlugin)

File Management Events

  • files:added { files } β€” Emitted when files are added to the FileManager cache
  • file:resolve:path { file } β€” Emitted during file path resolution (allows modification)
  • file:resolve:name { file } β€” Emitted during file name resolution (allows modification)

File Writing Events

  • files:writing:start { files } β€” Emitted before writing files to disk
  • files:writing:end { files } β€” Emitted after files are written to disk

File Processing Events

  • files:processing:start { files } β€” Emitted before processing begins
  • file:processing:start { file, index, total } β€” Emitted when each file starts processing
  • file:processing:end { file, index, total } β€” Emitted when each file finishes processing
  • file:processing:update { file, source, processed, percentage, total } β€” Emitted with progress updates
  • files:processing:end { files } β€” Emitted when all processing completes

Listening to Events

You can listen to events using the Fabric context:

const fabric = createFabric()

fabric.context.on('lifecycle:start', async () => {
  console.log('Starting Fabric...')
})

fabric.context.on('file:processing:update', async ({ processed, total, percentage }) => {
  console.log(`Progress: ${percentage.toFixed(1)}% (${processed}/${total})`)
})

fabric.context.on('lifecycle:end', async () => {
  console.log('Fabric completed!')
})

Plugins

fsPlugin

Writes files to disk on file:processing:update, supports dry runs and cleaning an output folder before writing.

import { fsPlugin } from '@kubb/fabric-core/plugins'
Option Type Default Description
dryRun boolean false If true, do not write files to disk.
onBeforeWrite (path: string, data: string | undefined) => void | Promise<void> β€” Called right before each file write on file:processing:update.
clean { path: string } β€” If provided, removes the directory at path before writing any files.

Injected fabric.write options (via fsPlugin):

Option Type Default Description
extension Record<Extname, Extname | ''> β€” Maps input file extensions to output extensions. When set, the matching parser (by extNames) is used.

barrelPlugin

Generates index.ts barrel files per folder when files:writing:start is triggered. writeEntry creates a single entry barrel at root.

import { barrelPlugin } from '@kubb/fabric-core/plugins'
Option Type Default Description
root string β€” Root directory to generate barrel files for.
mode 'all' | 'named' | 'propagate' | false β€” Controls how exports are generated: all exports, only named exports, propagate (skip barrels), or disabled.
dryRun boolean false If true, computes barrels but skips writing.

Injected fabric.writeEntry parameters (via barrelPlugin):

Param Type Description
root string Root directory where the entry index.ts should be created.
mode 'all' | 'named' | 'propagate' | false Controls which export style to use for the entry barrel.

loggerPlugin

Streams Fabric lifecycle activity as colourful consola logs, optional progress bars, and websocket messages that you can consume from custom tooling.

import { loggerPlugin } from '@kubb/fabric-core/plugins'
Option Type Default Description
level import('consola').LogLevel β€” Optional explicit log level passed to createConsola.
progress boolean true Enable/disable the integrated CLI progress bar.
websocket boolean | { host?: string; port?: number } true Toggle or configure the websocket server that broadcasts Fabric events for future GUIs.

By default the plugin displays a progress bar, starts a websocket server on an ephemeral port, and announces the URL. Every key lifecycle hook (start, process:*, file:*, write:*, end) is logged with a Fabric tag, animated in the progress bar, and broadcast to connected clientsβ€”perfect for building dashboards on top of Fabric.

graphPlugin

Shows a graph of all files

import { graphPlugin } from '@kubb/fabric-core/plugins'
Option Type Default Description
root string Root directory where to start searching from.
open boolean false Open a webpage with the generated graph

reactPlugin

Enables rendering React components to the terminal or to a string. Useful for CLI UIs and templating.

import { reactPlugin } from '@kubb/react-fabric/plugins'
Option Type Default Description
stdout NodeJS.WriteStream β€” Optional output stream used to print the rendered content while the app is running. If set, the output is written progressively.
stdin NodeJS.ReadStream β€” Optional input stream for interactive components.
stderr NodeJS.WriteStream β€” Optional error output stream.
debug boolean β€” When true, logs render/unmount information to the console to aid debugging.

Injected methods (via reactPlugin):

Method Signature Description
render (App: React.ElementType) => Promise<void> | void Render a React component tree to the terminal and emit the core start event.
renderToString (App: React.ElementType) => Promise<string> | string Render a React component tree and return the final output as a string (without writing to stdout).
waitUntilExit () => Promise<void> Wait until the rendered app exits, resolves when unmounted and emits the core end event.

definePlugin

Factory to declare a plugin that can be registered via fabric.use.

Field Required Description
name Yes String identifier of your plugin.
install(fabric, options) Yes Called when the plugin is registered. You can subscribe to core events and perform side effects here.
inject?(fabric, options) No Return synchronously the runtime methods/properties to merge into fabric (e.g. write, render). This must not be async.

Example:

import { createFabric } from '@kubb/fabric-core'
import { definePlugin } from '@kubb/fabric-core/plugins'

const helloPlugin = definePlugin<{ name?: string }, { sayHello: (msg?: string) => void }>({
  name: 'helloPlugin',
  install(fabric, options) {
    fabric.context.events.on('lifecycle:start', () => {
      console.log('Fabric started')
    })
  },
  inject(fabric, options) {
    return {
      sayHello(msg = options?.name ?? 'world') {
        console.log(`Hello ${msg}!`)
      },
    }
  },
})

const fabric = createFabric()
await fabric.use(helloPlugin, { name: 'Fabric' })
fabric.sayHello() // -> Hello Fabric!

Parsers

typescriptParser

Prints TS/JS imports/exports and sources, supports extname mapping for generated import/export paths.

import { typescriptParser } from '@kubb/fabric-core/parsers'
Option Type Default Description
file KubbFile.File - File that will be used to be parsed.
extname string '.ts' Extension to use when emitting import/export paths (e.g., rewrite ./file to ./file.ts).

tsxParser

Delegates to typescriptParser with TSX printing settings.

import { tsxParser } from '@kubb/fabric-core/parsers'
Option Type Default Description
file KubbFile.File - File that will be used to be parsed.
extname string '.tsx' Extension to use when emitting import/export paths for TSX/JSX files.

defaultParser

Fallback parser used when no extension mapping is provided to fabric.write.

import { defaultParser } @kubb/fabric-core/parsers`
Option Type Default Description
file KubbFile.File - File that will be used to be parsed.

defineParser

Factory to declare a parser that can be registered via fabric.use and selected by extNames during fabirc.write.

Field Required Description
name Yes String identifier of your parser.
extNames Yes List of file extensions this parser can handle (e.g. ['.ts']). Use undefined for the default parser fallback.
install(fabric, options) No Optional setup when the parser is registered (subscribe to events, set state, etc.).
parse(file, { extname }) Yes Must return the final string that will be written for the given file.

Example:

import { createFabric } from '@kubb/fabric-core'
import { defineParser } from '@kubb/fabric-core/parsers'

const vueParser = defineParser<{ banner?: string }>({
  name: 'vueParser',
  extNames: ['.vue'],
  async install(fabric, options) {
    // Optional setup
  },
  async parse(file, { extname }) {
    const banner = file.options?.banner ?? ''
    const sources = file.sources.map(s => s.value).join('\n')
    return `${banner}\n${sources}`
  },
})

const fabric = createFabric()
fabric.use(vueParser)
fabric.use(fsPlugin); // make it possible to write to the filesystem

fabric.write({ extension: { '.vue': '.ts' } })

[!NOTE]

  • fabric.use accepts both plugins and parsers. The fsPlugin handles I/O and adds fabric.write. Parsers decide how files are converted to strings for specific extensions.
  • When extension mapping is provided to fabric.write, Fabric picks a parser whose extNames include the file’s extension. Otherwise, the default parser is used.