susee
v3.0.0
Published
A high-performance TypeScript library bundler
Readme
Use susee v2.3.0 or above. In v2.3.0, the core bundler was ported from TypeScript to Rust (powered by
oxc) with assistance from the glm-5.2:cloud model served via the Ollama platform, fixing multiple bugs present in earlier versions. Older versions are no longer recommended.See the bug information since v2.3.0.
Overview
susee is a TypeScript bundler powered by oxc, specialized for library packages. Unlike general-purpose bundlers, susee focuses on consolidating a package's local TypeScript dependency tree into consolidated source units and compiling them into dual-format artifacts (ESM and CommonJS).
Key Features
- TypeScript-first build flow — built around library development, not application bundling. Preserves a package-oriented workflow with declaration output and clean library artifacts.
- Dual output support — produces both ESM and CommonJS from the same entry definition, so packages work with modern
importand legacyrequireecosystems. - Duplicate declaration validation — when source consolidation produces conflicting top-level declarations, the build fails with file and location output instead of silently renaming.
- Package metadata update — can update
package.jsonexports,main,module, andtypesfields after build output is generated. - Built-in minification — runs the
oxc-minifyminifier over emitted JavaScript when enabled. - CLI and programmatic API — use the CLI for local development/CI, or call the build API for custom scripting.
- JSX support — detects JSX in bundled output and validates the JSX runtime (React or a configured
jsxImportSource) before compiling.
Install
npm i -D suseeVerify the installation:
npx susee --versionScaffold a new project
Generate a complete library project pre-configured with susee using create-susee:
npm create susee@latest
# yarn create susee
# pnpm create susee
# bun create suseeThe scaffolder generates src/index.ts, a ready-to-use susee.config.ts, tsconfig.json, and a package.json with build/check scripts. It prompts you to pick a linter (Biome or Oxc — oxlint + oxfmt), optionally generates an AGENTS.md with project context for AI coding agents, auto-detects your package manager, and installs the latest published versions of all dependencies.
Quick Start
1. Create a config file
Generate a starter susee.config.{ts,js,mjs} in your project root:
npx susee initThe interactive prompt asks whether your project is TypeScript. For TypeScript projects, it writes susee.config.ts; for JavaScript projects, it writes susee.config.js (ESM) or susee.config.mjs (CommonJS) based on your package.json#type.
Starting from scratch?
create-suseescaffolds the whole project — config, entry file, tsconfig, and scripts — in one command.
2. Define your entries
// susee.config.ts
import type { SuSeeConfig } from "susee";
const config: SuSeeConfig = {
entryPoints: [
{
entry: "src/index.ts", // required — entry file path
exportPath: ".", // required — "." for main export, or "./foo"
format: ["esm"], // optional, default ["esm"]
tsconfigFilePath: undefined, // optional, custom tsconfig
checks: { // optional, all default false
checkAnonymous: false,
checkDefaultExports: false,
checkNpmInstalled: false,
},
minify: false, // optional: true | { options: MinifyOptions }
},
],
outDir: "dist", // optional, default "dist"
allowUpdatePackageJson: false, // optional, default false
};
export default config;3. Build
npx susee buildSusee reads your config, bundles each entry point, compiles to ESM and/or CommonJS, and writes the output to dist by default.
CLI
susee build Build using susee.config.{ts,js,mjs}
susee init Generate susee.config.{ts,js,mjs}
susee check Run lint checks on a dependency tree without bundling
susee bundle <entry> [options] Bundle a single entry file to disk without compiling
susee --version / -v Print version
susee --help / -h Show help
susee build <entry> [options] Build from a single entry fileBuild Flags
| Flag | Type | Default | Description |
|------|------|---------|-------------|
| --entry <path> | string | — | Entry file (optional if given positionally) |
| --outdir <path> | string | dist | Output directory |
| --format | cjs\|commonjs\|esm\|both | esm | Output module format (both = CJS + ESM) |
| --tsconfig <path> | string | undefined | Custom tsconfig path |
| --allow-update[=true\|false] | boolean | false | Allow package.json updates |
| --minify[=true\|false] | boolean | false | Minify output JS |
| --check[=true\|false] | boolean | false | Run bundler lint checks |
Bundle Flags
The susee bundle command writes the bundled source (before TypeScript compilation) to disk. It supports --entry, --outdir, and --check[=true|false].
Flags accept both --flag=value and --flag value syntax.
Examples
npx susee build src/index.ts --outdir dist
npx susee build src/index.ts --format commonjs
npx susee build src/index.ts --format both # emit CJS + ESM
npx susee build --entry src/index.ts --format esm --tsconfig tsconfig.build.json
npx susee build src/index.ts --minify
npx susee build src/index.ts --check # run lint checks during build
npx susee bundle src/index.ts --outdir bundled # write bundled source only
npx susee check # lint the dependency tree from configProgrammatic API
build()
import { build, type SuSeeConfig } from "susee";
const config: SuSeeConfig = {
entryPoints: [
{ entry: "src/index.ts", exportPath: "." },
],
outDir: "dist",
allowUpdatePackageJson: true,
};
await build(config);build() resolves options from the argument first, then from a root config file. If neither is available it logs an error and exits with code 1.
suseeBundle()
Bundle a single entry point into a consolidated source string without compiling or writing to disk:
import { suseeBundle, type CheckOptions } from "susee";
const code: string = suseeBundle("src/index.ts");
// with lint checks enabled
const checks: CheckOptions = {
checkAnonymous: true,
checkDefaultExports: true,
checkNpmInstalled: true,
};
const checked = suseeBundle("src/index.ts", checks);suseeBundle() runs the oxc-powered bundler over the entry's local dependency tree and returns the bundled source. When CheckOptions are provided the bundler runs diagnostics (anonymous declarations, default exports, npm-installed deps) before returning.
How It Works
flowchart TD
A[CLI / Programmatic API] --> B["build()"]
B --> C{options provided?}
C -->|yes| D[generateBuildOptions]
C -->|no| E[finalSuseeConfig]
E -->|no config| F[Error + exit 1]
E -->|found| D
D --> G[Compiler]
G --> H[For each entry point]
H --> I["bundler() — suseeBundler (oxc)"]
I --> J[Bundled source string]
J --> K{format}
K -->|commonjs| L["_commonjs()"]
K -->|esm| M["_esm()"]
L --> N["suseeCompiler — ts6 in-memory host"]
M --> N
N --> O["getCompilerOptions — tsconfig → per-format"]
O --> P["ts6.createProgram + emit"]
P --> Q{minify?}
Q -->|yes| R[oxcMinify]
Q -->|no| S["Write .cjs/.mjs + .d.* + .map"]
R --> S
S --> T{update package?}
T -->|yes| U["files.writePackageJson"]The pipeline bundles each entry point's local dependency tree into a single source string, compiles it in-memory with the TypeScript compiler (@suseejs/ts6), optionally minifies with oxc-minify, and writes dual-format artifacts with declaration and source-map files.
Source Architecture
src/
├── index.ts # Public API — re-exports build, suseeBundle, SuSeeConfig, CheckOptions
├── build.ts # Build orchestrator — resolves config, runs Compiler
├── bundler.ts # Wrapper around @suseejs/susee_bundler (oxc) + CLI bundle writer
├── cli/
│ ├── index.ts # CLI entrypoint & command dispatch (build/init/check/bundle)
│ ├── parse_args.ts # Parses CLI flags into SuSeeConfig / bundle opts
│ ├── init.ts # `susee init` — scaffolds config file
│ ├── lint.ts # `susee check` — runs suseeLint over the dependency tree
│ └── print_help.ts # `susee --help` output
├── compiler/
│ ├── index.ts # Compiler class — bundles + emits CJS/ESM + types
│ ├── suseeCompiler.ts# In-memory TypeScript compilation host
│ └── tsoptions.ts # Resolves tsconfig.json into per-format options
├── config/
│ └── index.ts # Config types, validation, and normalization
└── helpers/
├── files.ts # File system namespace + package.json writer
└── minify.ts # oxc-minify wrapperSee src/README.md for detailed module documentation.
Configuration Reference
SuSeeConfig
| Field | Type | Required | Default | Description |
|-------|------|----------|---------|-------------|
| entryPoints | EntryPoint[] | yes | — | Array of entry point definitions |
| outDir | string | no | dist | Output directory |
| allowUpdatePackageJson | boolean | no | false | Allow susee to update package.json |
EntryPoint
| Field | Type | Required | Default | Description |
|-------|------|----------|---------|-------------|
| entry | string | yes | — | Entry file path |
| exportPath | "." \| "./${string}" | yes | — | Export path for this entry |
| format | ("commonjs" \| "esm")[] | no | ["esm"] | Output module formats |
| tsconfigFilePath | string | no | undefined | Custom tsconfig path |
| checks | CheckOptions | no | all false | Bundler lint checks |
| minify | boolean \| { options: MinifyOptions } | no | false | Minify output |
CheckOptions
| Field | Type | Default | Description |
|-------|------|---------|-------------|
| checkAnonymous | boolean | false | Check for anonymous declarations |
| checkDefaultExports | boolean | false | Check default exports |
| checkNpmInstalled | boolean | false | Check that npm deps are installed |
TSConfig Resolution Priority
For each entry point, compiler options resolve in this order:
- Custom
tsconfigFilePathon the entry point tsconfig.jsonat the project root- Susee defaults (
module: ES2020for ESM,module: CommonJSfor CJS,target: Latest)
Agent Skills
Susee ships agent skills that give AI coding agents procedural knowledge about building with and contributing to susee. Install them with the skills CLI:
npx skills add phothinmg/susee| Skill | Purpose |
| ----- | ------- |
| susee-build | Configure and run builds — config files, CLI commands, programmatic API, dual ESM/CJS output |
| susee-troubleshooting | Diagnose failing builds — duplicate declarations, entry/exportPath validation, invalid flags, tsconfig issues |
| susee-contribution | Work on the susee codebase — architecture map, local checks, commit conventions, PR checklist |
Development
npm run build # compile src/ via oxnode build.ts
npm run lint # oxlint
npm run fmt # oxfmtKey Dependencies
@suseejs/susee_bundler— oxc-powered bundling engine@suseejs/ts6— TypeScript compiler fork for type-checking and declaration emitoxc-minify— JavaScript minification
