Files
skills/docs/devtools/tooling/linter/src/bin.md
2026-05-29 08:20:56 +01:00

2.5 KiB

bin

Purpose

bin.ts is the executable entry point installed by package.json as the suaveplan-lint binary. It is intentionally a one-line wrapper around runCli from @suaveplan/linter/cli: the wrapper calls the pure CLI function with process.argv.slice(2), then translates the resolved { code } into process.exit. Keeping process.exit out of every other file in the package means tests and embedded callers never accidentally terminate their host process, but the shipped binary still behaves like a conventional Unix tool — exit non-zero on failure, zero on success.

Features

  • Tiny — fewer than ten lines, no dependencies beyond cli.
  • Surfaces unhandled exceptions (anything runCli didn't catch as a LinterError) via process.stderr then exits with code 2 so operators can distinguish CLI parse failures (code 1) from completely unexpected crashes (code 2).
  • Uses .then rather than await to support compilers (and Vite's esbuild target) that don't permit top-level await — the binary is built into ESM via the same Vite pipeline as the rest of the package, and that pipeline targets es2020.

Usage: Basic

bunx suaveplan-lint --help
bunx suaveplan-lint --fix
bunx suaveplan-lint "docs/**/*.md"

Usage: Advanced

Embed the same logic in a custom CLI without spawning a subprocess:

import { runCli } from "@suaveplan/linter/cli";

const { code } = await runCli(["--fix", "docs/*.md"], {
    out: (line) => console.error(line),
});
process.exit(code);

API Reference

The binary has no public API surface beyond the suaveplan-lint shell entry. Implementation is runCli(process.argv.slice(2)) followed by process.exit(code). Unhandled rejections trigger process.exit(2) after writing the error to stderr.

Implementation Notes

  • The #!/usr/bin/env node shebang is preserved by Vite's entryFileNames configuration. Bun also accepts the same shebang line.
  • runCli already catches LinterError and writes a one-line summary via the injected out sink (defaulting to console.log); the .then rejection handler exists for any error type runCli did not handle — historically zero, but the wrapper exists so a future refactor that throws an unrelated TypeError from a helper still produces a useful exit code instead of an unhandled-rejection crash.
  • The bin field in package.json points at ./dist/bin.js, which is emitted by the Vite build alongside the other ESM entries with the shebang intact.