core/normalizers/algorithm.normalizer.ts
core/normalizers/algorithm.normalizer.ts is a file in GovLab Context. 91 lines of code and 19 definitions.
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 } : {}),
};
};