CG-Feedback-Monitor/server/scripts/verifyBackupRoundtrip.ts
2026-07-06 19:08:24 +02:00

67 lines
2.5 KiB
TypeScript

/**
* Harter Vollständigkeits-Beweis für Backup-Export/-Import (siehe Plan "Vollständigkeits-Garantie").
* Nimmt eine zuvor exportierte Backup-JSON (egal ob aus der alten Dexie-Version oder aus einem
* früheren exportAll()), importiert sie in die aktuelle SQLite-DB, exportiert sofort wieder und
* vergleicht pro Tabelle Zeilenzahl + Inhalt. ACHTUNG: überschreibt den aktuellen Inhalt der
* lokalen SQLite-Datenbank mit dem Inhalt der Backup-Datei.
*
* Aufruf: npm run verify-backup -- <pfad-zur-backup.json>
*/
import { readFileSync } from 'node:fs'
import '../database'
import { TABLE_DEFINITIONS } from '../db/tableRegistry'
import { exportAll, importAll } from '../db/queries/backup'
const filePath = process.argv[2]
if (!filePath) {
console.error('Nutzung: npm run verify-backup -- <pfad-zur-backup.json>')
process.exit(1)
}
const backup = JSON.parse(readFileSync(filePath, 'utf8')) as { tables?: Record<string, Array<Record<string, unknown>>> }
if (!backup.tables || typeof backup.tables !== 'object') {
console.error('Ungültiges Backup-Format: kein "tables"-Feld gefunden.')
process.exit(1)
}
const sourceTables = backup.tables
console.log(`Importiere ${filePath} in die SQLite-DB ...`)
importAll(sourceTables)
console.log('Exportiere sofort wieder zum Vergleich ...\n')
const reexported = exportAll()
const byId = (rows: Array<Record<string, unknown>>) =>
[...rows].sort((a, b) => (a.id as number) - (b.id as number))
let allPass = true
for (const table of TABLE_DEFINITIONS) {
const name = table.name
const sourceRows = byId(sourceTables[name] ?? [])
const targetRows = byId(reexported.tables[name] ?? [])
if (sourceRows.length !== targetRows.length) {
console.log(`${name}: FAIL — Zeilenzahl weicht ab (Quelle: ${sourceRows.length}, Reexport: ${targetRows.length})`)
allPass = false
continue
}
const sourceJson = JSON.stringify(sourceRows)
const targetJson = JSON.stringify(targetRows)
if (sourceJson !== targetJson) {
console.log(`${name}: FAIL — Inhalt weicht ab`)
console.log(` Quelle (Ausschnitt): ${sourceJson.slice(0, 300)}`)
console.log(` Reexport (Ausschnitt): ${targetJson.slice(0, 300)}`)
allPass = false
continue
}
console.log(`${name}: PASS (${sourceRows.length} Zeile${sourceRows.length === 1 ? '' : 'n'}, identisch)`)
}
console.log(allPass
? '\n✅ Alle 21 Tabellen vollständig und inhaltlich identisch importiert/exportiert.'
: '\n❌ Mindestens eine Tabelle weicht ab — siehe oben.')
process.exit(allPass ? 0 : 1)