import type Database from 'better-sqlite3'; import { randomUUID } from 'node:crypto'; import { getDb } from './db'; import { contentSeed, seedByTag, type ContentType } from '../data/content-seed'; import { stylesToClasses } from './style-presets'; interface Entry { value: string; type: ContentType; styles: Record; guid: string } export function syncSeed(db: Database.Database): void { const ins = db.prepare('INSERT OR IGNORE INTO content_blocks (tag, type, value, guid) VALUES (?, ?, ?, ?)'); const tx = db.transaction(() => { for (const e of contentSeed) ins.run(e.tag, e.type, e.value, randomUUID()); }); tx(); } export function makeContentStore(dbGetter: () => Database.Database) { let cache: Map | null = null; const load = (): Map => { if (cache) return cache; const rows = dbGetter().prepare('SELECT tag, type, value, styles, guid FROM content_blocks').all() as { tag: string; type: ContentType; value: string; styles: string; guid: string | null }[]; cache = new Map(rows.map((r) => { let styles: Record = {}; try { styles = JSON.parse(r.styles); } catch { /* styles corrotto: si ignora */ } if (typeof styles !== 'object' || styles === null) styles = {}; return [r.tag, { value: r.value, type: r.type, styles, guid: r.guid ?? '' }]; })); return cache; }; return { resolve(tag: string): { value: string; type: ContentType; classes: string; guid: string } { const hit = load().get(tag); if (hit) return { value: hit.value, type: hit.type, classes: stylesToClasses(hit.styles), guid: hit.guid }; const seed = seedByTag.get(tag); if (seed) return { value: seed.value, type: seed.type, classes: '', guid: '' }; console.warn(`[content] tag sconosciuto: ${tag}`); return { value: '', type: 'text', classes: '', guid: '' }; }, invalidate(): void { cache = null; }, }; } const store = makeContentStore(getDb); export const resolveContent = (tag: string) => store.resolve(tag); export const t = (tag: string): string => store.resolve(tag).value; export const invalidateContentCache = (): void => store.invalidate(); export function getImageOverride(tag: string): string | null { const r = store.resolve(tag); return r.type === 'image' && r.value ? `/uploads/${r.value}` : null; } export const contentImageUrl = (tag: string, fallback: string): string => getImageOverride(tag) ?? fallback;