Initial Commit
This commit is contained in:
93
packages/devtools/tooling/linter/src/cli/cli.md
Normal file
93
packages/devtools/tooling/linter/src/cli/cli.md
Normal file
@@ -0,0 +1,93 @@
|
||||
# `cli`
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
|
||||
## Purpose
|
||||
|
||||
`@suaveplan/linter/cli` is the pure-function CLI entry point. It parses an `argv` array,
|
||||
runs the unified orchestrator, and returns a resolved exit code. Unlike the upstream
|
||||
package, it never calls `process.exit` — the shipped binary (`suaveplan-lint`) is a
|
||||
one-line wrapper that calls `runCli(process.argv.slice(2))` and then exits with the
|
||||
returned code. Keeping the CLI pure means tests can assert on the resolved code without
|
||||
the test process terminating mid-suite, and other tools (pre-commit hooks, IDE
|
||||
integrations) can embed the CLI logic directly.
|
||||
|
||||
## Features
|
||||
|
||||
- Hand-rolled argv parser — no `commander` dependency for a binary with five flags.
|
||||
- Recognised flags: `--help` / `-h`, `--fix` / `--write`, `--unified`,
|
||||
`--markdown-only`, `--cwd <path>`. Anything else starting with `-` raises
|
||||
`LinterError(LINTER.UNKNOWN_FLAG)` (rather than silently treating it as a positional
|
||||
pattern, which is how the upstream package quietly swallowed typos).
|
||||
- Positional arguments accumulate into `patterns` so multiple globs are supported.
|
||||
- Injectable `out: (line: string) => void` sink for tests — defaults to `console.log`.
|
||||
- Translates `runUnifiedLint`'s `LintReport.success` into exit code 0 / 1, prints a
|
||||
concise summary line, and catches `LinterError` to surface the code and message in
|
||||
the summary.
|
||||
|
||||
## Usage: Basic
|
||||
|
||||
```ts
|
||||
import { runCli } from "@suaveplan/linter/cli";
|
||||
|
||||
const { code } = await runCli(process.argv.slice(2));
|
||||
process.exit(code);
|
||||
```
|
||||
|
||||
## Usage: Advanced
|
||||
|
||||
Embed the CLI inside another tool with full adapter control:
|
||||
|
||||
```ts
|
||||
import { runCli } from "@suaveplan/linter/cli";
|
||||
import type { CommandRunner } from "@suaveplan/linter";
|
||||
|
||||
const lines: string[] = [];
|
||||
const out = (line: string) => lines.push(line);
|
||||
const runner: CommandRunner = {
|
||||
async run() {
|
||||
return { exitCode: 0, stdout: "", stderr: "" };
|
||||
},
|
||||
};
|
||||
|
||||
const { code } = await runCli(["--fix", "docs/*.md"], {
|
||||
out,
|
||||
runner,
|
||||
cwd: "/tmp/repo",
|
||||
});
|
||||
// code === 0, lines contains the summary
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
### `runCli(argv, options?): Promise<{ code: number }>`
|
||||
|
||||
- `argv: ReadonlyArray<string>` — required. The argv slice (typically
|
||||
`process.argv.slice(2)`).
|
||||
- `options.out?: (line: string) => void` — sink for help / summary / error lines.
|
||||
- `options.runner?: CommandRunner` — forwarded to the orchestrator.
|
||||
- `options.fs?: FsAdapter`, `options.glob?: GlobAdapter`, `options.clock?: ClockLike`
|
||||
— forwarded to the orchestrator.
|
||||
|
||||
Returns `{ code: 0 }` on success or `{ code: 1 }` on failure. Throws
|
||||
`LinterError(LINTER.UNKNOWN_FLAG)` for an unrecognised flag.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
- The parser uses a single forward sweep; flags are recognised by exact match and
|
||||
positional args are anything that doesn't start with `-` (or `--cwd <path>` where
|
||||
the next token is consumed as the cwd value). This is deliberately simple — the
|
||||
scope is five flags, not a general argv parser.
|
||||
- `--unified` is accepted but no-op; the orchestrator runs both lanes by default and
|
||||
the flag exists for symmetry with the upstream CLI's documented surface.
|
||||
- The success summary names the count of markdown files touched and the count that
|
||||
were fixed. The failure summary names the biome exit code so consumers can grep CI
|
||||
output for the underlying cause.
|
||||
- `LinterError` is caught here (not at the orchestrator) because the CLI is the layer
|
||||
that maps domain errors to exit codes. Letting the error propagate out of `runCli`
|
||||
would force every consumer to write the same translation.
|
||||
- The CLI does NOT print the markdown reports inline. Consumers that want per-file
|
||||
output can call `runUnifiedLint` directly; the CLI summary is the "CI-friendly"
|
||||
shape.
|
||||
Reference in New Issue
Block a user