configuration/constants/graph.constants.ts

configuration/constants/graph.constants.ts is a file in Bane's Lab Site. 157 lines of code and 54 definitions.

import {
    AXIS_RELATION,
    CATEGORY_RELATION,
    COMPOSED_BY_RELATION,
    COMPOSES_RELATION,
    CONFLICTS_WITH_RELATION,
    CONTRACTS_RELATION,
    CONTRACT_RELATION,
    DERIVED_BY_RELATION,
    DETECTS_RELATION,
    ENABLES_RELATION,
    FACE_SEPARATOR,
    GROUNDED_BY_RELATION,
    GROUNDS_RELATION,
    PRINCIPLE_RELATION,
    REFACTORED_BY_RELATION,
    REFACTORS_RELATION,
    REINFORCES_RELATION,
    REQUIRES_RELATION,
    STAGE_RELATION,
    TENSIONS_RELATION,
    TENSIONS_WITH_RELATION,
    TERM_RELATION,
    VIOLATED_BY_RELATION,
    VIOLATES_RELATION,
} from "@govlab/constants";
import type { RelationPair, RelationRecord } from "#types/graph.types";
import { ONTOLOGY_PAGE } from "#core/ids/page.ids";

export const LINKS_TO_RELATION = "links-to";
export const LINKED_FROM_RELATION = "linked-from";
export const EVIDENCE_RELATION_ID = "evidence";
export const EVIDENCE_FOR_RELATION = "evidence-for";
export const USES_RELATION = "uses";
export const USED_BY_RELATION = "used-by";
export const CALLS_RELATION_ID = "calls";
const CALLED_BY_RELATION_ID = "called-by";
export const CONTAINS_RELATION = "contains";
export const CONTAINED_IN_RELATION = "contained-in";
export const BUILDS_ON_RELATION = "builds-on";
const PREREQUISITE_OF_RELATION = "prerequisite-of";
const DERIVATION_RELATION = "derivation";
export const CONCEPT_RELATION = "concept";
export const DETECTED_BY_RELATION = "detected-by";
export const REFERENCES_RELATION = "references";
const REFERENCED_FROM_RELATION = "referenced-from";
export const ENFORCED_BY_RELATION = "enforced-by";
const ENFORCES_RELATION = "enforces";
export const GOVERNED_BY_RELATION = "governed-by";
const GOVERNS_RELATION = "governs";
export const CONCERN_RELATION = "concern";
export const CONCERN_LAYER_RELATION = "concern-layer";
const MATH_TYPE_RELATION = "math-type";
const TERM_OF_RELATION = "term-of";
const REQUIRED_BY_RELATION = "required-by";
const REINFORCED_BY_RELATION = "reinforced-by";
const ENABLED_BY_RELATION = "enabled-by";
const NEGATED_BY_RELATION = "negated-by";
export const EXPRESSED_BY_RELATION = "expressed-by";
const EXPRESSES_RELATION = "expresses";

const OF_SUFFIX = "-of";

const pair = function pair(forward: string, reverse: string): RelationRecord {
    return { forward, leaf: false, reverse, rollsUp: false, tooltip: false };
};

const withOf = function withOf(forward: string): RelationRecord {
    return pair(forward, forward + OF_SUFFIX);
};

