# core/stores/architecture.store.ts

> 77 lines of code and 15 definitions.

Tree: GovLab Context
Language: typescript
Layer: application
Canonical: https://banes-lab.com/anatomy/context#file-context-core-stores-architecture-store-ts
Source text: https://banes-lab.com/source/context/core/stores/architecture.store.ts.txt

Listed in [core/stores](https://banes-lab.com/api/source/context/core/stores.md), after [core/stores/algorithm.store.ts](https://banes-lab.com/source/context/core/stores/algorithm.store.ts.md) and before [core/stores/check.store.ts](https://banes-lab.com/source/context/core/stores/check.store.ts.md).

## Definitions

- `dedupeEdges` (lexical_declaration, line 23)
- `base` (lexical_declaration, line 47, exported)
- `constructor` (method_definition, line 39, exported)
- `flatEdge` (lexical_declaration, line 62, exported)
- `edgesOf` (lexical_declaration, line 19)
- `seen` (lexical_declaration, line 24)
- `out` (lexical_declaration, line 25)
- `key` (lexical_declaration, line 27)
- `ArchitectureStore` (class_declaration, line 36, exported)
- `resolveId` (public_field_definition, line 37, exported)
- `aliasByKey` (lexical_declaration, line 48, exported)
- `resolve` (public_field_definition, line 57, exported)
- `selected` (lexical_declaration, line 58, exported)
- `resolveEdge` (lexical_declaration, line 61, exported)
- `validateOntology` (public_field_definition, line 82, exported)

## Contained in

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

## Uses

- [core/converters/identifier.converter.ts](https://banes-lab.com/source/context/core/converters/identifier.converter.ts.md)
- [core/loaders/architecture.loader.ts](https://banes-lab.com/source/context/core/loaders/architecture.loader.ts.md)

## Linked from

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

## Source

```typescript
import { ARCHITECTURE_LABEL, COLLECTIONS } from "#configuration/constants/ontology.constants";
import type {
    ArchRelations,
    ArchRelationsOptions,
    EdgeRelation,
    Principle,
    PrincipleEdge,
    PrincipleFilter,
    ResolveResult,
} from "#types/architecture.types";
import { EDGE_FIELDS, ID_EDGE_PREFIX, LABEL_EDGE_PREFIX } from "#configuration/constants/architecture.constants";
import type { Edge, OntologyIssues } from "#types/ontology.types";
import { BaseOntology } from "#core/stores/ontology.store";
import { ReadAudit } from "#core/observers/record.observer";
import { loadPrinciples } from "#core/loaders/architecture.loader";
import { matchesPrinciple } from "#core/matchers/architecture.matcher";
import { slugify } from "#core/converters/identifier.converter";

const edgesOf = function edgesOf(principle: Principle): Edge[] {
    return EDGE_FIELDS.map(({ field, relation }) => ({ relation, targets: principle[field] }));
};

const dedupeEdges = function dedupeEdges(edges: PrincipleEdge[]): PrincipleEdge[] {
    const seen = new Set<string>();
    const out: PrincipleEdge[] = [];
    for (const edge of edges) {
        const key = typeof edge === "string" ? `${LABEL_EDGE_PREFIX}${edge}` : `${ID_EDGE_PREFIX}${edge.id}`;
        if (!seen.has(key)) {
            seen.add(key);
            out.push(edge);
        }
    }
    return out;
};

export class ArchitectureStore extends BaseOntology<Principle, PrincipleFilter> implements ArchRelations {
    private readonly resolveId: (term: string) => string;

    public constructor(options: ArchRelationsOptions = {}, audit = new ReadAudit(COLLECTIONS.architecture)) {
        super(loadPrinciples(audit, options.data), {
            audit,
            idOf: (principle) => principle.id,
            label: ARCHITECTURE_LABEL,
            logger: options.logger,
            matches: matchesPrinciple,
        });
        const base = options.canonicalizeId ?? slugify;
        const aliasByKey = new Map<string, string>();
        for (const principle of this.all()) {
            for (const label of [principle.name, ...(principle.aliases ?? [])]) {
                aliasByKey.set(slugify(label), principle.id);
            }
        }
        this.resolveId = (term): string => aliasByKey.get(slugify(term)) ?? base(term);
    }

    public resolve = (ids: string[]): ResolveResult => {
        const selected = ids
            .map((id) => this.get(id))
            .filter((principle): principle is Principle => principle !== null);
        const resolveEdge = (target: string): PrincipleEdge => this.get(this.resolveId(target)) ?? target;
        const flatEdge = (field: EdgeRelation): PrincipleEdge[] =>
            dedupeEdges(selected.flatMap((principle) => principle[field]).map(resolveEdge));
        return {
            edges: {
                conflictsWith: flatEdge("conflicts_with"),
                enables: flatEdge("enables"),
                reinforces: flatEdge("reinforces"),
                requires: flatEdge("requires"),
                tensionsWith: flatEdge("tensions_with"),
            },
            principles: selected,
            refactorRecipes: selected.map((principle) => ({
                detectedBy: principle.detected_by,
                id: principle.id,
                refactoredBy: principle.refactored_by,
                violatedBy: principle.violated_by ?? [],
            })),
        };
    };

    public validateOntology = (): OntologyIssues => this.validateEdges(edgesOf, this.resolveId);
}
```
