import { randomUUID } from 'crypto' import type { Snapshot, SnapshotType } from '../../../shared/types' import type { SqliteDb } from '../types' function mapRow(row: Record): Snapshot { return { id: row.id as string, chapterId: row.chapter_id as string, type: row.type as SnapshotType, name: (row.name as string) ?? '', content: row.content as string, createdAt: row.created_at as string } } export class SnapshotRepository { constructor(private db: SqliteDb) {} create(chapterId: string, type: SnapshotType, content: string, name = ''): Snapshot { const id = randomUUID() this.db .prepare(`INSERT INTO snapshots (id, chapter_id, type, name, content) VALUES (?, ?, ?, ?, ?)`) .run(id, chapterId, type, name, content) return this.get(id)! } get(id: string): Snapshot | null { const row = this.db.prepare('SELECT * FROM snapshots WHERE id = ?').get(id) as | Record | undefined return row ? mapRow(row) : null } list(chapterId: string): Snapshot[] { return ( this.db .prepare('SELECT * FROM snapshots WHERE chapter_id = ? ORDER BY created_at DESC') .all(chapterId) as Record[] ).map(mapRow) } delete(id: string): void { this.db.prepare('DELETE FROM snapshots WHERE id = ?').run(id) } pruneAuto(chapterId: string, max: number): void { const autos = ( this.db .prepare( `SELECT id FROM snapshots WHERE chapter_id = ? AND type = 'auto' ORDER BY created_at ASC` ) .all(chapterId) as { id: string }[] ) const excess = autos.length - max if (excess <= 0) return for (let i = 0; i < excess; i++) { this.delete(autos[i].id) } } prunePersist(chapterId: string, max: number): void { const items = ( this.db .prepare( `SELECT id FROM snapshots WHERE chapter_id = ? AND type = 'persist' ORDER BY created_at ASC` ) .all(chapterId) as { id: string }[] ) const excess = items.length - max if (excess <= 0) return for (let i = 0; i < excess; i++) { this.delete(items[i].id) } } restore(snapshotId: string): string { const snap = this.get(snapshotId) if (!snap) throw new Error('Snapshot not found') return snap.content } }