# core/normalizers/algorithm.normalizer.ts

> 91 lines of code and 19 definitions.

Tree: GovLab Context
Language: typescript
Layer: processing
Canonical: https://banes-lab.com/anatomy/context#file-context-core-normalizers-algorithm-normalizer-ts
Source text: https://banes-lab.com/source/context/core/normalizers/algorithm.normalizer.ts.txt

Listed in [core/normalizers](https://banes-lab.com/api/source/context/core/normalizers.md), before [core/normalizers/architecture.normalizer.ts](https://banes-lab.com/source/context/core/normalizers/architecture.normalizer.ts.md).

## Definitions

- `baseContract` (lexical_declaration, line 36)
- `typedFieldsOf` (lexical_declaration, line 53)
- `asProductions` (lexical_declaration, line 19)
- `listFieldsOf` (lexical_declaration, line 62)
- `normalizeContract` (lexical_declaration, line 77, exported)
- `asDerivationMap` (lexical_declaration, line 25)
- `BaseContract` (type_alias_declaration, line 31)
- `TypedFields` (type_alias_declaration, line 50)
- `ListFields` (type_alias_declaration, line 51)
- `grounds` (lexical_declaration, line 63)
- `derivationMap` (lexical_declaration, line 64)
- `distinctFrom` (lexical_declaration, line 65)
- `canon` (lexical_declaration, line 66)
- `aliases` (lexical_declaration, line 67)
- `title` (lexical_declaration, line 84, exported)
- `tier` (lexical_declaration, line 85, exported)
- `check` (lexical_declaration, line 86, exported)
- `principleRef` (lexical_declaration, line 87, exported)
- `exemplar` (lexical_declaration, line 88, exported)

## Contained in

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

## Uses

- [core/converters/identifier.converter.ts](https://banes-lab.com/source/context/core/converters/identifier.converter.ts.md)
- [core/normalizers/field.normalizer.ts](https://banes-lab.com/source/context/core/normalizers/field.normalizer.ts.md)
- [core/validators/field.validator.ts](https://banes-lab.com/source/context/core/validators/field.validator.ts.md)

## Linked from

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

## Source

```typescript
import { ALGO_SCHEMA, CONTRACT_KIND } from "#configuration/schemas/algorithm.schema";
import { ALGO_SUBJECT, DOMAIN_TIER_VALUES, TIER_KEY } from "#configuration/constants/algorithm.constants";
import type { Contract, DerivationMapEntry, Production } from "#types/algorithm.types";
import { asCheck, mergeCheck } from "#core/converters/check.converter";
import {
    asClosed,
    asDistinctFrom,
    asExemplar,
    asString,
    asStringArray,
    optionalString,
} from "#core/normalizers/field.normalizer";
import type { CheckFacet } from "#types/check.types";
import { isObject } from "#core/predicates/record.predicate";
import { refuseRecord } from "#core/validators/field.validator";
import { slugify } from "#core/converters/identifier.converter";
import { tierOf } from "#configuration/strings/algorithm.strings";

const asProductions = function asProductions(value: unknown): Production[] {
    return (Array.isArray(value) ? value : [])
        .filter(isObject)
        .map((entry) => ({ lhs: asString(entry["lhs"]), rhs: asString(entry["rhs"]) }));
};

const asDerivationMap = function asDerivationMap(value: unknown): DerivationMapEntry[] {
    return (Array.isArray(value) ? value : [])
        .filter(isObject)
        .map((entry) => ({ record: asString(entry["record"]), stage: asString(entry["stage"]) }));
};

type BaseContract = Pick<
    Contract,
    "composes" | "domain" | "flow" | "force" | "id" | "intent" | "invariant" | "productions" | "title"
>;

const baseContract = function baseContract(raw: Record<string, unknown>, domain: string, title: string): BaseContract {
    return {
        composes: asStringArray(raw["composes"]),
        domain,
        flow: asStringArray(raw["flow"]),
        force: asStringArray(raw["force"]),
        id: asString(raw["id"]) || slugify(title),
        intent: asString(raw["intent"]),
        invariant: asString(raw["invariant"]),
        productions: asProductions(raw["productions"]),
        title,
    };
};

type TypedFields = Pick<Contract, "axis" | "mathType" | "stage" | "yields">;
type ListFields = Pick<Contract, "aliases" | "canon" | "derivationMap" | "distinctFrom" | "grounds">;

const typedFieldsOf = function typedFieldsOf(raw: Record<string, unknown>): TypedFields {
    return {
        ...optionalString(raw, "stage"),
        ...optionalString(raw, "axis"),
        ...optionalString(raw, "mathType"),
        ...optionalString(raw, "yields"),
    };
};

const listFieldsOf = function listFieldsOf(raw: Record<string, unknown>): ListFields {
    const grounds = asStringArray(raw["grounds"]);
    const derivationMap = asDerivationMap(raw["derivationMap"]);
    const distinctFrom = asDistinctFrom(raw["distinctFrom"]);
    const canon = asStringArray(raw["canon"]);
    const aliases = asStringArray(raw["aliases"]);
    return {
        ...(aliases.length > 0 ? { aliases } : {}),
        ...(grounds.length > 0 ? { grounds } : {}),
        ...(derivationMap.length > 0 ? { derivationMap } : {}),
        ...(distinctFrom.length > 0 ? { distinctFrom } : {}),
        ...(canon.length > 0 ? { canon } : {}),
    };
};

export const normalizeContract = function normalizeContract(
    raw: Record<string, unknown>,
    domain: string,
    declared: CheckFacet | null,
    group: Record<string, unknown>,
): Contract {
    refuseRecord(ALGO_SUBJECT, CONTRACT_KIND, ALGO_SCHEMA, raw);
    const title = asString(raw["title"]);
    const tier = asClosed(DOMAIN_TIER_VALUES, group[TIER_KEY], tierOf(domain));
    const check = mergeCheck(declared, asCheck(raw["check"]));
    const principleRef = asString(raw["principleRef"]);
    const exemplar = asExemplar(raw["exemplar"]);
    return {
        ...baseContract(raw, domain, title),
        tier,
        ...(principleRef ? { principleRef } : {}),
        ...(raw["meta"] === true ? { meta: true } : {}),
        ...(exemplar ? { exemplar } : {}),
        ...typedFieldsOf(raw),
        ...listFieldsOf(raw),
        ...(check ? { check } : {}),
    };
};
```
