tools/core/coordinators/rule.coordinator.ts
tools/core/coordinators/rule.coordinator.ts is a file in Coordination Surface. 97 lines of code and 17 definitions.
import type { RegisteredRule, RuleContext, Stage, StageResult } from "../types/rule.types.ts";
import type { RuleOutcome, RuleRun, RunOptions } from "../types/pipeline.types.ts";
import { STAGES } from "../types/rule.types.ts";
import { existsSync } from "node:fs";
import { resolve } from "node:path";
import { toPosix } from "../iterators/file.iterator.ts";
import { writeRuleReport } from "../reporters/rule.reporter.ts";
const SAT_OUT = { bypassed: false, findings: [], incomparable: false, written: [] } as const;
const bypassedStage = function bypassedStage(registered: RegisteredRule, stage: Stage): StageResult {
return {
bypassed: true,
findings: 0,
healed: 0,
invariant: registered.declaration.invariant,
rule: registered.id,
stage,
};
};
const handedPaths = function handedPaths(registered: RegisteredRule, run: RuleRun): string[] {
const { declaration } = registered;
const jurisdiction = run.byJurisdiction[declaration.jurisdiction];
const scoped =
declaration.extensions.length === 0
? jurisdiction
: jurisdiction.filter((path) =>
declaration.extensions.some((ext) => path.length > ext.length && path.endsWith(ext)),
);
const extra = (declaration.reads ?? []).filter(
(wanted) => !scoped.includes(wanted) && existsSync(resolve(run.options.repoRoot, wanted)),
);
return extra.length === 0 ? [...scoped] : [...scoped, ...extra];
};
const checkRule = function checkRule(registered: RegisteredRule, stage: Stage, run: RuleRun): RuleOutcome {
const { declaration } = registered;
const { options } = run;
const handed = handedPaths(registered, run);
const context: RuleContext = {
exists: (path: string) => existsSync(resolve(options.repoRoot, path)),
id: registered.id,
paths: handed,
read: run.read,
repoRoot: options.repoRoot,
taxonomy: run.taxonomy,
};
const started = process.hrtime.bigint();
const result = declaration.check(context, options.fix);
const elapsed = Number((process.hrtime.bigint() - started) / 1000n) / 1000;
writeRuleReport(options.repoRoot, registered.id, {
authoritative: run.authoritative,
derivations: result.derivations,
findings: result.findings,
healed: result.healed,
invariant: declaration.invariant,
mechanism: toPosix(options.repoRoot, registered.path),
rule: registered.id,
scanned: handed.length,
scope: run.scope,
stage: declaration.stage,
verdict: result.findings.length === 0 ? "pass" : "fail",
});
return {
bypassed: false,
findings: result.findings,
incomparable: false,
stage: {
bypassed: false,
elapsed,
findings: result.findings.length,
healed: result.healed.length,
invariant: declaration.invariant,
rule: registered.id,
stage,
},
written: result.healed,
};
};
export const walkRule = function walkRule(registered: RegisteredRule, stage: Stage, run: RuleRun): RuleOutcome {
const { bypass } = run.options;
if (bypass.includes(registered.id) || bypass.includes(stage)) {
return { ...SAT_OUT, bypassed: true, stage: bypassedStage(registered, stage) };
}
if (registered.declaration.wholeScopeOnly === true && !run.authoritative) {
return { ...SAT_OUT, incomparable: true, stage: bypassedStage(registered, registered.declaration.stage) };
}
return checkRule(registered, stage, run);
};
export const selectedRules = function selectedRules(
rules: readonly RegisteredRule[],
options: RunOptions,
): { registered: RegisteredRule; stage: Stage }[] {
return STAGES.filter((stage) => options.stage === null || options.stage === stage).flatMap((stage) =>
rules
.filter((registered) => registered.declaration.stage === stage)
.filter((registered) => options.ruleId === null || options.ruleId === registered.id)
.map((registered) => ({ registered, stage })),
);
};