Building
What the build step does
Section titled “What the build step does”The build step transforms TypeScript source code into distributable JavaScript. The raw .ts files in src/ can’t be published or executed directly by Node.js — they need to be compiled to .js, and type declarations (.d.ts) need to be generated so consumers get autocompletion.
tsup handles this. It’s a TypeScript bundler powered by esbuild, which compiles orders of magnitude faster than the standard TypeScript compiler (tsc). tsup also handles ESM output correctly without extra configuration and generates both JavaScript and type declarations in a single step.
The build produces two entry points:
dist/cli.js— the CLI binary. This is what thebinfield inpackage.jsonpoints to, and what runs when a user typessemtest. It contains the Commander command definitions and orchestrates the full pipeline.dist/index.js— the public API. This is what consumers get when theyimport { defineConfig } from "@thulanek/semtest-runner". It re-exports the config helper and types for programmatic use.
Code splitting is enabled, so shared modules (like the config schema, which both entry points need) are bundled into a separate chunk and imported by both — no duplication.
tsup configuration
Section titled “tsup configuration”The config lives at packages/semtest-runner/tsup.config.ts:
import { defineConfig } from "tsup";
export default defineConfig({ entry: ["src/cli.ts", "src/index.ts"], format: ["esm"], dts: true, clean: true, target: "node20", splitting: true,});| Option | Value | Purpose |
|---|---|---|
entry | cli.ts, index.ts | Two entry points — CLI binary and public API |
format | esm | ESM-only output (no CJS) |
dts | true | Generates .d.ts declaration files |
clean | true | Clears dist/ before each build |
target | node20 | Minimum Node version |
splitting | true | Code-splits shared modules between entry points |
TypeScript configuration
Section titled “TypeScript configuration”Key compiler options from packages/semtest-runner/tsconfig.json:
| Option | Value |
|---|---|
target | ES2022 |
module | ESNext |
moduleResolution | bundler |
strict | true |
declaration | true |
isolatedModules | true |
Turbo pipeline
Section titled “Turbo pipeline”The root turbo.json defines three tasks:
{ "tasks": { "build": { "dependsOn": ["^build"], "outputs": ["dist/**"] }, "dev": { "cache": false, "persistent": true }, "test": { "dependsOn": ["build"] } }}- build: Topologically ordered — dependencies build before dependents. Cached by
dist/**output. - dev: Not cached, runs persistently (watch mode).
- test: Runs after build completes.
Build commands
Section titled “Build commands”# Build everythingpnpm turbo run build
# Build only the main packagepnpm turbo run build --filter=@thulanek/semtest-runner
# Watch mode (dev)pnpm turbo run dev --filter=@thulanek/semtest-runner