susee
v1.6.0
Published
TypeScript-first bundler for library packages
Readme
About
A TypeScript-first bundler designed specifically for library packages that delivers fast builds, type safety, and modern JavaScript output with minimal configuration.
[!NOTE]
- Susee currently depends on the
TypeScript 6programmatic API.- Starting with
v1.6.0, Susee uses@suseejs/ts6, a focused fork of@typescript/typescript6that exposes thets6runtime Susee needs.- This keeps Susee's TypeScript API dependency isolated, while allowing your project to install and use
TypeScript 7alongside it withouttscnaming conflicts.- For the best compatibility with this setup, use
Susee v1.6.0or newer.
Key Features
✅ TypeScript-first - Built with TypeScript for maximum type safety
✅ Dual Output - Generate both ESM and CommonJS formats automatically
✅ Duplicate Declaration Detection - Fails fast when bundled files contain conflicting top-level declarations
✅ Fast Builds - Optimized for library packages with minimal overhead
✅ Package.json Management - Automatic updates to package.json fields based on the build results
✅ Plugin System - Extend functionality with custom plugins
✅ CLI & Programmatic API - Use as a CLI tool or integrate directly
✅ Build Profiling - Print bundler and compiler phase timings with --profile
Installation and Quick Start
Installation Methods
Local Development Dependency (Recommended)
Install susee as a development dependency in your project:
npm i -D suseeThis method is recommended for library projects as it ensures the bundler version is locked to the project and available for CI/CD pipelines.
Global Installation
For system-wide availability of the susee CLI:
npm install -g suseeGlobal installation enables running susee directly from any directory without the npx prefix.
Installation Verification
After installation, verify the package is available by checking the version command:
npx susee --versionQuick Start
Using config file
The easiest way to start is using the built-in initialization command which generates a configuration template at your project root.This command creates a susee.config.ts, susee.config.js, or susee.config.mjs file.
npx susee initBuild your project by running:
npx suseeUsing Programmatic API
You can trigger the build process within a TypeScript/JavaScript script using the build() function.
import { build } from "susee";
await build({
entryPoints: [
{
entry: "src/index.ts",
exportPath: ".",
format: ["esm", "commonjs"],
},
],
outDir: "dist",
allowUpdatePackageJson: true,
});Using CLI (Direct Build)
Build a single entry directly without a config file.This method uses default values for options not explicitly provided.
npx susee build src/index.ts --outdir dist --format esmContributor Setup (Repository)
When contributing to this repository, use npm to keep installs aligned with package-lock.json and npm-based scripts.
npm install
npm run hooks:installThis installs project dependencies and configures local git hooks for commit workflow checks.
Security
Please report vulnerabilities privately and follow the disclosure process in SECURITY.md.
Do not open public issues for security reports.
API Quick Reference
build(options?): Build from the provided options or from a discoveredsusee.config.ts/js/mjsfile. If neither exists, Susee exits with code1.suseeBundler(entry): Bundle a single entry and return the merged source string. This export does not expose plugin or warning options.suseeCliBuild(): Run the CLI dispatcher programmatically usingprocess.argv.susee: Build from the root config file and clear the configuredoutDirbefore compiling.susee init: Generate a config template in the project root after prompting whether the project uses TypeScript.susee build <entry> [options]: Build a single entry directly from CLI arguments. Defaults:--outdir dist,--format esm,--warning false,--allow-update false,--profile false.entryPoints[].format: Output module format list. Default:["esm"].entryPoints[].tsconfigFilePath: Custom tsconfig path. Default:undefined.entryPoints[].plugins: Dependency, pre-process, and post-process plugins. Default:[].entryPoints[].warning: Treat dependency graph warnings as fatal. Default:false.outDir: Root output directory. Default:"dist".allowUpdatePackageJson: Update package fields based on generated output. Default:false.
CLI Usage
Susee CLI.
Usage:
susee Build using susee.config.{ts,js,mjs}
susee init Generate susee.config.{ts,js,mjs}
susee --version | -v Check susee version
susee --help | -h Show this message
susee build <entry> [options] Build from a single entry fileCLI Build Options
--entry <path> Entry file (optional if provided as positional <entry>)
--outdir <path> Output directory (default: dist)
--format <cjs|commonjs|esm> Output format (default: esm)
--tsconfig <path> Custom tsconfig path
--allow-update[=true|false] Allow package.json updates (default: false)
--warning[=true|false] Treat dependency graph warnings as fatal (default: false)
--profile[=true|false] Print bundler/compiler phase timings (default: false)CLI Examples
npx susee build src/index.ts --outdir dist
npx susee build src/index.ts --format commonjs
npx susee build --entry src/index.ts --format esm
npx susee build src/index.ts --profileNotes:
susee buildaccepts either a positional<entry>or--entry <path>.--profileis also accepted on plainsuseeconfig-driven builds.- The CLI clears the target
outDirbefore writing new output.
Config File
Supported config filenames at project root:
susee.config.tssusee.config.jssusee.config.mjs
SuSeeConfig shape
type OutputFormat = ("commonjs" | "esm")[];
interface EntryPoint {
entry: string;
exportPath: "." | `./${string}`;
format?: OutputFormat; // default: ["esm"]
tsconfigFilePath?: string | undefined; // default: undefined
plugins?: unknown[]; // default: []
warning?: boolean; // default: false
}
interface SuSeeConfig {
entryPoints: EntryPoint[];
outDir?: string; // default: "dist"
allowUpdatePackageJson?: boolean; // default: false
}Example susee.config.ts
import type { SuSeeConfig } from "susee";
const config: SuSeeConfig = {
entryPoints: [
{
entry: "src/index.ts",
exportPath: ".",
format: ["esm", "commonjs"],
},
],
outDir: "dist",
allowUpdatePackageJson: false,
};
export default config;Programmatic API
build(options?)
Signature:
function build(options?: SuSeeConfig): Promise<void>;Parameters:
options(optional): Build options passed directly from code.
Returns:
Promise<void>that resolves when compilation completes.
Runtime behavior:
- If
optionsis provided, Susee builds from that object. - If
optionsis omitted, Susee tries to load config from project root. - If both are missing, Susee logs an error and exits with code
1. - Before compiling, Susee clears the configured
outDir.
import { build, type SuSeeConfig } from "susee";
const options: SuSeeConfig = {
entryPoints: [
{
entry: "src/index.ts",
exportPath: ".",
format: ["esm", "commonjs"],
},
],
};
await build(options);Output Notes
For an entry like src/index.ts with both formats enabled, output includes:
- ESM:
dist/index.mjs - CommonJS:
dist/index.cjs - Sourcemaps:
.mjs.mapand.cjs.map
Declaration files are emitted by the compiler when available.
Build Output Matrix
| Input | Output Directory Rule | ESM Files | CommonJS Files |
| -------------------------------------------- | --------------------- | ------------------------------------------- | ------------------------------------------- |
| entry: "src/index.ts", exportPath: "." | <outDir> | index.mjs, index.mjs.map, index.d.mts | index.cjs, index.cjs.map, index.d.cts |
| entry: "src/foo.ts", exportPath: "./foo" | <outDir>/foo | foo.mjs, foo.mjs.map, foo.d.mts | foo.cjs, foo.cjs.map, foo.d.cts |
Notes:
- Default
outDirisdistwhen not set. - For subpath exports, output directory is computed as
outDir + exportPath.slice(1). - Declarations (
.d.mts/.d.cts) are emitted when provided by the underlying compiler result.
Package.json Update Matrix
When allowUpdatePackageJson (config) or --allow-update (CLI build) is enabled, Susee rewrites package metadata from the emitted file paths.
- Main export build with
exportPath: "."and CommonJS output: updatesmainto the generated.cjsfile. - Main export build with
exportPath: "."and ESM output: updatesmoduleto the generated.mjsfile. - Main export build with
exportPath: "."and declarations: updatestypesto the generated declaration file. - Any export build with generated import or require declarations: creates or merges
exportsentries for that export path. - Any package update: forces
typeto"module".
Notes:
- Package update requires a
package.jsonfile in the project root. - For subpath exports, Susee merges the generated entry into existing
exportswhen that field is an object. - For the main export path
., Susee replacesexportswith the generated root mapping.
Validation Rules
From config validation logic:
- At least one
entryPointsitem is required. - Duplicate
exportPathvalues are rejected. - Each
entrypath must exist. - Duplicate top-level declarations across bundled files fail the build during dependency analysis.
- CommonJS modules in the dependency tree fail the build unless you handle them with
@suseejs/commonjs-plugin.
Violations print an error and exit with code 1.
