a reactive (signals based) hypermedia web framework (wip) stormlightlabs.github.io/volt/
hypermedia frontend signals
at main 2.0 kB view raw
1import { mkdir, readFile, writeFile } from "node:fs/promises"; 2import path from "node:path"; 3 4/** 5 * Version history entry for a single version 6 */ 7export type VersionHistoryEntry = { 8 version: string; 9 date: string; 10 hash: string; 11 added: number; 12 removed: number; 13 edited: number; 14}; 15 16/** 17 * Complete metadata for a single document 18 */ 19export type DocMetadata = { 20 version: string; 21 updated: string; 22 hash: string; 23 sections: string[]; 24 history: VersionHistoryEntry[]; 25}; 26 27/** 28 * Complete metadata storage for all documents by mapping relative file paths to their metadata 29 */ 30export type VersionsMetadata = Record<string, DocMetadata>; 31 32const METADATA_PATH = path.join(process.cwd(), "..", "docs", ".versions.json"); 33 34/** 35 * Load the complete versions metadata from disk 36 */ 37export async function loadMetadata(): Promise<VersionsMetadata> { 38 try { 39 const content = await readFile(METADATA_PATH, "utf8"); 40 return JSON.parse(content); 41 } catch (error) { 42 if ((error as NodeJS.ErrnoException).code === "ENOENT") { 43 return {}; 44 } 45 throw error; 46 } 47} 48 49/** 50 * Save the complete versions metadata to disk & creates the docs directory if it doesn't exist 51 */ 52export async function saveMetadata(metadata: VersionsMetadata): Promise<void> { 53 const docsDir = path.dirname(METADATA_PATH); 54 await mkdir(docsDir, { recursive: true }); 55 await writeFile(METADATA_PATH, JSON.stringify(metadata, null, 2), "utf8"); 56} 57 58/** 59 * Get metadata for a specific document 60 */ 61export async function getDocMetadata(relativePath: string): Promise<DocMetadata | undefined> { 62 const metadata = await loadMetadata(); 63 return metadata[relativePath]; 64} 65 66/** 67 * Update metadata for a specific document or creates a new entry if document hasn't been versioned yet 68 */ 69export async function updateDocMetadata(relativePath: string, docMeta: DocMetadata): Promise<void> { 70 const metadata = await loadMetadata(); 71 metadata[relativePath] = docMeta; 72 await saveMetadata(metadata); 73}