# core/loaders/pattern.loader.ts

> 27 lines of code and 6 definitions.

Tree: GovLab Stats
Language: typescript
Layer: infrastructure
Canonical: https://banes-lab.com/anatomy/stats#file-stats-core-loaders-pattern-loader-ts
Source text: https://banes-lab.com/source/stats/core/loaders/pattern.loader.ts.txt

Listed in [core/loaders](https://banes-lab.com/api/source/stats/core/loaders.md), after [core/loaders/manifest.loader.ts](https://banes-lab.com/source/stats/core/loaders/manifest.loader.ts.md) and before [core/loaders/registry.loader.ts](https://banes-lab.com/source/stats/core/loaders/registry.loader.ts.md).

## Definitions

- `countMap` (lexical_declaration, line 9)
- `collectFindings` (lexical_declaration, line 13, exported)
- `data` (lexical_declaration, line 14, exported)
- `summary` (lexical_declaration, line 15, exported)
- `modules` (lexical_declaration, line 16, exported)
- `withFindings` (lexical_declaration, line 17, exported)

## Contained in

- [core/loaders](https://banes-lab.com/anatomy/stats/folder-stats-core-loaders.md)

## Uses

- [core/predicates/record.predicate.ts](https://banes-lab.com/source/stats/core/predicates/record.predicate.ts.md)
- [core/selectors/field.selector.ts](https://banes-lab.com/source/stats/core/selectors/field.selector.ts.md)

## Linked from

- [core/loaders](https://banes-lab.com/anatomy/stats/folder-stats-core-loaders.md)
- [core/predicates](https://banes-lab.com/anatomy/stats/folder-stats-core-predicates.md)
- [core/selectors](https://banes-lab.com/anatomy/stats/folder-stats-core-selectors.md)

## Source

```typescript
import { arrayField, field, numberField, stringField } from "#core/selectors/field.selector";
import { FINDINGS_FILE } from "#configuration/constants/pattern.constants";
import type { FindingsStats } from "#types/pattern.types";
import { TOP_MODULES } from "#configuration/constants/metric.constants";
import { isRecord } from "#core/predicates/record.predicate";
import path from "node:path";
import { readJson } from "#core/loaders/data.loader";

const countMap = function countMap(value: unknown): Map<string, number> {
    return new Map(isRecord(value) ? Object.keys(value).map((key) => [key, numberField(value, key, 0)]) : []);
};

export const collectFindings = function collectFindings(root: string): FindingsStats {
    const data = readJson(path.join(root, FINDINGS_FILE));
    const summary = field(data, "summary");
    const modules = arrayField(data, "modules");
    const withFindings = modules
        .map((entry) => ({ module: stringField(entry, "module"), total: numberField(entry, "total", 0) }))
        .filter((entry) => entry.total > 0)
        .toSorted((left, right) => right.total - left.total);
    return {
        byKind: countMap(field(summary, "byKind")),
        bySeverity: countMap(field(summary, "bySeverity")),
        modules: numberField(summary, "modules", modules.length),
        modulesWithFindings: withFindings.length,
        topModules: withFindings.slice(0, TOP_MODULES),
        total: numberField(summary, "findings", 0),
    };
};
```
