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> = { identifier: LEAK_IDENTIFIER, "inline-code": LEAK_INLINE, path: LEAK_PATH, }; export const validatePayload = function validatePayload( payload: PagePayload, leaks: LeakSet, roots: ReadonlySet, ): Finding[] { const tokens = new Set(leaks.tokens); const findings: Finding[] = []; const seen = new Set(); 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; };