core/caches/readme.cache.ts
core/caches/readme.cache.ts is a file in GovLab Docs. 95 lines of code and 23 definitions.
import { DOCS_CACHE_NAME, NO_CACHE_ENV, NO_CACHE_ON } from "#configuration/constants/invocation.constants";
import { MANIFEST_FILE, PACKAGE_FILE, README_FILE } from "#configuration/constants/document.constants";
import { ROOT, absolutePath } from "@ssot/paths";
import {
cacheFile,
collectFiles,
createFingerprintIndex,
fingerprint,
fingerprintOf,
} from "@govlab/content-fingerprint";
import type { FingerprintIndex } from "@govlab/content-fingerprint";
import { excludeMatcher } from "@govlab/quality/config";
import { existsSync } from "node:fs";
import { isPlainRecord } from "#core/predicates/record.predicate";
import { join } from "node:path";
import { readJsonSafe } from "#core/loaders/base.loader";
const GENERATED_MARK = ".generated.";
const TEST_MARKERS: readonly string[] = [".test.", ".spec."];
const isExcluded = await excludeMatcher(ROOT);
const isSharedInput = function isSharedInput(name: string): boolean {
return (
name !== README_FILE && !name.includes(GENERATED_MARK) && !TEST_MARKERS.some((marker) => name.includes(marker))
);
};
const inputsUnder = function inputsUnder(dir: string): string[] {
return collectFiles(dir, { excluded: isExcluded, include: isSharedInput });
};
const SHARED_HASH = fingerprint([
absolutePath("govlab.quality.generated.concepts"),
absolutePath("govlab.quality.generated.rules"),
absolutePath("govlabHost.config"),
...[
absolutePath("govlab.context.principles"),
absolutePath("govlab.docs"),
absolutePath("govlab.utils.canonicalWrite"),
].flatMap(inputsUnder),
]);
export const cacheForced = function cacheForced(env: Readonly<Record<string, string | undefined>>): boolean {
return env[NO_CACHE_ENV] === NO_CACHE_ON;
};
const packageAt = function packageAt(rel: string): Record<string, unknown> {
const parsed = readJsonSafe(join(ROOT, rel, PACKAGE_FILE));
return isPlainRecord(parsed) ? parsed : {};
};
const dependencyNamesOf = function dependencyNamesOf(rel: string): string[] {
const { dependencies } = packageAt(rel);
return isPlainRecord(dependencies) ? Object.keys(dependencies) : [];
};
const membersByName = function membersByName(modules: readonly string[]): ReadonlyMap<string, string> {
return new Map(
modules.flatMap((rel) => {
const { name } = packageAt(rel);
return typeof name === "string" ? [[name, rel] as const] : [];
}),
);
};
const dependencyClosure = function dependencyClosure(rel: string, byName: ReadonlyMap<string, string>): string[] {
const reached = new Set([rel]);
const pending = [rel];
for (let next = pending.pop(); next !== undefined; next = pending.pop()) {
for (const member of dependencyNamesOf(next).flatMap((name) => byName.get(name) ?? [])) {
if (!reached.has(member)) {
reached.add(member);
pending.push(member);
}
}
}
return [...reached].toSorted((left, right) => left.localeCompare(right));
};
export const moduleKey = function moduleKey(rel: string, modules: readonly string[]): string {
const inputs = dependencyClosure(rel, membersByName(modules)).flatMap((member) => inputsUnder(join(ROOT, member)));
return fingerprintOf([fingerprint(inputs), SHARED_HASH]);
};
export const workspaceMapKey = function workspaceMapKey(modules: readonly string[]): string {
const inputs = modules.flatMap((rel) => [join(ROOT, rel, MANIFEST_FILE), join(ROOT, rel, PACKAGE_FILE)]);
return fingerprintOf([fingerprint(inputs), SHARED_HASH]);
};
export const createDocIndex = function createDocIndex(force: boolean): FingerprintIndex {
return createFingerprintIndex({ file: cacheFile(DOCS_CACHE_NAME), force });
};
const hasDocsBlock = function hasDocsBlock(rel: string): boolean {
const parsed = readJsonSafe(join(ROOT, rel, MANIFEST_FILE));
return isPlainRecord(parsed) && isPlainRecord(parsed.docs);
};
export const selectStaleModules = function selectStaleModules(
index: FingerprintIndex,
modules: readonly string[],
keyByModule: ReadonlyMap<string, string>,
): string[] {
return modules.filter(
(rel) =>
!index.unchanged(rel, keyByModule.get(rel) ?? "") ||
(hasDocsBlock(rel) && !existsSync(join(ROOT, rel, README_FILE))),
);
};