tools/core/validators/writer.validator.ts

tools/core/validators/writer.validator.ts is a file in Coordination Surface. 43 lines of code and 9 definitions.

import { filesystemImports } from "../predicates/source.predicate.ts";
import { localImports } from "../analyzers/graph.analyzer.ts";

const WRITE_MEMBERS = [`writeFileSync`, `rmSync`, `mkdirSync`];

interface WriteBreach {
    readonly path: string;
    readonly member: string;
}

export const importsWriter = function importsWriter(source: string): string | null {
    return (
        filesystemImports(source)
            .map((line) => WRITE_MEMBERS.find((member) => line.includes(member)))
            .find((member) => member !== undefined) ?? null
    );
};

export const reachableFrom = function reachableFrom(
    entries: readonly string[],
    known: ReadonlySet<string>,
    read: (path: string) => string,
): string[] {
    const seen = new Set<string>();
    const queue = [...entries];

    while (queue.length > 0) {
        const path = queue.shift() ?? "";
        if (path.length > 0 && !seen.has(path)) {
            seen.add(path);
            queue.push(...localImports(path, read(path), known));
        }
    }

    return [...seen].toSorted((left, right) => left.localeCompare(right, "en"));
};

export const unsanctionedWriters = function unsanctionedWriters(
    entries: readonly string[],
    known: ReadonlySet<string>,
    read: (path: string) => string,
    sanctioned: readonly string[],
): WriteBreach[] {
    return reachableFrom(entries, known, read)
        .filter((path) => !sanctioned.includes(path))
        .flatMap((path) => {
            const member = importsWriter(read(path));
            return member === null ? [] : [{ member, path }];
        });
};