core/persistence/report.persistence.ts

core/persistence/report.persistence.ts is a file in GovLab Patterns. 69 lines of code and 14 definitions.

import { ARTIFACT_SUFFIXES, SLUG_JOIN, SVG_SUFFIX } from "#configuration/constants/report.constants";
import type { ModuleFindings, ModuleSvgs, ModuleTitle } from "#types/report.types";
import { dirname, join } from "node:path";
import { existsSync, mkdirSync, readdirSync, unlinkSync } from "node:fs";
import { masterWritten, svgCollection } from "#configuration/strings/report.strings";
import { buildMasterFindings } from "#core/formatters/report.formatter";
import { loadModuleFindings } from "#core/loaders/finding.loader";
import process from "node:process";
import { relativePath } from "@ssot/paths";
import { writeVerbatim } from "@govlab/canonical-write";

export const HEX_DIR = relativePath("moduleInfo.root");

const isArtifact = function isArtifact(name: string): boolean {
    return ARTIFACT_SUFFIXES.some((suffix) => name.endsWith(suffix));
};

export const staleFiles = function staleFiles(hexDir: string, keep: ReadonlySet<string>): string[] {
    return (existsSync(hexDir) ? readdirSync(hexDir) : []).filter((name) => isArtifact(name) && !keep.has(name));
};

export const persistArtifacts = function persistArtifacts(
    moduleDir: string,
    artifacts: ReadonlyMap<string, string>,
): void {
    const hexDir = join(moduleDir, HEX_DIR);
    mkdirSync(hexDir, { recursive: true });
    for (const name of staleFiles(hexDir, new Set(artifacts.keys()))) {
        unlinkSync(join(hexDir, name));
    }
    for (const [name, content] of artifacts) {
        writeVerbatim(join(hexDir, name), `${content}\n`);
    }
};

const slugOf = function slugOf(fileName: string): string {
    return fileName.slice(0, Math.max(0, fileName.indexOf(SLUG_JOIN)));
};

export const writeSvgCollection = function writeSvgCollection(
    rootDir: string,
    units: readonly ModuleSvgs[],
    known: ReadonlySet<string>,
): void {
    const svgDir = join(rootDir, relativePath("moduleInfo.svg"));
    const ran = new Set(units.map((unit) => unit.slug));
    const written = new Map(
        units.flatMap((unit) =>
            [...unit.svgs].map(([page, markup]): [string, string] => [
                `${unit.slug}${SLUG_JOIN}${page}${SVG_SUFFIX}`,
                markup,
            ]),
        ),
    );
    mkdirSync(svgDir, { recursive: true });
    const pruned = readdirSync(svgDir).filter((name) => {
        const slug = slugOf(name);
        return name.endsWith(SVG_SUFFIX) && !written.has(name) && (ran.has(slug) || !known.has(slug));
    });
    for (const name of pruned) {
        unlinkSync(join(svgDir, name));
    }
    for (const [name, markup] of written) {
        writeVerbatim(join(svgDir, name), `${markup}\n`);
    }
    process.stdout.write(svgCollection(written.size, pruned.length, svgDir));
};

export const writeHexMaster = function writeHexMaster(masterPath: string, units: readonly ModuleTitle[]): void {
    const found = units
        .map((unit) => loadModuleFindings(unit.dir, unit.title))
        .filter((entry): entry is ModuleFindings => entry !== null);
    mkdirSync(dirname(masterPath), { recursive: true });
    writeVerbatim(masterPath, `${buildMasterFindings(found)}\n`);
    process.stdout.write(masterWritten(masterPath));
};