Skip to content

🧰 Fabric is a language-agnostic toolkit for generating code and files using JSX and TypeScript.

License

Notifications You must be signed in to change notification settings

kubb-labs/fabric

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

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.

defineFabric(instance?): () => Fabric

Factory to create your own createFabric with an optional bootstrap instance(fabric) called on creation.

Events (emitted by the core during processing)

  • start
  • end
  • render { fabric }
  • file:add { files }
  • write:start { files }
  • write:end { files }
  • file:start { file, index, total }
  • file:end { file, index, total }
  • process:start { files }
  • process:progress { file, source, processed, percentage, total }
  • process:end { files }

Plugins

fsPlugin

Writes files to disk on process:progress, 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 process:progress.
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 at process:end. 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.

progressPlugin

Shows a CLI progress bar by listening to core events.

import { progressPlugin } from '@kubb/fabric-core/plugins'
Option Type Default Description
— — — This plugin has no options, it displays a CLI progress bar by listening to core events.

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.

createPlugin

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 { createPlugin } from '@kubb/fabric-core/plugins'

const helloPlugin = createPlugin<{ name?: string }, { sayHello: (msg?: string) => void }>({
  name: 'helloPlugin',
  install(fabric, options) {
    fabric.context.events.on('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.

createParser

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 { createParser } from '@kubb/fabric-core/parsers'

const vueParser = createParser<{ 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.

Supporting Kubb

Kubb uses an MIT-licensed open source project with its ongoing development made possible entirely by the support of Sponsors. If you would like to become a sponsor, please consider:

My sponsors

Contributors Contributors

Star History

Star History Chart

About

🧰 Fabric is a language-agnostic toolkit for generating code and files using JSX and TypeScript.

Topics

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Sponsor this project

 

Packages

No packages published

Contributors 3

  •  
  •  
  •