Add unit tests for data file rotation utility functions
- Implement tests for writing data files with rotation, ensuring backups are created only on changes. - Verify that old backups are rotated correctly and the maximum number of backups is maintained. - Test restoration of backups while preserving the current state as a backup. - Utilize Vitest for testing framework and manage temporary file storage during tests.
This commit is contained in:
163
scripts/data-backup-restore.js
Normal file
163
scripts/data-backup-restore.js
Normal file
@@ -0,0 +1,163 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import path from 'path'
|
||||
import {
|
||||
getBackupDirectoryForDataFile,
|
||||
listDataFileBackups,
|
||||
restoreDataFileBackup
|
||||
} from '../server/utils/data-file-rotation.js'
|
||||
|
||||
const FILES = {
|
||||
'users.json': getDataPath('users.json'),
|
||||
'sessions.json': getDataPath('sessions.json'),
|
||||
'members.json': getDataPath('members.json'),
|
||||
'newsletter-subscribers.json': getDataPath('newsletter-subscribers.json'),
|
||||
'news.json': getDataPath('news.json'),
|
||||
'termine.csv': getDataPath('termine.csv'),
|
||||
'contact-requests.json': getDataPath('contact-requests.json')
|
||||
}
|
||||
|
||||
function getDataPath(filename) {
|
||||
const cwd = process.cwd()
|
||||
if (cwd.endsWith('.output')) {
|
||||
return path.join(cwd, '../server/data', filename)
|
||||
}
|
||||
return path.join(cwd, 'server/data', filename)
|
||||
}
|
||||
|
||||
function parseArg(name) {
|
||||
const index = process.argv.findIndex((arg) => arg === name)
|
||||
if (index === -1) return null
|
||||
const next = process.argv[index + 1]
|
||||
if (!next || next.startsWith('--')) return null
|
||||
return next
|
||||
}
|
||||
|
||||
function hasFlag(name) {
|
||||
return process.argv.includes(name)
|
||||
}
|
||||
|
||||
function printUsage() {
|
||||
console.log('Verwendung:')
|
||||
console.log(' node scripts/data-backup-restore.js list [--file users.json]')
|
||||
console.log(' node scripts/data-backup-restore.js restore --file users.json --latest')
|
||||
console.log(' node scripts/data-backup-restore.js restore --file users.json --backup <backup-datei.bak>')
|
||||
console.log('')
|
||||
console.log('Optionen:')
|
||||
console.log(' --file Eine der bekannten Daten-Dateien')
|
||||
console.log(' --latest Stellt das neueste Backup wieder her')
|
||||
console.log(' --backup Konkreter Backup-Dateiname (*.bak)')
|
||||
console.log('')
|
||||
console.log('Bekannte Dateien:')
|
||||
Object.keys(FILES).forEach((name) => console.log(` - ${name}`))
|
||||
}
|
||||
|
||||
async function listCommand() {
|
||||
const requestedFile = parseArg('--file')
|
||||
const names = requestedFile ? [requestedFile] : Object.keys(FILES)
|
||||
|
||||
for (const name of names) {
|
||||
const dataPath = FILES[name]
|
||||
if (!dataPath) {
|
||||
console.error(`Unbekannte Datei: ${name}`)
|
||||
process.exitCode = 1
|
||||
continue
|
||||
}
|
||||
|
||||
const backups = await listDataFileBackups(dataPath)
|
||||
const backupDir = getBackupDirectoryForDataFile(dataPath)
|
||||
|
||||
console.log(`\n${name}`)
|
||||
console.log(` Datenpfad: ${dataPath}`)
|
||||
console.log(` Backup-Ordner: ${backupDir}`)
|
||||
|
||||
if (backups.length === 0) {
|
||||
console.log(' Backups: keine')
|
||||
continue
|
||||
}
|
||||
|
||||
console.log(` Backups (${backups.length}, neuestes zuerst):`)
|
||||
backups.slice(0, 15).forEach((backup) => {
|
||||
console.log(` - ${backup}`)
|
||||
})
|
||||
if (backups.length > 15) {
|
||||
console.log(` ... (${backups.length - 15} weitere)`)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function restoreCommand() {
|
||||
const fileName = parseArg('--file')
|
||||
if (!fileName) {
|
||||
console.error('Fehlend: --file <datei>')
|
||||
printUsage()
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
const dataPath = FILES[fileName]
|
||||
if (!dataPath) {
|
||||
console.error(`Unbekannte Datei: ${fileName}`)
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
const backups = await listDataFileBackups(dataPath)
|
||||
if (backups.length === 0) {
|
||||
console.error(`Keine Backups gefunden für ${fileName}`)
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
const backupName = parseArg('--backup')
|
||||
const latest = hasFlag('--latest')
|
||||
|
||||
let targetBackup = backupName
|
||||
if (!targetBackup && latest) {
|
||||
targetBackup = backups[0]
|
||||
}
|
||||
|
||||
if (!targetBackup) {
|
||||
console.error('Bitte --latest oder --backup <name> angeben')
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
if (!backups.includes(targetBackup)) {
|
||||
console.error(`Backup nicht gefunden: ${targetBackup}`)
|
||||
console.error('Nutzen Sie zuerst: node scripts/data-backup-restore.js list --file <datei>')
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
const result = await restoreDataFileBackup(dataPath, targetBackup)
|
||||
|
||||
console.log(`Wiederherstellung abgeschlossen: ${fileName}`)
|
||||
console.log(` Eingespieltes Backup: ${targetBackup}`)
|
||||
if (result.backupPath) {
|
||||
console.log(` Backup des vorherigen Zustands: ${result.backupPath}`)
|
||||
}
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const command = process.argv[2]
|
||||
|
||||
if (!command || command === '--help' || command === '-h') {
|
||||
printUsage()
|
||||
return
|
||||
}
|
||||
|
||||
if (command === 'list') {
|
||||
await listCommand()
|
||||
return
|
||||
}
|
||||
|
||||
if (command === 'restore') {
|
||||
await restoreCommand()
|
||||
return
|
||||
}
|
||||
|
||||
console.error(`Unbekannter Befehl: ${command}`)
|
||||
printUsage()
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
main().catch((error) => {
|
||||
console.error('Fehler im Backup/Restore-Skript:', error)
|
||||
process.exit(1)
|
||||
})
|
||||
Reference in New Issue
Block a user