npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@mochi-css/builder

v7.0.0

Published

This package is part of the [Mochi-CSS project](https://github.com/Niikelion/mochi-css). It provides the core infrastructure for statically extracting Mochi-CSS styles from TypeScript/TSX source files and generating plain CSS at build time.

Readme

🧁 Mochi-CSS/builder

This package is part of the Mochi-CSS project. It provides the core infrastructure for statically extracting Mochi-CSS styles from TypeScript/TSX source files and generating plain CSS at build time.

Note: This package is primarily consumed by integrations such as @mochi-css/postcss. You only need it directly when building a custom integration or tooling on top of Mochi-CSS.


Installation

npm i @mochi-css/builder --save-dev

Quick Start

The builder is configured through plugins. The typical setup loads a plugin into a FullContext, then passes the collected stages and hooks to Builder:

import { Builder, RolldownBundler, VmRunner } from "@mochi-css/builder"
import { FullContext } from "@mochi-css/config"
import { writeFile } from "fs/promises"

// Load plugins into a context (see @mochi-css/plugins and @mochi-css/vanilla/config)
const ctx = new FullContext(() => {})
myPlugin.onLoad(ctx)

const builder = new Builder({
    roots: ["./src"],
    stages: [...ctx.stages.getAll()],
    bundler: new RolldownBundler(),
    runner: new VmRunner(),
    sourceTransforms: [...ctx.sourceTransforms.getAll()],
    emitHooks: [...ctx.emitHooks.getAll()],
    emitDir: "./dist/mochi",
    cleanup: () => ctx.cleanup.runAll(),
})

const { global, files } = await builder.collectMochiCss()

if (global) await writeFile("dist/global.css", global)
if (files) {
    for (const [source, css] of Object.entries(files)) {
        await writeFile(source.replace(/\.(ts|tsx)$/, ".css"), css)
    }
}

How It Works

The builder performs multiphase processing:

  1. Preprocessing — Runs the optional filePreProcess callback on every source file before parsing.
  2. Analysis — Scans source files, builds a dependency graph, and identifies all style function calls and the variables they depend on.
  3. sourceTransforms — Hooks that run after analysis on the canonical AST index. Mutations persist and are visible to postEvalTransforms.
  4. preEvalTransforms — Hooks that run on a deep copy of the ASTs, used only for bundling and evaluation. Mutations do NOT persist.
  5. Extraction — Generates minimal executable code from relevant style expressions, bundles it, and executes it in an isolated VM context.
  6. postEvalTransforms — Hooks that run after execution. The evaluator is populated — use context.evaluator.getTrackedValue() to read runtime values.
  7. emitHooks — Hooks that run after postEvalTransforms. Call context.emitChunk(path, content) to produce output files written to emitDir.

API

Builder

The main orchestration class.

class Builder {
    constructor(options: BuilderOptions)

    // Analyze a pre-parsed set of modules; returns chunks keyed by path
    collectStylesFromModules(modules: Module[]): Promise<Map<string, Set<string>>>

    // High-level: discover files, extract styles, and generate CSS
    collectMochiCss(options?: CollectCssOptions): Promise<{
        global?: string
        files?: Record<string, string>
        sourcemods?: Record<string, string>
    }>
}

BuilderOptions

| Option | Type | Description | | -------------------- | -------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- | | roots | RootEntry[] | Directories (or named root entries) scanned recursively for source files. | | stages | StageDefinition[] | Analysis pipeline stages. Populated by calling plugin.onLoad(ctx) and passing ctx.stages.getAll(). | | bundler | Bundler | Bundler implementation. Use RolldownBundler. | | runner | Runner | Code runner implementation. Use VmRunner. | | splitCss | boolean | When true, CSS is split per source file instead of merged. Default: false. | | onDiagnostic | function | Callback for structured warnings and non-fatal errors. | | filePreProcess | function | Optional callback invoked on every source file before parsing. Receives { content, filePath } and returns the (possibly transformed) source string. | | sourceTransforms | AstPostProcessor[] | Hooks that run after analysis. May mutate AST nodes. Mutations persist in the canonical index. | | preEvalTransforms | AstPostProcessor[] | Hooks that run on a deep copy of the ASTs before evaluation. Mutations do NOT persist in the canonical index. | | postEvalTransforms | AstPostProcessor[] | Hooks that run after execution. The evaluator is populated — use context.evaluator.getTrackedValue() to read runtime values. | | emitHooks | EmitHook[] | Hooks that run after postEvalTransforms. Call context.emitChunk(path, content) to emit files. | | emitDir | string | Base directory for files produced via context.emitChunk(). | | cleanup | function | Called once at the end of the pipeline. Use to release caches built during transforms. |

CSS output

When splitCss is false (default), all generated CSS is merged into a single global string.

When splitCss is true, the files map contains per-source-file CSS keyed by the source file path, and any truly global styles (from globalCss) are in global.


AnalysisContext

Passed to sourceTransforms, preEvalTransforms, postEvalTransforms, and emitHooks.

type AnalysisContext = {
    onDiagnostic?: OnDiagnostic
    evaluator: Evaluator
    // Emit a chunk of content to a file in emitDir. Multiple chunks for the same path are
    // deduplicated by content and joined with "\n\n".
    emitChunk(path: string, content: string): void
    // Mark an AST expression for inclusion in the eval bundle for a given file.
    // The expression's identifier dependencies are traced and its value is captured at runtime.
    // Wrap with evaluator.valueWithTracking() first to read back the runtime value later.
    markForEval(filePath: string, expression: SWC.Expression): void
}

EmitHook

A hook that runs after code execution. Call context.emitChunk() to emit files into emitDir. Files emitted on a previous run that are absent on the next run are automatically deleted.

type EmitHook = (runner: StageRunner, context: AnalysisContext) => void | Promise<void>

RolldownBundler / Bundler

RolldownBundler uses Rolldown to bundle the extracted minimal source code into a CommonJS module that can be executed.

interface Bundler {
    bundle(rootFilePath: string, files: FileLookup): Promise<string>
}

You can provide an alternative Bundler implementation if your environment requires a different bundler.


VmRunner / Runner

VmRunner executes bundled code in an isolated Node.js vm.Context, injecting extractors as context variables.

interface Runner {
    execute(source: string, context: Record<string, unknown>): Promise<void>
}

You can provide an alternative Runner implementation if your environment requires a different js runner.


Utilities

parseSource / parseFile

Parse TypeScript/TSX source code into a Module AST.

async function parseSource(source: string, filePath: string): Promise<Module>
async function parseFile(filePath: string): Promise<Module>

Useful when you want to supply pre-parsed modules to collectStylesFromModules.

findAllFiles

Recursively discover all .ts and .tsx files in a directory.

async function findAllFiles(dir: string): Promise<string[]>

Diagnostics & Errors

Provide an onDiagnostic callback to receive structured warnings and non-fatal errors.

const builder = new Builder({
    // ...
    onDiagnostic: (diagnostic) => {
        console.warn(`[${diagnostic.code}] ${diagnostic.message}`)
        if (diagnostic.file) console.warn(`  at ${diagnostic.file}:${diagnostic.line}`)
    },
})

Fatal errors are thrown as MochiError instances:

class MochiError extends Error {
    readonly code: string // e.g. "MOCHI_BUNDLE"
    readonly file?: string
}

| Error Code | Cause | | ------------------------------- | ----------------------------------------------- | | MOCHI_FILE_READ | Cannot read a source file | | MOCHI_PARSE | TypeScript parsing failed | | MOCHI_BUNDLE | Bundling the extracted code failed | | MOCHI_EXEC | Execution of bundled code failed | | MOCHI_UNRESOLVED_IMPORT | A local import cannot be resolved | | MOCHI_INVALID_STYLE_ARG | A css()/styled() argument is not an object | | MOCHI_INVALID_GLOBAL_CSS_ARG | A globalCss() argument is not an object | | MOCHI_INVALID_KEYFRAMES_ARG | A keyframes() argument is not an object | | MOCHI_STYLE_GENERATION | CSS generation threw an error | | MOCHI_INVALID_EXTRACTOR_USAGE | Derived extractor was not properly destructured |


Writing Plugins and Custom Extractors

Plugin authoring — StyleExtractor, StyleGenerator, createExtractorsPlugin, stage definitions, and utilities like propagateUsagesFromExpr — is covered in the @mochi-css/plugins README.