export const RELATIONS: readonly RelationRecord[] = [
    { ...pair(LINKS_TO_RELATION, LINKED_FROM_RELATION), leaf: true, tooltip: true },
    { ...pair(EVIDENCE_RELATION_ID, EVIDENCE_FOR_RELATION), leaf: true, rollsUp: true, tooltip: true },
    { ...pair(USES_RELATION, USED_BY_RELATION), leaf: true },
    pair(CALLS_RELATION_ID, CALLED_BY_RELATION_ID),
    pair(CONTAINS_RELATION, CONTAINED_IN_RELATION),
    pair(BUILDS_ON_RELATION, PREREQUISITE_OF_RELATION),
    pair(REQUIRES_RELATION, REQUIRED_BY_RELATION),
    pair(REINFORCES_RELATION, REINFORCED_BY_RELATION),
    pair(ENABLES_RELATION, ENABLED_BY_RELATION),
    pair(CONFLICTS_WITH_RELATION, NEGATED_BY_RELATION),
    pair(REFACTORED_BY_RELATION, REFACTORS_RELATION),
    pair(VIOLATED_BY_RELATION, VIOLATES_RELATION),
    pair(EXPRESSED_BY_RELATION, EXPRESSES_RELATION),
    pair(TENSIONS_WITH_RELATION, TENSIONS_WITH_RELATION),
    withOf(TENSIONS_RELATION),
    pair(COMPOSES_RELATION, COMPOSED_BY_RELATION),
    pair(GROUNDS_RELATION, GROUNDED_BY_RELATION),
    pair(DERIVATION_RELATION, DERIVED_BY_RELATION),
    pair(PRINCIPLE_RELATION, CONTRACTS_RELATION),
    { ...pair(DETECTED_BY_RELATION, DETECTS_RELATION), tooltip: true },
    { ...pair(ENFORCED_BY_RELATION, ENFORCES_RELATION), tooltip: true },
    { ...pair(REFERENCES_RELATION, REFERENCED_FROM_RELATION), rollsUp: true },
    { ...pair(GOVERNED_BY_RELATION, GOVERNS_RELATION), rollsUp: true },
    { ...withOf(CONCERN_RELATION), rollsUp: true },
    { ...withOf(CONCERN_LAYER_RELATION), rollsUp: true },
    pair(TERM_RELATION, TERM_OF_RELATION),
    pair("subsumes", "subsumed-by"),
    pair("transitions-to", "transitions-from"),
    pair("kinds", "allowed-by"),
    pair(CATEGORY_RELATION, "members"),
    withOf(AXIS_RELATION),
    withOf(STAGE_RELATION),
    withOf(MATH_TYPE_RELATION),
    withOf(CONTRACT_RELATION),
    withOf("domain"),
    withOf("force"),
    withOf("layer"),
    withOf("primary-math-type"),
    withOf(CONCEPT_RELATION),
    withOf("dimension"),
    withOf("invariant"),
    withOf("lens"),
    withOf("universal-axis"),
    withOf("techniques"),
    withOf("math-domains"),
    withOf("sequence"),
];

export const RELATION_PAIRS: readonly RelationPair[] = RELATIONS.map(({ forward, reverse }) => ({ forward, reverse }));

export const TOOLTIP_RELATIONS: ReadonlySet<string> = new Set(
    RELATIONS.filter((relation) => relation.tooltip).flatMap((relation) => [relation.forward, relation.reverse]),
);

export const ROLLED_UP_RELATIONS: ReadonlySet<string> = new Set(
    RELATIONS.filter((relation) => relation.rollsUp).map((relation) => relation.reverse),
);

export const LEAF_RELATIONS: readonly RelationRecord[] = RELATIONS.filter((relation) => relation.leaf);

const CHAPTER_COLLECTION = "chapter";
const PATH_MARK = "/";
const FRAGMENT_MARK = "#";
const SNAKE_MARK = "_";
const KEBAB_MARK = "-";

const LISTING_PAGES: ReadonlySet<string> = new Set([ONTOLOGY_PAGE]);

export const chunkKeyOf = function chunkKeyOf(ref: string): string {
    const collection = ref.slice(0, ref.indexOf(FACE_SEPARATOR));
    if (collection !== CHAPTER_COLLECTION) {
        return collection;
    }
    const path = ref.slice(collection.length + FACE_SEPARATOR.length + PATH_MARK.length);
    const ends = [path.indexOf(PATH_MARK), path.indexOf(FRAGMENT_MARK)].filter((at) => at !== -1);
    return collection + KEBAB_MARK + path.slice(0, ends.length === 0 ? path.length : Math.min(...ends));
};

export const isListingRef = function isListingRef(ref: string): boolean {
    return [...LISTING_PAGES].some((page) => chunkKeyOf(ref) === CHAPTER_COLLECTION + KEBAB_MARK + page);
};

export const relationId = function relationId(spelling: string): string {
    let kebab = "";
    for (const character of spelling) {
        const lower = character.toLowerCase();
        if (character === SNAKE_MARK) {
            kebab += KEBAB_MARK;
        } else if (lower === character) {
            kebab += character;
        } else {
            kebab += KEBAB_MARK + lower;
        }
    }
    return kebab;
};

export const reverseOf = function reverseOf(relation: string): string | null {
    return RELATION_PAIRS.find((entry) => entry.forward === relation)?.reverse ?? null;
};