core/converters/ontology.converter.ts

core/converters/ontology.converter.ts is a file in Bane's Lab Build Scripts. 183 lines of code and 21 definitions.

import {
    ALGO_DOMAIN_FACE,
    ALGO_FACE,
    ARCH_FACE,
    COMPOSED_BY_RELATION,
    CONTRACTS_RELATION,
    DERIVED_BY_RELATION,
    DETECTS_RELATION,
    GROUNDED_BY_RELATION,
    LAYER_FACE,
    LEX_FACE,
    REFERENCED_BY_RELATION,
} from "@govlab/constants";
import { type Contract, type GovlabContext, type Principle, slugify } from "@govlab/context";
import type {
    ContractDomainView,
    ContractView,
    OntologySnapshot,
    PrincipleCategoryView,
    PrincipleView,
} from "@banes-lab/web/types/ontology.types.js";
import type { EdgeRef, EdgeRelation } from "@banes-lab/web/types/link.types.js";
import { SEVERITY_VOCABULARY, TIER_VOCABULARY } from "#configuration/constants/ontology.constants";
import { createResolver, refOf } from "#core/resolvers/ontology.resolver";
import { createReverseIndex, lookup } from "#core/converters/ontology.index.converter";
import { distinctsOf, exemplarOf, groupBy, layerRef, orNull } from "#core/converters/view.converter";
import { forceNames, forcesOf, kindsOf, layersOf, rangesOf } from "#core/converters/layer.converter";
import type { OntologySources } from "#types/ontology.types";
import { grammarOf } from "#core/converters/grammar.converter";
import { reasonOf } from "#core/converters/reason.converter";
import { resolutionOf } from "#core/converters/check.converter";
import { termsOf } from "#core/converters/lexicon.converter";
import { vocabulariesOf } from "#core/converters/ontology.vocabulary.converter";

const edgeRefs = function edgeRefs(
    sources: OntologySources,
    principle: Principle,
    relation: EdgeRelation,
): readonly EdgeRef[] {
    return sources.context.arch
        .resolve([principle.id])
        .edges[relation].map((edge) =>
            typeof edge === "string"
                ? sources.resolve.arch(edge)
                : { label: edge.name, ref: refOf(ARCH_FACE, edge.id) },
        );
};

const tensionsOf = function tensionsOf(sources: OntologySources, principle: Principle): readonly EdgeRef[] {
    return principle.tensions_with.flatMap((target) => {
        const resolution = sources.context.resolveTension(principle.id, target);
        return resolution === null
            ? []
            : [sources.resolve.tension(sources.resolve.arch(resolution.a), sources.resolve.arch(resolution.b))];
    });
};

const termTwin = function termTwin(sources: OntologySources, principle: Principle): EdgeRef | null {
    for (const key of [principle.name, ...(principle.aliases ?? [])]) {
        const term = sources.context.lex.resolve(key);
        if (term !== null) {
            return { label: term.name, ref: refOf(LEX_FACE, term.id) };
        }
    }
    return null;
};

const principleView = function principleView(sources: OntologySources, principle: Principle): PrincipleView {
    const { resolve } = sources;
    return {
        aliases: principle.aliases ?? [],
        canon: principle.canon ?? [],
        category: resolve.archCategory(principle.category),
        contracts: lookup(sources.index, CONTRACTS_RELATION, ARCH_FACE, principle.id),
        definition: principle.definition,
        detectedBy: resolve.labels(principle.detected_by),
        distinctFrom: distinctsOf(principle.distinctFrom, resolve.target),
        edges: {
            conflictsWith: edgeRefs(sources, principle, "conflictsWith"),
            enables: edgeRefs(sources, principle, "enables"),
            reinforces: edgeRefs(sources, principle, "reinforces"),
            requires: edgeRefs(sources, principle, "requires"),
            tensionsWith: edgeRefs(sources, principle, "tensionsWith"),
        },
        enforcedBy: resolve.labels(principle.enforced_by),
        exemplar: exemplarOf(principle.exemplar),
        expressedBy: (principle.expressedBy ?? []).map((target) => resolve.target(target)),
        formedBy: orNull(principle.formed_by),
        id: principle.id,
        kind: resolve.kind(principle.type),
        layer: layerRef(sources, principle.id),
        mandatoryFor: orNull(principle.mandatoryFor),
        measuredBy: resolve.labels(principle.measured_by),
        name: principle.name,
        refactoredBy: principle.refactored_by.map((target) => resolve.target(target)),
        referencedBy: lookup(sources.index, REFERENCED_BY_RELATION, ARCH_FACE, principle.id),
        scope: principle.scope.map((scope) => resolve.force(scope, sources.forces)),
        severity: resolve.vocabulary(SEVERITY_VOCABULARY, principle.severity),
        tensions: tensionsOf(sources, principle),
        term: termTwin(sources, principle),
        violatedBy: (principle.violated_by ?? []).map((target) => resolve.target(target)),
    };
};

