core/validators/leak.validator.ts

core/validators/leak.validator.ts is a file in Bane's Lab Content. 53 lines of code and 12 definitions.

import {
    LEAK_IDENTIFIER,
    LEAK_INLINE,
    LEAK_PATH,
    machinePathLine,
    privateTermLine,
} from "#configuration/strings/coverage.strings";
import type { LeakReason, LeakSet, PagePayload, PrivateHit, PublishedFile } from "#types/leak.types";
import type { Finding } from "#types/derivation.types";
import { leaksIn } from "#core/matchers/leak.matcher";

const NEWLINE = "\n";

const lineAt = function lineAt(text: string, at: number): number {
    return text.slice(0, at).split(NEWLINE).length;
};

export const validatePublished = function validatePublished(
    published: PublishedFile,
    scan: (text: string) => PrivateHit[],
    machinePaths: readonly string[],
): Finding[] {
    const terms = scan(published.text).map((hit) => ({
        file: published.file,
        message: privateTermLine(hit.line, hit.digest),
    }));
    const paths = machinePaths.flatMap((path) => {
        const at = published.text.indexOf(path);
        return at === -1 ? [] : [{ file: published.file, message: machinePathLine(lineAt(published.text, at)) }];
    });
    return [...terms, ...paths];
};

const REASON_LEADS: Readonly<Record<LeakReason, string>> = {
    identifier: LEAK_IDENTIFIER,
    "inline-code": LEAK_INLINE,
    path: LEAK_PATH,
};

export const validatePayload = function validatePayload(
    payload: PagePayload,
    leaks: LeakSet,
    roots: ReadonlySet<string>,
): Finding[] {
    const tokens = new Set(leaks.tokens);
    const findings: Finding[] = [];
    const seen = new Set<string>();
    for (const text of payload.strings) {
        for (const match of leaksIn(text, tokens, roots)) {
            const key = match.reason + match.token;
            if (!seen.has(key)) {
                seen.add(key);
                findings.push({ file: payload.file, message: `${REASON_LEADS[match.reason]}${match.token}` });
            }
        }
    }
    return findings;
};