Checkpoint: Ajout onglet Sauvegarde DB dans ImportSettings : endpoint POST /api/db-backup (mysqldump), GET /api/db-backup/:filename, procédures tRPC backup.list et backup.delete, composant BackupSection avec liste des sauvegardes et téléchargement.
This commit is contained in:
@@ -85,6 +85,11 @@ import {
|
||||
updateWebImportSourceStatus,
|
||||
} from "./db";
|
||||
import { loginLocal, hashPassword, getAzureAuthUrl, isAzureAdConfigured, generateToken } from "./auth";
|
||||
import { exec as execCb } from "child_process";
|
||||
import { promisify } from "util";
|
||||
import fsSync from "fs";
|
||||
import pathSync from "path";
|
||||
const execAsync = promisify(execCb);
|
||||
import { extractInvoicesWithMistral, generateMetadataJSON } from "./invoiceExtractor";
|
||||
import { localStoragePut, generateStorageKey } from "./localStorage";
|
||||
import { testSftpConnection, exportInvoiceToSftp, getUserSftpConfig } from "./sftpExport";
|
||||
@@ -2678,5 +2683,33 @@ export const appRouter = router({
|
||||
return { apiToken: source.apiToken };
|
||||
}),
|
||||
}),
|
||||
|
||||
// ============= BACKUP ROUTES =============
|
||||
backup: router({
|
||||
// Liste les sauvegardes existantes dans le dossier backups/
|
||||
list: adminProcedure.query(async () => {
|
||||
const backupDir = pathSync.resolve("backups");
|
||||
if (!fsSync.existsSync(backupDir)) return [];
|
||||
const files = fsSync.readdirSync(backupDir)
|
||||
.filter(f => f.endsWith(".sql") || f.endsWith(".sql.gz"))
|
||||
.map(f => {
|
||||
const stat = fsSync.statSync(pathSync.join(backupDir, f));
|
||||
return { name: f, size: stat.size, createdAt: stat.mtime };
|
||||
})
|
||||
.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime());
|
||||
return files;
|
||||
}),
|
||||
|
||||
// Supprime une sauvegarde
|
||||
delete: adminProcedure
|
||||
.input(z.object({ name: z.string() }))
|
||||
.mutation(async ({ input }) => {
|
||||
const backupDir = pathSync.resolve("backups");
|
||||
const filePath = pathSync.join(backupDir, pathSync.basename(input.name));
|
||||
if (!fsSync.existsSync(filePath)) throw new TRPCError({ code: 'NOT_FOUND', message: 'Fichier introuvable' });
|
||||
fsSync.unlinkSync(filePath);
|
||||
return { success: true };
|
||||
}),
|
||||
}),
|
||||
});
|
||||
export type AppRouter = typeof appRouter;
|
||||
|
||||
Reference in New Issue
Block a user