diffjam
Version:
cli for diffjam.com
100 lines (88 loc) • 2.63 kB
text/typescript
import { equal } from "node:assert";
import { join } from "node:path";
import cluster from "node:cluster";
import { Config } from "./Config";
import { Match } from "./match";
import { Policy } from "./Policy";
import { readFile } from "fs";
import { FileMatcher } from "./FileMatcher";
export type Message =
| { type: "match"; policyName: string; match: Match }
| { type: "processedFile"; filePath: string };
export function processFile(
filePath: string,
cwd: string,
config: Config,
onMatch: (match: Match, policy: Policy) => void,
onDone: (filePath: string) => void
) {
readFile(join(cwd, filePath), { encoding: "utf8" }, (err, fileContents) => {
if (err) {
if (err.code === "ENOENT") {
// File doesn't exist, so we'll just skip it.
onDone(filePath);
return;
}
throw err;
}
const file = new FileMatcher(filePath, fileContents);
for (const policy of Object.values(config.policyMap)) {
policy.processFile(file, onMatch);
}
onDone(filePath);
});
}
export function readyWorker(
config: Config,
cwd: string,
onMatch: (match: Match, policy: Policy) => void,
onDone: (filePath: string) => void
) {
return {
processFile(filePath: string) {
processFile(filePath, cwd, config, onMatch, onDone);
},
};
}
export async function workerProcess() {
equal(
cluster.isPrimary || cluster.isMaster,
false,
"workerProcess() should only be called in a worker process"
);
let confReady = false;
const queued: string[] = [];
equal(!!process.env.configFilePath, true, "configFilePath not set");
equal(!!process.env.cwd, true, "cwd not set");
const conf = Config.read(process.env.configFilePath!);
const cwd = process.env.cwd!;
// We may receive messages while still loading the config.
// We'll queue them up and process them once the config is ready.
process.on("message", (message: any) => {
const { filePath } = message;
if (!confReady) return queued.push(filePath);
worker.processFile(filePath);
});
// Errors in reading the config should be caught and logged by the parent process.
let config: Config;
try {
config = await conf;
} catch (err) {
return;
}
confReady = true;
const worker = readyWorker(
config,
cwd,
(match: Match, policy: Policy) => {
process.send!({ type: "match", policyName: policy.name, match });
},
(filePath: string) => {
process.send!({ type: "processedFile", filePath });
}
);
let filePath: string | undefined;
while ((filePath = queued.shift())) {
worker.processFile(filePath);
}
}