core/loaders/readme.loader.ts

core/loaders/readme.loader.ts is a file in Bane's Lab Content. 113 lines of code and 22 definitions.

import {
    DIAGRAM_KIND,
    EXHIBIT_PAGES,
    LESSON_KIND,
    PAYLOAD_BLOCKS_KEY,
    PAYLOAD_DESCRIPTION_KEY,
    PAYLOAD_DIAGRAM_KEY,
    PAYLOAD_INTRO_KEY,
    PAYLOAD_META_KEY,
    PAYLOAD_PRINCIPLE_KEY,
    PAYLOAD_PROBLEM_KEY,
    PAYLOAD_SUBSECTIONS_KEY,
    PAYLOAD_SUBTITLE_KEY,
    PAYLOAD_TEXT_KEY,
} from "#configuration/constants/readme.constants";
import { FAQ_PAGE, METHODOLOGY_PAGE } from "@banes-lab/web/core/ids/page.ids.ts";
import {
    PAYLOAD_ID_KEY,
    PAYLOAD_KIND_KEY,
    PAYLOAD_LABEL_KEY,
    PAYLOAD_SECTIONS_KEY,
    PAYLOAD_TITLE_KEY,
} from "#configuration/constants/leak.constants";
import type {
    ReadmeInputs,
    ReadmeLesson,
    ReadmePage,
    ReadmeSection,
    ReadmeSubsection,
    ReadmeTab,
} from "#types/readme.types";
import { contentOf, isRecord, listAt, tabsIn, textAt } from "#core/selectors/payload.selector";
import { payloadFileOf } from "#core/loaders/payload.loader";
import { readJsonOrNull } from "#core/persistence/report.persistence";

const lessonsOf = function lessonsOf(blocks: readonly Record<string, unknown>[]): ReadmeLesson[] {
    return blocks.flatMap((block) => {
        const problem = textAt(block, PAYLOAD_PROBLEM_KEY);
        const principle = textAt(block, PAYLOAD_PRINCIPLE_KEY);
        return block[PAYLOAD_KIND_KEY] === LESSON_KIND && problem !== null && principle !== null
            ? [{ principle, problem }]
            : [];
    });
};

const subsectionOf = function subsectionOf(record: Record<string, unknown>): ReadmeSubsection {
    return { content: textAt(record, PAYLOAD_TEXT_KEY), title: textAt(record, PAYLOAD_TITLE_KEY) ?? "" };
};

const diagramOf = function diagramOf(blocks: readonly Record<string, unknown>[]): string | null {
    const block = blocks.find((candidate) => candidate[PAYLOAD_KIND_KEY] === DIAGRAM_KIND);
    return block === undefined ? null : textAt(block, PAYLOAD_DIAGRAM_KEY);
};

const sectionOf = function sectionOf(record: Record<string, unknown>): ReadmeSection {
    const subsections = listAt(record, PAYLOAD_SUBSECTIONS_KEY);
    const blocks = [
        ...listAt(record, PAYLOAD_BLOCKS_KEY),
        ...subsections.flatMap((sub) => listAt(sub, PAYLOAD_BLOCKS_KEY)),
    ];
    return {
        diagram: diagramOf(blocks),
        id: textAt(record, PAYLOAD_ID_KEY) ?? "",
        intro: textAt(record, PAYLOAD_INTRO_KEY),
        lessons: lessonsOf(blocks),
        subsections: subsections.map(subsectionOf),
        title: textAt(record, PAYLOAD_TITLE_KEY) ?? "",
    };
};

const tabOf = function tabOf(record: Record<string, unknown>): ReadmeTab {
    return {
        id: textAt(record, PAYLOAD_ID_KEY) ?? "",
        label: textAt(record, PAYLOAD_LABEL_KEY) ?? "",
        sections: listAt(record, PAYLOAD_SECTIONS_KEY).map(sectionOf),
    };
};

const tabsOf = function tabsOf(content: Record<string, unknown>, page: string): ReadmeTab[] {
    const tabs = tabsIn(content);
    if (tabs.length > 0) {
        return tabs.map(tabOf);
    }
    return [{ id: page, label: page, sections: listAt(content, PAYLOAD_SECTIONS_KEY).map(sectionOf) }];
};

export const readStructuredPage = function readStructuredPage(page: string): ReadmePage | null {
    const parsed = readJsonOrNull(payloadFileOf(page));
    const content = contentOf(parsed);
    if (!isRecord(parsed) || content === null) {
        return null;
    }
    return {
        description: textAt(parsed, PAYLOAD_DESCRIPTION_KEY) ?? "",
        page,
        tabs: tabsOf(content, page),
        title: textAt(parsed, PAYLOAD_LABEL_KEY) ?? "",
    };
};

const metaOf = function metaOf(page: string, key: string): string {
    const content = contentOf(readJsonOrNull(payloadFileOf(page)));
    const meta = content === null ? null : content[PAYLOAD_META_KEY];
    return isRecord(meta) ? (textAt(meta, key) ?? "") : "";
};

export const readmeInputsOf = function readmeInputsOf(): ReadmeInputs | null {
    const methodology = readStructuredPage(METHODOLOGY_PAGE);
    const faq = readStructuredPage(FAQ_PAGE);
    const exhibits = EXHIBIT_PAGES.map(readStructuredPage);
    const present = exhibits.filter((page): page is ReadmePage => page !== null);
    if (methodology === null || faq === null || present.length !== exhibits.length) {
        return null;
    }
    return {
        exhibits: present,
        faq,
        heading: metaOf(METHODOLOGY_PAGE, PAYLOAD_TITLE_KEY),
        methodology,
        subtitle: metaOf(METHODOLOGY_PAGE, PAYLOAD_SUBTITLE_KEY),
    };
};