# core/converters/canon.concept.converter.ts

> 90 lines of code and 23 definitions.

Tree: GovLab Quality
Language: typescript
Layer: processing
Canonical: https://banes-lab.com/anatomy/quality#file-quality-core-converters-canon-concept-converter-ts
Source text: https://banes-lab.com/source/quality/core/converters/canon.concept.converter.ts.txt

Listed in [core/converters](https://banes-lab.com/api/source/quality/core/converters.md), after [core/converters/access.converter.ts](https://banes-lab.com/source/quality/core/converters/access.converter.ts.md) and before [core/converters/canon.converter.ts](https://banes-lab.com/source/quality/core/converters/canon.converter.ts.md).

## Definitions

- `canonicalOf` (lexical_declaration, line 19)
- `knobEntry` (lexical_declaration, line 40)
- `plainEntry` (lexical_declaration, line 56)
- `entryForTool` (lexical_declaration, line 63)
- `groupByConcept` (lexical_declaration, line 24)
- `Grouped` (interface_declaration, line 7)
- `ByTool` (type_alias_declaration, line 12)
- `Base` (interface_declaration, line 14)
- `{ canonical }` (lexical_declaration, line 20)
- `tool` (lexical_declaration, line 27)
- `byTool` (lexical_declaration, line 29)
- `grouped` (lexical_declaration, line 30)
- `common` (lexical_declaration, line 57)
- `ruleIds` (lexical_declaration, line 68)
- `ecosystems` (lexical_declaration, line 69)
- `base` (lexical_declaration, line 70)
- `mappingConcepts` (lexical_declaration, line 75, exported)
- `dimensionOf` (lexical_declaration, line 80, exported)
- `byConcept` (lexical_declaration, line 81, exported)
- `out` (lexical_declaration, line 82, exported)
- `knob` (lexical_declaration, line 84, exported)
- `valueType` (lexical_declaration, line 85, exported)
- `entries` (lexical_declaration, line 86, exported)

## Contained in

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

## Linked from

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

## Source

```typescript
import type { CatalogRule, ConceptEntry } from "#types/catalog.types";
import type { ConceptKnob, KnobConcept, MappingConcept, MappingEntry } from "#types/canon.types";
import { stringArrayField, stringField } from "#core/selectors/record.selector";
import { TOGGLE_KNOB } from "#configuration/constants/emitter.constants";
import { TOGGLE_VALUE_TYPE } from "#configuration/constants/canon.constants";

interface Grouped {
    ecosystems: Set<string>;
    ruleIds: Set<string>;
}

type ByTool = Map<string, Grouped>;

interface Base {
    lang: string[] | string;
    ruleIds: string[];
}

const canonicalOf = function canonicalOf(rule: CatalogRule): string[] {
    const { canonical } = rule;
    return typeof canonical === "string" ? [canonical] : stringArrayField(rule, "canonical");
};

const groupByConcept = function groupByConcept(rules: readonly CatalogRule[]): Map<string, ByTool> {
    const byConcept = new Map<string, ByTool>();
    for (const rule of rules) {
        const tool = stringField(rule, "tool");
        for (const concept of canonicalOf(rule)) {
            const byTool = byConcept.get(concept) ?? new Map<string, Grouped>();
            const grouped = byTool.get(tool) ?? { ecosystems: new Set<string>(), ruleIds: new Set<string>() };
            grouped.ecosystems.add(stringField(rule, "ecosystem"));
            grouped.ruleIds.add(rule.ruleId);
            byTool.set(tool, grouped);
            byConcept.set(concept, byTool);
        }
    }
    return byConcept;
};

const knobEntry = function knobEntry(knob: ConceptKnob, base: Base, tool: string): MappingEntry {
    return {
        default: knob.default === undefined ? null : knob.default,
        fidelity: knob.fidelity,
        knob: knob.knob,
        lang: base.lang,
        provenance: knob.provenance,
        ruleCount: base.ruleIds.length,
        ruleIds: base.ruleIds,
        tool,
        verified: "doc-only",
        ...(knob.fixed === true ? { fixed: true } : {}),
        ...(knob.variant === undefined || knob.variant === "" ? {} : { variant: knob.variant }),
    };
};

const plainEntry = function plainEntry(base: Base, tool: string, valueType: string): MappingEntry {
    const common = { lang: base.lang, ruleCount: base.ruleIds.length, ruleIds: base.ruleIds, tool };
    return valueType === TOGGLE_VALUE_TYPE
        ? { ...common, fidelity: "exact", knob: TOGGLE_KNOB, verified: "doc-only" }
        : { ...common, fidelity: null, knob: null, knobStatus: "undiscovered", verified: "unverified" };
};

const entryForTool = function entryForTool(
    tool: string,
    grouped: Grouped,
    concept: { knob: KnobConcept | undefined; valueType: string },
): MappingEntry {
    const ruleIds = [...grouped.ruleIds].toSorted((a, b) => a.localeCompare(b));
    const ecosystems = [...grouped.ecosystems].toSorted((a, b) => a.localeCompare(b));
    const base = { lang: ecosystems.length === 1 ? (ecosystems[0] ?? "") : ecosystems, ruleIds };
    const knob = concept.knob?.tools[tool];
    return knob ? knobEntry(knob, base, tool) : plainEntry(base, tool, concept.valueType);
};

export const mappingConcepts = function mappingConcepts(
    rules: readonly CatalogRule[],
    concepts: readonly ConceptEntry[],
    knobs: Readonly<Record<string, KnobConcept>>,
): Map<string, MappingConcept> {
    const dimensionOf = new Map(concepts.map((concept) => [concept.id, concept.dimension]));
    const byConcept = groupByConcept(rules);
    const out = new Map<string, MappingConcept>();
    for (const id of [...byConcept.keys()].toSorted((a, b) => a.localeCompare(b))) {
        const knob = knobs[id];
        const valueType = knob ? knob.valueType : TOGGLE_VALUE_TYPE;
        const entries = [...(byConcept.get(id) ?? [])]
            .map(([tool, grouped]) => entryForTool(tool, grouped, { knob, valueType }))
            .toSorted((a, b) => b.ruleCount - a.ruleCount);
        out.set(id, {
            dimension: dimensionOf.get(id) ?? "unknown",
            entries,
            ruleCount: entries.reduce((sum, entry) => sum + entry.ruleCount, 0),
            toolCount: entries.length,
            valueType,
            ...(knob?.enum === undefined || knob.enum === null ? {} : { enum: knob.enum }),
        });
    }
    return out;
};
```
