CG-Feedback-Monitor/server/db/queries/backup.ts
2026-07-06 19:08:24 +02:00

46 lines
1.7 KiB
TypeScript

/**
* Generischer Dump/Restore aller Tabellen — Server-Pendant zum bisherigen client-seitigen
* dbBackup.ts (das direkt gegen Dexie/IndexedDB lief). Iteriert exakt TABLE_DEFINITIONS aus
* tableRegistry.ts, derselben Liste, die auch das SQL-Schema erzeugt (siehe Vollständigkeits-
* Garantie im Plan) — eine neue Tabelle kann dadurch nicht unbemerkt aus dem Backup fallen.
*/
import { db } from '../../database'
import { TABLE_DEFINITIONS } from '../tableRegistry'
import { getAllRows, insertRowWithId } from '../crud'
export interface BackupPayload {
version: number
exportedAt: string
tables: Record<string, Array<Record<string, unknown>>>
}
/** Liefert jede Tabelle mit dekodierten Spalten (echte Arrays/Booleans statt JSON-/Bit-Rohwerten). */
export function exportAll(): BackupPayload {
const tables: Record<string, Array<Record<string, unknown>>> = {}
for (const table of TABLE_DEFINITIONS) {
tables[table.name] = getAllRows<Record<string, unknown>>(table.name)
}
return { version: 1, exportedAt: new Date().toISOString(), tables }
}
/** Löscht alle Tabellen und fügt die übergebenen Zeilen mit ihrer ursprünglichen id wieder ein (erhält Fremdschlüssel-Referenzen). */
export function importAll(tables: Record<string, Array<Record<string, unknown>>>): void {
db.exec('BEGIN')
try {
for (const table of TABLE_DEFINITIONS) {
db.prepare(`DELETE FROM "${table.name}"`).run()
}
for (const table of TABLE_DEFINITIONS) {
for (const row of tables[table.name] ?? []) {
const { id, ...rest } = row
if (typeof id !== 'number') continue
insertRowWithId(table.name, id, rest)
}
}
db.exec('COMMIT')
} catch (err) {
db.exec('ROLLBACK')
throw err
}
}