core/converters/catalog.converter.ts
core/converters/catalog.converter.ts is a file in Bane's Lab Build Scripts. 129 lines of code and 32 definitions.
import { ADDRESS_GROUP_TITLES, COLLECTION_TITLES, addressGroupTitle } from "@banes-lab/web/strings/catalog.strings";
import {
CANONICAL_FORM,
IDS_TITLE,
NO_MANIFEST_HEAD,
indexPartTitle,
untitledGroup,
} from "#configuration/strings/catalog.strings";
import { CATALOG_VERSION, INDEX_KIND, INDEX_PART_BUDGET } from "#configuration/constants/catalog.constants";
import type { Entry, Identity, Leaf, SiteBuild, SiteParts } from "#types/catalog.types";
import { idsIndex, idsShard, indexPart, localAddress, siteIndex } from "#core/resolvers/catalog.resolver";
import type { Discovery } from "#types/site.types";
import type { RouteLedger } from "#types/route.types";
import { grammarRows } from "#core/converters/catalog.grammar.converter";
import { groupedBy } from "#core/converters/base.converter";
import { latestStamp } from "#core/converters/route.converter";
import { packedParts } from "#core/stores/catalog.store";
import { renderSiteIndex } from "#core/formatters/index.formatter";
import { trainingConsent } from "#configuration/strings/site.strings";
const SITE_REF = "api:";
const IDS_REF = "api:ids";
const IDS_SHARD_PREFIX = "api:ids/";
const PART_REF_MARK = "/";
const REF_SEPARATOR = ":";
const ID_COLUMNS = ["ref", "kind", "title", "summary", "json", "markdown", "bytes", "fingerprint"] as const;
const groupOf = function groupOf(entry: Entry): string {
return entry.ref.slice(0, entry.ref.indexOf(REF_SEPARATOR));
};
const groupNameOf = function groupNameOf(group: string): string {
const collection = COLLECTION_TITLES.get(group);
const name = collection === undefined ? ADDRESS_GROUP_TITLES.get(group) : collection.toLowerCase();
if (name === undefined) {
throw new Error(untitledGroup(group));
}
return name;
};
const rowOf = function rowOf(entry: Entry): readonly unknown[] {
return [
entry.ref,
entry.kind,
entry.title,
entry.summary,
entry.json,
entry.markdown,
entry.bytes,
entry.fingerprint,
];
};
interface IdsShard {
readonly count: number;
readonly group: string;
readonly leaf: Leaf;
}
const groupShards = function groupShards(group: string, members: readonly Entry[]): readonly IdsShard[] {
const parts = packedParts(members, INDEX_PART_BUDGET);
const groupTitle = addressGroupTitle(groupNameOf(group));
return parts.map((rows, index): IdsShard => {
const single = parts.length === 1;
const part = index + 1;
const ref = IDS_SHARD_PREFIX + group + (single ? "" : PART_REF_MARK + String(part));
const title = single ? groupTitle : indexPartTitle(groupTitle, part, parts.length);
const address = single ? idsShard(group) : indexPart(idsShard(group), String(part));
const leaf: Leaf = {
data: { columns: ID_COLUMNS, count: rows.length, group, ref, rows: rows.map(rowOf), title },
identity: { address, href: null, kind: INDEX_KIND, ref, summary: null, title },
markdown: null,
};
return { count: rows.length, group, leaf };
});
};
export const idsLeaves = function idsLeaves(entries: readonly Entry[], site: string): readonly Leaf[] {
const grouped = [...groupedBy(entries, groupOf).entries()].flatMap(([group, members]) =>
groupShards(group, members),
);
const shards = grouped.map((shard) => shard.leaf);
const listed = grouped.map(({ count, group, leaf }) => ({ count, group, json: site + leaf.identity.address.json }));
const kinds = [...new Set([...entries, ...shards.map((shard) => shard.identity)].map((entry) => entry.kind))];
const head: Leaf = {
data: {
count: entries.length,
kinds: kinds.toSorted((left, right) => left.localeCompare(right)),
ref: IDS_REF,
shards: listed,
title: IDS_TITLE,
},
identity: { address: idsIndex(), href: null, kind: INDEX_KIND, ref: IDS_REF, summary: null, title: IDS_TITLE },
markdown: null,
};
return [...shards, head];
};
export const siteBuildOf = function siteBuildOf(
entries: readonly Entry[],
ledger: RouteLedger,
site: string,
): SiteBuild {
const head = entries.find((entry) => entry.ref === IDS_REF);
if (head === undefined) {
throw new Error(NO_MANIFEST_HEAD);
}
return {
build: head.fingerprint,
published: entries.map((entry) => localAddress(site, entry.json)),
updated: latestStamp(ledger),
version: CATALOG_VERSION,
};
};
export const siteLeaf = function siteLeaf(discovery: Discovery, parts: SiteParts, build: SiteBuild): Leaf {
const { published, ...stamp } = build;
const identity: Identity = {
address: siteIndex(),
href: "/",
kind: INDEX_KIND,
ref: SITE_REF,
summary: discovery.summary,
title: discovery.name,
};
const data = {
...parts,
...stamp,
canonical: CANONICAL_FORM,
consent: trainingConsent(discovery.consent, discovery.author, discovery.site),
grammar: grammarRows(published),
ref: SITE_REF,
site: discovery.site,
summary: discovery.summary,
title: discovery.name,
};
return { data, identity, markdown: renderSiteIndex(data, discovery.site) };
};