/** * Local file storage — disk-based * Gebruikt wanneer geen Kubo API beschikbaar is. * Slaat bestanden op in .data/files/ en houdt metadata bij in .data/files.json */ import { readFile, writeFile, mkdir, unlink, readdir, stat } from 'fs/promises'; import { join } from 'path'; import { createHash } from 'crypto'; const DATA_DIR = join(process.cwd(), '.data', 'files'); const FILES_DB = join(process.cwd(), '.data', 'files.json'); interface FileRecord { cid: string; name: string; size: number; modified: string; path: string; // relatief pad in .data/files/ } async function ensureDir() { await mkdir(DATA_DIR, { recursive: true }); } async function readDb(): Promise> { try { const data = await readFile(FILES_DB, 'utf-8'); return JSON.parse(data); } catch { return {}; } } async function writeDb(db: Record): Promise { await ensureDir(); await writeFile(FILES_DB, JSON.stringify(db, null, 2), 'utf-8'); } /** Genereer een CID-achtige hash van de bestandsinhoud */ function generateCid(buffer: Buffer): string { const hash = createHash('sha256').update(buffer).digest('hex'); // IPFS-style base32 hash (Qm prefix + base32 hash) return 'Qm' + hash.slice(0, 44); } /** Sla een bestand op en retourneer CID + metadata */ export async function localSaveFile( name: string, buffer: Buffer, size: number ): Promise<{ cid: string; size: number }> { await ensureDir(); const cid = generateCid(buffer); const filePath = join(DATA_DIR, `${cid}-${name}`); // Sla het bestand op await writeFile(filePath, buffer); // Update de database const db = await readDb(); db[cid] = { cid, name, size, modified: new Date().toISOString(), path: `${cid}-${name}`, }; await writeDb(db); return { cid, size }; } /** Haal een bestand op */ export async function localGetFile(cid: string): Promise<{ buffer: Buffer; name: string } | null> { const db = await readDb(); const record = db[cid]; if (!record) return null; const filePath = join(DATA_DIR, record.path); try { const buffer = await readFile(filePath); return { buffer, name: record.name }; } catch { return null; } } /** Lijst alle bestanden */ export async function localListFiles(): Promise { const db = await readDb(); return Object.values(db); } /** Verwijder een bestand */ export async function localDeleteFile(cid: string): Promise { const db = await readDb(); const record = db[cid]; if (!record) return; // Verwijder het bestand van disk const filePath = join(DATA_DIR, record.path); try { await unlink(filePath); } catch { // Bestand bestaat niet meer — niet erg } // Verwijder uit de database delete db[cid]; await writeDb(db); } /** Bereken totale opslag */ export async function localGetStorageUsage(): Promise<{ files: number; totalBytes: number }> { const db = await readDb(); const files = Object.values(db); const totalBytes = files.reduce((sum, f) => sum + f.size, 0); return { files: files.length, totalBytes }; }