# core/converters/report.converter.ts

> 86 lines of code and 14 definitions.

Tree: Bane's Lab Build Scripts
Language: typescript
Layer: processing
Canonical: https://banes-lab.com/anatomy/build-scripts#file-build-scripts-core-converters-report-converter-ts
Source text: https://banes-lab.com/source/build-scripts/core/converters/report.converter.ts.txt

Listed in [core/converters](https://banes-lab.com/api/source/build-scripts/core/converters.md), after [core/converters/reference.field.converter.ts](https://banes-lab.com/source/build-scripts/core/converters/reference.field.converter.ts.md) and before [core/converters/route.converter.ts](https://banes-lab.com/source/build-scripts/core/converters/route.converter.ts.md).

## Definitions

- `definitionKey` (lexical_declaration, line 8, exported)
- `tally` (lexical_declaration, line 70)
- `fileStatsOf` (lexical_declaration, line 78, exported)
- `definitionView` (lexical_declaration, line 17)
- `definitionsByFile` (lexical_declaration, line 35, exported)
- `flaggedOf` (lexical_declaration, line 56, exported)
- `KEY_SEPARATOR` (lexical_declaration, line 5)
- `CYCLE_KIND` (lexical_declaration, line 6)
- `refOf` (lexical_declaration, line 12)
- `cut` (lexical_declaration, line 13)
- `byFile` (lexical_declaration, line 36, exported)
- `findingView` (lexical_declaration, line 43, exported)
- `flagged` (lexical_declaration, line 57, exported)
- `counts` (lexical_declaration, line 71)

## Contained in

- [core/converters](https://banes-lab.com/anatomy/build-scripts/folder-build-scripts-core-converters.md)

## Used by

- [core/converters/anatomy.converter.ts](https://banes-lab.com/source/build-scripts/core/converters/anatomy.converter.ts.md)
- [core/converters/anatomy.index.converter.ts](https://banes-lab.com/source/build-scripts/core/converters/anatomy.index.converter.ts.md)

## Linked from

- [core/converters](https://banes-lab.com/anatomy/build-scripts/folder-build-scripts-core-converters.md)

## Source

```typescript
import type { AnatomyStats, DefinitionRef, DefinitionView, FindingView } from "@banes-lab/web/types/anatomy.types.js";
import type { CodeFinding, DefinitionRecord, ModuleReport } from "@govlab/patterns";
import type { DiskFile } from "#types/structure.types";

const KEY_SEPARATOR = "::";
const CYCLE_KIND = "call-cycle";

export const definitionKey = function definitionKey(file: string, name: string): string {
    return file + KEY_SEPARATOR + name;
};

const refOf = function refOf(key: string): DefinitionRef {
    const cut = key.lastIndexOf(KEY_SEPARATOR);
    return { file: key.slice(0, cut), id: key, name: key.slice(cut + KEY_SEPARATOR.length) };
};

const definitionView = function definitionView(record: DefinitionRecord): DefinitionView {
    return {
        callable: record.callable,
        callees: record.callees.map(refOf),
        callers: record.callers.map(refOf),
        exported: record.exported,
        file: record.file,
        flow: record.flow,
        id: definitionKey(record.file, record.name),
        inDegree: record.inDegree,
        kind: record.kind,
        line: record.line,
        local: record.local,
        name: record.name,
        outDegree: record.outDegree,
    };
};

export const definitionsByFile = function definitionsByFile(report: ModuleReport): Map<string, DefinitionView[]> {
    const byFile = new Map<string, DefinitionView[]>();
    for (const record of report.definitions) {
        byFile.set(record.file, [...(byFile.get(record.file) ?? []), definitionView(record)]);
    }
    return byFile;
};

export const findingView = function findingView(finding: CodeFinding): FindingView {
    return {
        confidence: finding.confidence,
        detail: finding.detail,
        file: finding.file,
        kind: finding.kind,
        line: finding.line,
        name: finding.name,
        remedy: finding.remedy,
        severity: finding.severity,
    };
};

export const flaggedOf = function flaggedOf(findings: readonly CodeFinding[]): Map<string, string> {
    const flagged = new Map<string, string>();
    for (const finding of findings) {
        if (finding.kind === CYCLE_KIND) {
            for (const member of finding.members) {
                flagged.set(member, finding.severity);
            }
        } else {
            flagged.set(definitionKey(finding.file, finding.name), finding.severity);
        }
    }
    return flagged;
};

const tally = function tally(values: readonly string[]): Record<string, number> {
    const counts: Record<string, number> = {};
    for (const value of values) {
        counts[value] = (counts[value] ?? 0) + 1;
    }
    return counts;
};

export const fileStatsOf = function fileStatsOf(
    file: DiskFile,
    definitions: readonly DefinitionView[],
    edges: number,
    findings: readonly FindingView[],
): AnatomyStats {
    return {
        bytes: file.bytes,
        callable: definitions.filter((definition) => definition.callable).length,
        definitions: definitions.length,
        edges,
        exported: definitions.filter((definition) => definition.exported).length,
        files: 1,
        findings: tally(findings.map((finding) => finding.kind)),
        flows: tally(definitions.map((definition) => definition.flow)),
        lines: file.lines,
    };
};
```
