# core/loaders/catalog.loader.ts

> 46 lines of code and 9 definitions.

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

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

## Definitions

- `emptyQuality` (lexical_declaration, line 15)
- `collectQuality` (lexical_declaration, line 29, exported)
- `tallyBy` (lexical_declaration, line 7)
- `counts` (lexical_declaration, line 8)
- `rawRules` (lexical_declaration, line 30, exported)
- `rules` (lexical_declaration, line 31, exported)
- `byEcosystem` (lexical_declaration, line 35, exported)
- `byTool` (lexical_declaration, line 36, exported)
- `conceptIndex` (lexical_declaration, line 37, exported)

## Contained in

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

## Uses

- [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/selectors](https://banes-lab.com/anatomy/stats/folder-stats-core-selectors.md)

## Source

```typescript
import { arrayField, stringField } from "#core/selectors/field.selector";
import type { QualityStats } from "#types/catalog.types";
import path from "node:path";
import { readJson } from "#core/loaders/data.loader";
import { relativePath } from "@ssot/paths";

const tallyBy = function tallyBy(rules: readonly unknown[], key: string): Map<string, number> {
    const counts = new Map<string, number>();
    for (const bucket of rules.map((rule) => stringField(rule, key)).filter((value) => value.length > 0)) {
        counts.set(bucket, (counts.get(bucket) ?? 0) + 1);
    }
    return counts;
};

const emptyQuality = function emptyQuality(): QualityStats {
    return {
        available: false,
        byEcosystem: new Map(),
        byTool: new Map(),
        canonicalMapped: 0,
        concepts: 0,
        ecosystems: 0,
        producer: relativePath("govlab.quality"),
        tools: 0,
        totalRules: 0,
    };
};

export const collectQuality = function collectQuality(root: string): QualityStats {
    const rawRules = readJson(path.join(root, relativePath("govlab.quality.generated.rules")));
    const rules: unknown[] = Array.isArray(rawRules) ? rawRules : [];
    if (rules.length === 0) {
        return emptyQuality();
    }
    const byEcosystem = tallyBy(rules, "ecosystem");
    const byTool = tallyBy(rules, "tool");
    const conceptIndex = readJson(path.join(root, relativePath("govlab.quality.generated.concepts")));
    return {
        available: true,
        byEcosystem,
        byTool,
        canonicalMapped: rules.filter((rule) => arrayField(rule, "canonical").length > 0).length,
        concepts: arrayField(conceptIndex, "concepts").length,
        ecosystems: byEcosystem.size,
        producer: relativePath("govlab.quality"),
        tools: byTool.size,
        totalRules: rules.length,
    };
};
```
