import { promises as fs } from "fs"; import path from "path"; import { FILENAME_REGEX, STATIC_DIR, TOPICS } from "./constants.js"; export const cache = new Map(); function getObjectWithMaxTimestamp(array) { if (!array || array.length === 0) { return null; } return array.reduce((max, current) => { return current.timestamp > max.timestamp ? current : max; }); } async function populateResources() { const filenamesRaw = await fs.readdir(STATIC_DIR); const filenames = filenamesRaw .filter((filename) => FILENAME_REGEX.test(filename)) .map((filename) => { const parts = filename.replace(".md", "").split("_"); if (parts.length !== 4 || parts[0] !== "F") { console.warn(`File not following format: ${filename}`); return; } const topicSeq = Number(parts[1].substring(1)); const resourceSeq = Number(parts[2].substring(1)); const timestamp = Number(parts[3]); return { topicSeq, resourceSeq, timestamp, filename }; }); const topicsBySeq = Object.groupBy(filenames, ({ topicSeq }) => topicSeq); TOPICS.forEach((topic) => { if (topic.seq in topicsBySeq) { const resourcesBySeq = Object.groupBy( topicsBySeq[topic.seq], ({ resourceSeq }) => resourceSeq, ); topic.resources.forEach((resource) => { if (resource.seq in resourcesBySeq) { const latestResource = getObjectWithMaxTimestamp( resourcesBySeq[resource.seq], ); resource.filename = latestResource.filename; } }); } }); } export async function getStructure({ refresh = false } = {}) { const structureKey = "structure"; if (refresh) { cache.delete(structureKey); } if (!cache.has(structureKey)) { await populateResources(); cache.set(structureKey, TOPICS); } return cache.get(structureKey); }