# runtime/entrypoints/report.entrypoint.ts

> 139 lines of code and 33 definitions.

Tree: GovLab Patterns
Language: typescript
Layer: runtime
Canonical: https://banes-lab.com/anatomy/patterns#file-patterns-runtime-entrypoints-report-entrypoint-ts
Source text: https://banes-lab.com/source/patterns/runtime/entrypoints/report.entrypoint.ts.txt

Listed in [runtime/entrypoints](https://banes-lab.com/api/source/patterns/runtime/entrypoints.md), after [runtime/entrypoints/pattern.entrypoint.ts](https://banes-lab.com/source/patterns/runtime/entrypoints/pattern.entrypoint.ts.md).

## Definitions

- `titleOf` (lexical_declaration, line 42)
- `writeModule` (lexical_declaration, line 76)
- `svgUnits` (lexical_declaration, line 64)
- `knownSlugs` (lexical_declaration, line 68)
- `titles` (lexical_declaration, line 72)
- `artifactsFor` (lexical_declaration, line 53)
- `writeAll` (lexical_declaration, line 83)
- `pool` (lexical_declaration, line 46)
- `writeSvgs` (method_definition, line 122)
- `runOne` (lexical_declaration, line 128)
- `runAll` (lexical_declaration, line 100)
- `writeMaster` (method_definition, line 119)
- `generate` (method_definition, line 136)
- `masterOk` (method_definition, line 112)
- `argv` (lexical_declaration, line 31)
- `ignored` (lexical_declaration, line 32)
- `markers` (lexical_declaration, line 35)
- `pruned` (lexical_declaration, line 36)
- `masterPath` (lexical_declaration, line 37)
- `cache` (lexical_declaration, line 38)
- `scope` (lexical_declaration, line 40)
- `{ built, title }` (lexical_declaration, line 54)
- `artifacts` (lexical_declaration, line 55)
- `{ artifacts, svgs }` (lexical_declaration, line 77)
- `svgs` (lexical_declaration, line 84)
- `fanIn` (lexical_declaration, line 86)
- `files` (lexical_declaration, line 87)
- `key` (lexical_declaration, line 88)
- `modules` (lexical_declaration, line 101)
- `ctx` (lexical_declaration, line 129)
- `result` (lexical_declaration, line 134)
- `check` (lexical_declaration, line 149)
- `target` (lexical_declaration, line 150)

## Contained in

- [runtime/entrypoints](https://banes-lab.com/anatomy/patterns/folder-patterns-runtime-entrypoints.md)

## Uses

- [configuration/strings/report.strings.ts](https://banes-lab.com/source/patterns/configuration/strings/report.strings.ts.md)
- [core/caches/report.cache.ts](https://banes-lab.com/source/patterns/core/caches/report.cache.ts.md)
- [core/coordinators/report.coordinator.ts](https://banes-lab.com/source/patterns/core/coordinators/report.coordinator.ts.md)
- [core/persistence/report.persistence.ts](https://banes-lab.com/source/patterns/core/persistence/report.persistence.ts.md)
- [core/resolvers/package.resolver.ts](https://banes-lab.com/source/patterns/core/resolvers/package.resolver.ts.md)
- [core/validators/report.validator.ts](https://banes-lab.com/source/patterns/core/validators/report.validator.ts.md)

## Enforces

- [Reproducibility](https://banes-lab.com/records/architecture/reproducibility.md)

## Linked from

- [configuration/strings](https://banes-lab.com/anatomy/patterns/folder-patterns-configuration-strings.md)
- [core/caches](https://banes-lab.com/anatomy/patterns/folder-patterns-core-caches.md)
- [core/coordinators](https://banes-lab.com/anatomy/patterns/folder-patterns-core-coordinators.md)
- [core/persistence](https://banes-lab.com/anatomy/patterns/folder-patterns-core-persistence.md)
- [core/resolvers](https://banes-lab.com/anatomy/patterns/folder-patterns-core-resolvers.md)
- [core/validators](https://banes-lab.com/anatomy/patterns/folder-patterns-core-validators.md)
- [runtime/entrypoints](https://banes-lab.com/anatomy/patterns/folder-patterns-runtime-entrypoints.md)

## Source

```typescript
import {
    FAILURE_EXIT,
    LIST_SEPARATOR,
    NO_CACHE_ENV,
    NO_CACHE_ON,
    REPORT_FLAG_NAMES,
} from "#configuration/constants/invocation.constants";
import { HEAL_ATTEMPTS, HTML_SUFFIX, SLUG_JOIN } from "#configuration/constants/report.constants";
import { HEAL_NOTES, healNote, moduleDrift, moduleWritten, writeSummary } from "#configuration/strings/report.strings";
import type { ModuleArtifacts, ModuleSvgs, ModuleTitle } from "#types/report.types";
import type { ModuleScope, RepoContext } from "#types/package.types";
import { ROOT, absolutePath, relativePath } from "@ssot/paths";
import { basename, resolve } from "node:path";
import { buildContext, emptyContext } from "#core/factories/context.factory";
import { discoverModules, sourceFiles, testFilesOf } from "#core/loaders/package.loader";
import { flagValue, hasFlag, resolveArgv } from "@govlab/argv";
import { healModule, runHexCheck } from "#core/coordinators/report.coordinator";
import { hexArtifactsExist, moduleFingerprint, openReportCache } from "#core/caches/report.cache";
import { loadGovlabConfig, masterExcludeMarkers, pathExclusion } from "@govlab/quality/config";
import { persistArtifacts, writeHexMaster, writeSvgCollection } from "#core/persistence/report.persistence";
import { REPORT_ARGV } from "#configuration/configs/invocation.config";
import { buildModuleReport } from "#core/coordinators/package.coordinator";
import { checkHexMaster } from "#core/validators/report.validator";
import { defineCheck } from "@govlab/context/check";
import process from "node:process";
import { settleParses } from "#core/loaders/source.loader";
import { titleFor } from "#core/resolvers/package.resolver";

defineCheck({ detects: [], enforces: ["architecture:reproducibility"] });

const argv = resolveArgv(REPORT_ARGV);
const ignored = (flagValue(argv, REPORT_FLAG_NAMES.ignore) ?? "")
    .split(LIST_SEPARATOR)
    .filter((entry) => entry.length > 0);
const markers = masterExcludeMarkers(await loadGovlabConfig(process.cwd()));
const pruned = pathExclusion(process.cwd(), [...markers, ...ignored]);
const masterPath = absolutePath("projectInfo.findings");
const cache = openReportCache(process.env[NO_CACHE_ENV] === NO_CACHE_ON);

const scope: ModuleScope = { pruned, root: ROOT };

const titleOf = function titleOf(moduleDir: string): string {
    return titleFor(ROOT, moduleDir);
};

const pool = async function pool(items: readonly string[], worker: (item: string) => Promise<void>): Promise<void> {
    await items.reduce(async (queued, item) => {
        await queued;
        await worker(item);
    }, Promise.resolve());
};

const artifactsFor = async function artifactsFor(moduleDir: string, ctx: RepoContext): Promise<ModuleArtifacts> {
    const { built, title } = await buildModuleReport(moduleDir, ctx, scope);
    const artifacts = new Map<string, string>([
        ...[...built.pages].map(([base, html]): [string, string] => [`${base}.generated${HTML_SUFFIX}`, html]),
        [basename(relativePath("moduleInfo.analysis")), built.analysis],
        [basename(relativePath("moduleInfo.findings")), built.findings],
        [basename(relativePath("moduleInfo.report")), JSON.stringify(built.report)],
    ]);
    return { artifacts, findings: { findings: built.findingsData, module: title }, svgs: built.svgs };
};

const svgUnits = function svgUnits(byModule: ReadonlyMap<string, ReadonlyMap<string, string>>): ModuleSvgs[] {
    return [...byModule].map(([moduleDir, svgs]) => ({ slug: titleOf(moduleDir).split("/").join(SLUG_JOIN), svgs }));
};

const knownSlugs = function knownSlugs(modules: readonly string[]): Set<string> {
    return new Set(modules.map((dir) => titleOf(dir).split("/").join(SLUG_JOIN)));
};

const titles = function titles(modules: readonly string[]): ModuleTitle[] {
    return modules.map((dir) => ({ dir, title: titleOf(dir) }));
};

const writeModule = async function writeModule(moduleDir: string, ctx: RepoContext): Promise<Map<string, string>> {
    const { artifacts, svgs } = await artifactsFor(moduleDir, ctx);
    persistArtifacts(moduleDir, artifacts);
    process.stdout.write(moduleWritten(titleOf(moduleDir), artifacts.size));
    return svgs;
};

const writeAll = async function writeAll(modules: readonly string[], ctx: RepoContext): Promise<void> {
    const svgs = new Map<string, Map<string, string>>();
    await pool(modules, async (moduleDir) => {
        const fanIn = [...ctx.fanIn].filter(([key]) => key.startsWith(`${moduleDir}::`));
        const files = [...sourceFiles(moduleDir, pruned), ...testFilesOf(moduleDir, pruned)];
        const key = moduleFingerprint(files, fanIn, ctx.importCycles.get(moduleDir) ?? []);
        if (!cache.unchanged(moduleDir, key) || !hexArtifactsExist(moduleDir)) {
            svgs.set(moduleDir, await writeModule(moduleDir, ctx));
            cache.update(moduleDir, key);
        }
    });
    writeSvgCollection(ROOT, svgUnits(svgs), knownSlugs(modules));
    writeHexMaster(masterPath, titles(modules));
    cache.flush();
    process.stdout.write(writeSummary(svgs.size, modules.length));
};

const runAll = async function runAll(check: boolean): Promise<void> {
    const modules = discoverModules(ROOT, pruned);
    const ctx = await buildContext(modules, scope);
    if (!check) {
        await writeAll(modules, ctx);
        return;
    }
    await runHexCheck({
        attempts: HEAL_ATTEMPTS,
        async generate(moduleDir) {
            return artifactsFor(moduleDir, ctx);
        },
        masterOk(collected) {
            return checkHexMaster(masterPath, collected);
        },
        modules,
        pool,
        reparse: settleParses,
        title: titleOf,
        writeMaster() {
            writeHexMaster(masterPath, titles(modules));
        },
        writeSvgs(byModule) {
            writeSvgCollection(ROOT, svgUnits(byModule), knownSlugs(modules));
        },
    });
};

const runOne = async function runOne(moduleDir: string, check: boolean, fast: boolean): Promise<void> {
    const ctx = fast ? emptyContext() : await buildContext(discoverModules(ROOT, pruned), scope);
    if (!check) {
        await writeModule(moduleDir, ctx);
        return;
    }
    const result = await healModule(moduleDir, {
        attempts: HEAL_ATTEMPTS,
        async generate(dir) {
            return artifactsFor(dir, ctx);
        },
        reparse: settleParses,
    });
    if (result.state === "drift") {
        process.stderr.write(moduleDrift(moduleDir));
        process.exitCode = FAILURE_EXIT;
        return;
    }
    process.stdout.write(healNote(HEAL_NOTES[result.state]));
};

const check = hasFlag(argv, REPORT_FLAG_NAMES.check);
const target = resolve(argv.positionals[0] ?? ".");

await (hasFlag(argv, REPORT_FLAG_NAMES.all)
    ? runAll(check)
    : runOne(target, check, hasFlag(argv, REPORT_FLAG_NAMES.fast)));
```
