Initial Commit
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
import {
|
||||
nodeCommandRunner,
|
||||
probeBiomeAvailable,
|
||||
runBiome,
|
||||
} from "../biome-runner/biome-runner.js";
|
||||
import { LinterError } from "../error-codes/error-codes.js";
|
||||
import { nodeGlobAdapter } from "../glob-resolver/glob-resolver.js";
|
||||
import {
|
||||
nodeFsAdapter,
|
||||
processMarkdownFiles,
|
||||
} from "../markdown-fixer/markdown-fixer.js";
|
||||
import { recordRunDuration } from "../telemetry/telemetry.js";
|
||||
import type {
|
||||
BiomeReport,
|
||||
ClockLike,
|
||||
LintReport,
|
||||
MarkdownFixReport,
|
||||
UnifiedLintOptions,
|
||||
} from "../types/linter.types.js";
|
||||
|
||||
const defaultClock: ClockLike = { now: () => Date.now() };
|
||||
|
||||
async function runBiomeLane(
|
||||
options: UnifiedLintOptions
|
||||
): Promise<BiomeReport | undefined> {
|
||||
const runner = options.runner ?? nodeCommandRunner;
|
||||
const cwd = options.cwd ?? ".";
|
||||
const available = await probeBiomeAvailable({ runner, cwd });
|
||||
if (!available) {
|
||||
return undefined;
|
||||
}
|
||||
const mode = options.fix === true ? "check-write" : "check";
|
||||
try {
|
||||
return await runBiome({ cwd, mode, runner });
|
||||
} catch (err) {
|
||||
// `runBiome` only raises `BIOME_FAILED` in `check` mode AND always
|
||||
// attaches the parsed `BiomeReport` under `details.report`, so this
|
||||
// branch is the documented surface that surfaces the embedded
|
||||
// report instead of re-throwing. All other errors propagate.
|
||||
if (err instanceof LinterError && err.code === "LINTER.BIOME_FAILED") {
|
||||
return err.details["report"] as BiomeReport;
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
async function runMarkdownLane(
|
||||
options: UnifiedLintOptions,
|
||||
clock: ClockLike
|
||||
): Promise<{
|
||||
reports: MarkdownFixReport[];
|
||||
durationMs: number;
|
||||
}> {
|
||||
const start = clock.now();
|
||||
const reports = await processMarkdownFiles({
|
||||
cwd: options.cwd ?? ".",
|
||||
fs: options.fs ?? nodeFsAdapter,
|
||||
glob: options.glob ?? nodeGlobAdapter,
|
||||
...(options.patterns ? { patterns: options.patterns } : {}),
|
||||
});
|
||||
const durationMs = Math.max(0, clock.now() - start);
|
||||
recordRunDuration("markdown", durationMs);
|
||||
return { reports, durationMs };
|
||||
}
|
||||
|
||||
/**
|
||||
* Orchestrator. Runs the biome lane (if available) and the markdown lane,
|
||||
* aggregates them into a {@link LintReport}, and returns. NEVER calls
|
||||
* `process.exit` — translation to an exit code is the CLI's job.
|
||||
*/
|
||||
export async function runUnifiedLint(
|
||||
options: UnifiedLintOptions = {}
|
||||
): Promise<LintReport> {
|
||||
const clock = options.clock ?? defaultClock;
|
||||
const start = clock.now();
|
||||
const biome =
|
||||
options.markdownOnly === true ? undefined : await runBiomeLane(options);
|
||||
const { reports } = await runMarkdownLane(options, clock);
|
||||
const durationMs = Math.max(0, clock.now() - start);
|
||||
const biomeSuccess = biome?.success ?? true;
|
||||
const success = biomeSuccess;
|
||||
recordRunDuration("total", durationMs);
|
||||
return {
|
||||
biome,
|
||||
markdown: reports,
|
||||
success,
|
||||
durationMs,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user