core/converters/source.route.converter.ts

core/converters/source.route.converter.ts is a file in Bane's Lab Build Scripts. 103 lines of code and 20 definitions.

import type { AnatomyFile, AnatomyFolder } from "@banes-lab/web/types/anatomy.types.js";
import type { HeadAlternates, SourceNodeLink, SourceSubject } from "@banes-lab/web/types/page.types.js";
import type { SourceRoute, SourceRouteTools, SourceTree } from "#types/source.types";
import { folderIndex, sourceLeaf, treeIndex } from "#core/resolvers/catalog.resolver";
import { holdsFiles, isPagedFile } from "@banes-lab/web/predicates/folder.predicate";
import { missingAlternate, sourceFileDescription, sourceFolderDescription } from "#configuration/strings/page.strings";
import type { Address } from "#types/catalog.types";
import { summaryOf } from "#core/converters/source.converter";

interface TreeScope {
    readonly tools: SourceRouteTools;
    readonly tree: SourceTree;
}

const alternatesOf = function alternatesOf(address: Address, path: string): HeadAlternates {
    if (address.markdown === null) {
        throw new Error(missingAlternate(path));
    }
    return { json: address.json, markdown: address.markdown };
};

const nameOf = function nameOf(scope: TreeScope, path: string): string {
    const local = scope.tools.localPath(path);
    return local.length === 0 ? scope.tree.label : local;
};

const linkOf = function linkOf(scope: TreeScope, folder: AnatomyFolder): SourceNodeLink {
    return { label: nameOf(scope, folder.path), path: scope.tools.nodeRoute(folder.path, true) };
};

interface Placement {
    readonly parent: SourceNodeLink;
    readonly trail: readonly SourceNodeLink[];
}

const subjectBase = function subjectBase(
    scope: TreeScope,
    path: string,
    repository: string | undefined,
    trail: readonly SourceNodeLink[],
): Omit<SourceSubject, "alternates" | "description" | "language" | "path"> {
    const { tab } = scope.tree;
    return {
        license: scope.tools.license(tab),
        name: nameOf(scope, path),
        repository: repository ?? null,
        tabPath: scope.tools.tabPath(tab),
        tabTitle: scope.tree.label,
        title: scope.tools.sourceTitle(path),
        trail,
    };
};

const fileRoute = function fileRoute(scope: TreeScope, file: AnatomyFile, placement: Placement): SourceRoute {
    const local = scope.tools.localPath(file.path);
    const path = scope.tools.nodeRoute(file.path, false);
    return {
        children: [],
        parent: placement.parent,
        subject: {
            ...subjectBase(scope, file.path, file.repository, placement.trail),
            alternates: alternatesOf(sourceLeaf(scope.tree.tab, local), path),
            description: sourceFileDescription(local, scope.tree.label, summaryOf(file)),
            language: scope.tools.languageOf(file.name),
            path,
        },
        text: file.source,
    };
};

const folderRoute = function folderRoute(scope: TreeScope, folder: AnatomyFolder, placement: Placement): SourceRoute {
    const local = scope.tools.localPath(folder.path);
    const path = scope.tools.nodeRoute(folder.path, true);
    const address = local.length === 0 ? treeIndex(scope.tree.tab) : folderIndex(scope.tree.tab, local);
    const files = folder.files.filter(isPagedFile);
    return {
        children: [
            ...folder.folders.filter(holdsFiles).map((child) => linkOf(scope, child)),
            ...files.map((file) => ({ label: file.name, path: scope.tools.nodeRoute(file.path, false) })),
        ],
        parent: placement.parent,
        subject: {
            ...subjectBase(scope, folder.path, folder.repository, placement.trail),
            alternates: alternatesOf(address, path),
            description: sourceFolderDescription(nameOf(scope, folder.path), scope.tree.label, folder.stats.files),
            language: null,
            path,
        },
        text: null,
    };
};

const routesIn = function routesIn(scope: TreeScope, folder: AnatomyFolder, placement: Placement): SourceRoute[] {
    const own = linkOf(scope, folder);
    const isRoot = scope.tools.localPath(folder.path).length === 0;
    const inside = { parent: own, trail: isRoot ? placement.trail : [...placement.trail, own] };
    return [
        folderRoute(scope, folder, placement),
        ...folder.files.filter(isPagedFile).map((file) => fileRoute(scope, file, inside)),
        ...folder.folders.filter(holdsFiles).flatMap((child) => routesIn(scope, child, inside)),
    ];
};

export const sourceRoutes = function sourceRoutes(
    trees: readonly SourceTree[],
    tools: SourceRouteTools,
): readonly SourceRoute[] {
    return trees.flatMap((tree) => {
        const scope = { tools, tree };
        const top = { label: tree.label, path: tools.tabPath(tree.tab) };
        return routesIn(scope, tree.snapshot.tree, { parent: top, trail: [top] });
    });
};