const principlesOf = function principlesOf(sources: OntologySources): readonly PrincipleCategoryView[] {
    return groupBy(sources.context.arch.all(), (principle) => principle.category).map(([category, principles]) => ({
        category,
        id: slugify(category),
        principles: principles.map((principle) => principleView(sources, principle)),
    }));
};

const contractView = function contractView(sources: OntologySources, contract: Contract): ContractView {
    const { index, resolve } = sources;
    const principle = contract.principleRef === undefined ? null : resolve.archId(contract.principleRef);
    const isLayer = sources.context.layers().some((layer) => layer.id === contract.id);
    return {
        axis: contract.axis === undefined ? null : resolve.reason(contract.axis),
        canon: contract.canon ?? [],
        composedBy: lookup(index, COMPOSED_BY_RELATION, ALGO_FACE, contract.id),
        composes: contract.composes.map((target) => resolve.algo(target)),
        derivationMap: (contract.derivationMap ?? []).map((entry) => ({
            record: resolve.algo(entry.record),
            stage: resolve.stage(entry.stage),
        })),
        derivedBy: lookup(index, DERIVED_BY_RELATION, ALGO_FACE, contract.id),
        detects: lookup(index, DETECTS_RELATION, ALGO_FACE, contract.id),
        distinctFrom: distinctsOf(contract.distinctFrom, resolve.algo),
        domain: { label: contract.domain, ref: refOf(ALGO_DOMAIN_FACE, slugify(contract.domain)) },
        exemplar: exemplarOf(contract.exemplar),
        flow: contract.flow,
        force: contract.force.map((force) => resolve.force(force, sources.forces)),
        groundedBy: lookup(index, GROUNDED_BY_RELATION, ALGO_FACE, contract.id),
        grounds: (contract.grounds ?? []).map((ground) => resolve.target(ground)),
        id: contract.id,
        intent: contract.intent,
        invariant: contract.invariant,
        layer: isLayer ? { label: contract.title, ref: refOf(LAYER_FACE, contract.id) } : null,
        mathType: contract.mathType === undefined ? null : resolve.reason(contract.mathType),
        meta: contract.meta === true,
        principle,
        productions: contract.productions.map((production) => ({ lhs: production.lhs, rhs: production.rhs })),
        stage: contract.stage === undefined ? null : resolve.stage(contract.stage),
        tier: resolve.vocabulary(TIER_VOCABULARY, contract.tier),
        title: contract.title,
        yields: orNull(contract.yields),
    };
};

const contractsOf = function contractsOf(sources: OntologySources): readonly ContractDomainView[] {
    return groupBy(sources.context.algo.all(), (contract) => contract.domain).map(([domain, contracts]) => ({
        contracts: contracts.map((contract) => contractView(sources, contract)),
        domain,
        id: slugify(domain),
    }));
};

export const snapshotOf = function snapshotOf(context: GovlabContext): OntologySnapshot {
    const resolve = createResolver(context);
    const sources: OntologySources = {
        context,
        forces: forceNames(context),
        index: createReverseIndex(context, resolve),
        resolve,
    };
    const contracts = contractsOf(sources);
    const layers = layersOf(context, resolve);
    const principles = principlesOf(sources);
    const reason = reasonOf(context, resolve, sources.index);
    const terms = termsOf(sources, principles);
    return {
        contracts,
        forces: forcesOf(context, resolve),
        grammar: grammarOf(context, resolve),
        kinds: kindsOf(context),
        layers,
        principles,
        ranges: rangesOf(resolve),
        reason,
        resolution: resolutionOf(context, resolve),
        terms,
        vocabularies: vocabulariesOf({
            contracts,
            principles,
            surfaces: reason.testSurfaces,
            tensions: layers.resolutions,
            terms,
            topology: layers.topology,
        }),
    };
};