This file provides guidance to AI coding assistants when working with code in this repository.
Generated: 2026-01-28 | Commit: 9b0b0f5f | Branch: develop
- Node.js: >=22.0.0
- Bun: 1.3.5+ (package manager & runtime)
| Task | Command |
|---|---|
| Install | bun install |
| Build all | bun run build |
| Build deps first | bun run build:deps (utils) |
| Lint | bun run lint |
| Format | bun run format |
| Typecheck | bun run typecheck |
| Test all | bun run test |
| Test package | bun run test packages/<name> |
| Test file | bun run test packages/core/__tests__/core.test.ts |
| Doctor | node-minify doctor |
| CI (full) | bun run ci |
| Add changeset | bun run changeset |
- Indent: 4 spaces | Quotes: double | Semicolons: always | Trailing commas: ES5
- Imports:
typekeyword for type-only;node:prefix for Node.js built-ins - Extensions: Include
.tsin local imports (e.g.,./setup.ts) - Naming: camelCase functions/variables, PascalCase types/interfaces
- Headers: All source files:
/*! node-minify ... MIT Licensed */ - JSDoc: All exported functions MUST have
@paramand@returnstags
Bun monorepo for compressing JS, CSS, HTML, JSON, and images.
packages/
├── core/ # Main minify() function
├── utils/ # Shared utilities (see packages/utils/AGENTS.md)
├── types/ # TypeScript definitions (no build, exports src/types.d.ts)
├── cli/ # Commander.js CLI
├── benchmark/ # Compressor comparison tool
├── action/ # GitHub Action (see packages/action/AGENTS.md)
└── <compressor>/ # 22 compressor wrappers (terser, esbuild, lightningcss, etc.)
| Type | Recommended | Alternatives |
|---|---|---|
| JS | terser |
esbuild, swc, oxc, uglify-js, google-closure-compiler |
| CSS | lightningcss |
esbuild, clean-css, cssnano, csso |
| HTML | html-minifier |
minify-html |
| JSON | jsonminify |
- |
| Images | sharp (WebP/AVIF), svgo (SVG), imagemin (PNG/JPEG/GIF) |
- |
Removed (v11): babel-minify, uglify-es, yui, crass, sqwish
core → utils + types
cli → core + benchmark + utils
action → core + benchmark + utils
benchmark → core + utils
compressors → utils + types
Build order: utils first → all others parallel
packages/<name>/
├── src/index.ts # Main export
├── __tests__/ # Vitest tests
├── package.json # exports: { types, default }
├── tsconfig.json
└── vitest.config.ts
Exceptions:
types: No build, exportssrc/types.d.tsdirectlyaction: Usesbun build(bundled), hasaction.ymlcli: Dual entry (src/index.ts+src/bin/cli.ts)utils: Multi-file build (tsdown src/*.ts)
From @node-minify/types:
Settings // User options for minify()
MinifierOptions // What compressors receive: { settings, content }
CompressorResult // What compressors return: { code, map?, buffer?, outputs? }
Compressor // Function: (args: MinifierOptions) => Promise<CompressorResult>- Create
packages/<name>/with standard structure - Export async function matching
Compressortype:
import type { CompressorResult, MinifierOptions } from "@node-minify/types";
import { ensureStringContent, wrapMinificationError } from "@node-minify/utils";
export async function myCompressor({ settings, content }: MinifierOptions): Promise<CompressorResult> {
const contentStr = ensureStringContent(content, "my-compressor");
try {
// ... minification logic
return { code: minifiedCode };
} catch (error) {
throw wrapMinificationError("my-compressor", error);
}
}- Add tests using
runOneTestfromtests/fixtures.ts - Add changeset:
bun run changeset
Shared fixtures (tests/fixtures.ts):
runOneTest({ options, compressorLabel, compressor })— Run single testtestsobject — Pre-defined suites:concat,commonjs,commoncss,commonhtml,commonjson
File paths (tests/files-path.ts):
filesJS,filesCSS,filesHTML,filesJSON,filesImages
Convention: Tests auto-isolate to tests/tmp/ when using replaceInPlace or $1 output patterns.
Timeouts: Some packages use 60s timeout for slow compressors.
Required for user-facing changes:
bun run changeset # Add changeset (interactive)
bun run changeset:version # Bump versionsCustom scripts/publish.ts resolves workspace:* → concrete versions before npm publish.
-
Never use
any— not asas any, not as an annotation, not as a type argument. Biome'snoExplicitAnyis set toerrorand fires on every explicitanyin any position, so the gate is broader than theas anysymptom it was introduced for. -
Never use
as unknown as Tanywhere. No linter catches this shape, so it is enforced by review: use a real type, or@ts-expect-errorwhere the invalidity is the point -
Never use
@ts-ignoreor@ts-nocheckanywhere — both silently disable checking rather than proving an error exists -
Never use
@ts-expect-errorinsrc/— fix the type instead -
In test files only,
@ts-expect-erroris sanctioned for two cases, each of which must carry a comment on the same line naming the specific condition:// @ts-expect-error testing invalid input: settings is missing required fields // @ts-expect-error mock is narrower than the real type it stands in for
Test files are typechecked (
bun run typecheck), so an unused directive fails the build — the suppression cannot rot. This covers every__tests__/directory plus the sharedtests/helpers andtests/integration/.Place the directive on the line the compiler reports, which is not always the offending property: a missing required field is reported on the object-literal or declaration line, so the directive belongs there rather than on a property. Where several errors would be reported for one literal, TypeScript surfaces only the first — keep the comment to the error actually being suppressed instead of listing every latent one.
Enforcement of these four rules is split. Biome's
noTsIgnorecatches@ts-ignore, and root lint covers workspace packages plustests/,scripts/, andexamples/vialint:root.scripts/ci-guard-type-suppressions.shis the mechanism for what no Biome rule covers: it bans@ts-nocheckand@ts-ignoreacross the whole repository, bans@ts-expect-errorunder anysrc/, and rejects a directive with no reason after it. Run it locally withbash scripts/ci-guard-type-suppressions.sh; CI runs it on the Linux/Node 22 leg. -
Never remove JSDoc from exported functions
-
Never use deprecated packages in new code
-
Never commit without
bun run lint -
Never use sync file operations in compressor code (use async)
-
Never mix image and text files in same input array
Published as srod/node-minify@v11. See packages/action/AGENTS.md for details.
- uses: srod/node-minify@v11
with:
input: "src/app.js"
output: "dist/app.min.js"
compressor: "terser"Zero-config mode:
- uses: srod/node-minify@v11
with:
auto: true
output-dir: dist| Workflow | Trigger | Purpose |
|---|---|---|
test.yml |
Push/PR | Build, lint, typecheck, test |
publish.yml |
Push to main | Changesets release + npm publish |
test-action.yml |
Action changes | GitHub Action integration tests |
release-action.yml |
Release | Bundle action dist, update tags |
docs/ is a separate Astro site. See docs/AGENTS.md.
cd docs && bun run dev # Dev server at localhost:4321
cd docs && bun run build # Production build| Issue | Fix |
|---|---|
| Build fails | bun run build:deps first |
| Type errors | Run bun run build (types from dist/) |
| Test isolation | Uses tests/tmp/ (gitignored) |
| Clean rebuild | bun run clean && bun run build |