domain/converters/kind.converter.ts

domain/converters/kind.converter.ts is a file in Bane's Lab Site. 161 lines of code and 14 definitions.

import {
    CONCERNS_LABEL,
    DISCRIMINATOR_LABEL,
    DISTINGUISHES_LABEL,
    FORCE_INTRO,
    FORCE_TITLE,
    KINDS_IN_RANGE_LABEL,
    KIND_INTRO,
    KIND_TITLE,
    PRINCIPLES_OF_KIND_LABEL,
    RANGE_CAPTION,
    RANGE_INTRO,
    RANGE_SECTION_TITLE,
    SIGNATURES_LABEL,
    TERMS_OF_KIND_LABEL,
    VOCABULARY_SECTIONS,
} from "#configuration/strings/kind.strings";
import {
    CONTRACTS_LABEL,
    COVERAGE_TITLE,
    PRINCIPLES_LABEL,
    missingVocabularySection,
} from "#configuration/strings/ontology.strings";
import {
    COVERAGE_SUBSECTION_ID,
    FORCE_ANCHOR,
    FORCE_SECTION_ID,
    KIND_ANCHOR,
    KIND_SECTION_ID,
    RANGE_SECTION_ID,
    RELATION_ANCHOR,
    VOCABULARY_ANCHOR,
    VOCABULARY_SECTION_PREFIX,
} from "#core/ids/ontology.ids";
import type { ForceView, KindView, RelationRangeView, VocabularyView } from "#types/ontology.types";
import { HYPHEN, SPACE, UNDERSCORE } from "#configuration/constants/document.constants";
import type { Section, Subsection } from "#types/document.types";
import {
    chips,
    glossary,
    labeled,
    linkList,
    plainList,
    row,
    text,
    wideRow,
} from "#domain/converters/ontology.converter";
import { diagram, edgeLine, node } from "#domain/converters/ontology.graph.converter";
import type { CoverageView } from "#types/coverage.types";
import { DEFINITION_LABEL } from "#configuration/strings/lexicon.strings";
import { EDGE_SOLID } from "#configuration/constants/diagram.constants";
import { KIND_SECTION_ICON } from "#configuration/icons/ontology.icons";
import type { SchemaInput } from "#types/kind.types";
import { coverageRow } from "#domain/converters/coverage.converter";

const HEADER = "flowchart LR";
const RELATION_PREFIX = "relation-";

const kindSubsection = function kindSubsection(kind: KindView): Subsection {
    return {
        blocks: [
            chips([
                labeled(PRINCIPLES_OF_KIND_LABEL, String(kind.principles)),
                labeled(TERMS_OF_KIND_LABEL, String(kind.terms)),
            ]),
            glossary([
                row(DISCRIMINATOR_LABEL, kind.discriminator),
                row(DISTINGUISHES_LABEL, kind.distinguishesFrom),
                row(SIGNATURES_LABEL, plainList(kind.definitionSignatures)),
            ]),
        ],
        id: KIND_ANCHOR + kind.kind,
        title: kind.kind,
    };
};

const kindSection = function kindSection(
    kinds: readonly KindView[],
    resolutionNote: string,
    coverage: readonly CoverageView[],
): Section {
    return {
        blocks: [text(resolutionNote)],
        icon: KIND_SECTION_ICON,
        id: KIND_SECTION_ID,
        intro: KIND_INTRO,
        subsections: [
            ...kinds.map(kindSubsection),
            { blocks: [glossary(coverage.map(coverageRow))], id: COVERAGE_SUBSECTION_ID, title: COVERAGE_TITLE },
        ],
        title: KIND_TITLE,
    };
};

const rangeDiagram = function rangeDiagram(ranges: readonly RelationRangeView[], kinds: readonly KindView[]): string {
    const relationNodes = ranges.map((range) => node(RELATION_PREFIX + range.relation, range.relation));
    const kindNodes = kinds.map((kind) => node(kind.kind, kind.kind));
    const edges = ranges.flatMap((range) =>
        range.kinds.map((kind) => edgeLine(RELATION_PREFIX + range.relation, EDGE_SOLID, kind.label)),
    );
    return diagram(HEADER, [...relationNodes, ...kindNodes, ...edges]);
};

const rangeSection = function rangeSection(ranges: readonly RelationRangeView[], kinds: readonly KindView[]): Section {
    return {
        blocks: [{ caption: RANGE_CAPTION, kind: "mermaid", text: rangeDiagram(ranges, kinds) }],
        icon: KIND_SECTION_ICON,
        id: RANGE_SECTION_ID,
        intro: RANGE_INTRO,
        subsections: ranges.map((range) => ({
            blocks: [glossary([row(KINDS_IN_RANGE_LABEL, linkList(range.kinds))])],
            id: RELATION_ANCHOR + range.relation,
            title: range.relation,
        })),
        title: RANGE_SECTION_TITLE,
    };
};

const forceSubsection = function forceSubsection(force: ForceView): Subsection {
    return {
        blocks: [
            glossary([
                row(CONTRACTS_LABEL, linkList(force.contracts)),
                row(PRINCIPLES_LABEL, linkList(force.principles)),
                ...(force.concerns.length === 0 ? [] : [row(CONCERNS_LABEL, plainList(force.concerns))]),
            ]),
        ],
        id: FORCE_ANCHOR + force.id,
        title: force.force.replaceAll(UNDERSCORE, SPACE),
    };
};

const vocabularySection = function vocabularySection(vocabulary: VocabularyView): Section {
    const copy = VOCABULARY_SECTIONS.get(vocabulary.id);
    if (copy === undefined) {
        throw new Error(missingVocabularySection(vocabulary.id));
    }
    return {
        icon: KIND_SECTION_ICON,
        id: VOCABULARY_SECTION_PREFIX + vocabulary.id,
        intro: copy.intro,
        subsections: vocabulary.entries.map((entry) => ({
            blocks: [
                glossary([wideRow(DEFINITION_LABEL, entry.definition), row(copy.records, linkList(entry.records))]),
            ],
            id: VOCABULARY_ANCHOR + vocabulary.id + HYPHEN + entry.value,
            title: entry.value,
        })),
        title: copy.title,
    };
};

const forceSection = function forceSection(forces: readonly ForceView[]): Section {
    return {
        icon: KIND_SECTION_ICON,
        id: FORCE_SECTION_ID,
        intro: FORCE_INTRO,
        subsections: forces.map(forceSubsection),
        title: FORCE_TITLE,
    };
};

export const kindSections = function kindSections(input: SchemaInput): readonly Section[] {
    return [
        kindSection(input.kinds, input.note, input.coverage),
        ...input.vocabularies.map(vocabularySection),
        rangeSection(input.ranges, input.kinds),
        forceSection(input.forces),
    ];
};