core/persistence/catalog.persistence.ts
core/persistence/catalog.persistence.ts is a file in GovLab Quality. 52 lines of code and 15 definitions.
import type { CatalogProduct, CatalogWriter, KnobEntry } from "#types/catalog.types";
import { existsSync, readFileSync } from "node:fs";
import { writeCanonicalJson, writeCanonicalText, writeGeneratedMarkdown } from "@govlab/canonical-write";
import { absolutePath } from "@ssot/paths";
import { byRuleId } from "#core/comparators/rule.comparator";
import { govlabPrettierConfig } from "#core/adapters/tool.prettier.adapter";
import { isRecord } from "#core/selectors/record.selector";
import path from "node:path";
const SORT_LOCALE = "en";
const PRODUCT_SUFFIX = ".generated.json";
const KNOB_FILE = "knobs.generated.json";
export const catalogWriter = async function catalogWriter(): Promise<CatalogWriter> {
const base = await govlabPrettierConfig(process.cwd());
return {
json: async (file, data): Promise<void> => {
await writeCanonicalJson(file, data, base);
},
markdown: async (file, text): Promise<void> => {
await writeGeneratedMarkdown(file, text, base);
},
text: async (file, text): Promise<void> => {
await writeCanonicalText(file, text, base);
},
};
};
export const productFile = function productFile(source: string): string {
return path.join(absolutePath("govlab.quality.catalog.generated"), `${source}${PRODUCT_SUFFIX}`);
};
export const writeProduct = async function writeProduct(writer: CatalogWriter, product: CatalogProduct): Promise<void> {
const rules = product.rules.toSorted(byRuleId);
await writer.json(productFile(product.source), { rules, summary: product.summary });
};
const knobFile = function knobFile(): string {
return absolutePath("govlab.quality.generated", KNOB_FILE);
};
export const readKnobs = function readKnobs(): Record<string, unknown> {
const file = knobFile();
const parsed: unknown = existsSync(file) ? JSON.parse(readFileSync(file, "utf8")) : {};
return isRecord(parsed) ? parsed : {};
};
export const writeKnobs = async function writeKnobs(
writer: CatalogWriter,
refreshed: ReadonlyMap<string, KnobEntry[]>,
): Promise<void> {
const merged = { ...readKnobs(), ...Object.fromEntries(refreshed) };
const sorted = Object.fromEntries(
Object.keys(merged)
.toSorted((a, b) => a.localeCompare(b, SORT_LOCALE))
.map((name) => [name, merged[name]]),
);
await writer.json(knobFile(), sorted);
};