From 6b833610562b3064f5f9efe5ec16bbbbb5ea930f Mon Sep 17 00:00:00 2001 From: Manus Date: Sat, 8 Aug 2026 10:52:58 +0000 Subject: [PATCH] =?UTF-8?q?Checkpoint:=20mysqldump=20n'est=20pas=20disponi?= =?UTF-8?q?ble=20dans=20le=20container=20Node.js.=20Remplacement=20par=20u?= =?UTF-8?q?n=20dump=20SQL=20g=C3=A9n=C3=A9r=C3=A9=20directement=20via=20my?= =?UTF-8?q?sql2=20:=20SHOW=20CREATE=20TABLE=20+=20SELECT=20*=20pour=20chaq?= =?UTF-8?q?ue=20table,=20avec=20=C3=A9chappement=20correct=20des=20valeurs?= =?UTF-8?q?.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/_core/index.ts | 47 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 41 insertions(+), 6 deletions(-) diff --git a/server/_core/index.ts b/server/_core/index.ts index 163c540..a8341c6 100644 --- a/server/_core/index.ts +++ b/server/_core/index.ts @@ -256,13 +256,48 @@ async function startServer() { const fileName = `backup-${database}-${timestamp}.sql`; const filePath = path.join(backupDir, fileName); - // Construire la commande mysqldump - const sslFlag = dbUrl.searchParams.get("ssl-mode") === "DISABLED" ? "" : "--ssl-mode=REQUIRED"; - const cmd = `mysqldump ${sslFlag} -h "${host}" -P ${port} -u "${username}" --password="${password}" "${database}" > "${filePath}"`; + // Dump SQL via mysql2 (pas besoin de mysqldump) + console.log(`[Backup] Generating SQL dump for database ${database}...`); + const mysql = await import("mysql2/promise"); + const sslRequired = !dbUrl.searchParams.get("ssl-mode")?.includes("DISABLED"); + const conn = await mysql.createConnection({ + host, port: parseInt(port), user: username, password: decodeURIComponent(password), + database, ssl: sslRequired ? { rejectUnauthorized: false } : undefined, + }); - console.log(`[Backup] Generating dump for database ${database}...`); - await execAsync(cmd); - console.log(`[Backup] Dump saved to ${filePath}`); + let sql = `-- Backup généré le ${new Date().toISOString()}\n-- Base : ${database}\nSET FOREIGN_KEY_CHECKS=0;\n\n`; + + // Lister les tables + const [tables] = await conn.query(`SHOW TABLES`); + const tableNames: string[] = tables.map((r: any) => Object.values(r)[0] as string); + + for (const table of tableNames) { + // CREATE TABLE + const [createRows] = await conn.query(`SHOW CREATE TABLE \`${table}\``); + const createSql: string = createRows[0]['Create Table'] || createRows[0][`Create Table`]; + sql += `\n-- Table: ${table}\nDROP TABLE IF EXISTS \`${table}\`;\n${createSql};\n\n`; + + // INSERT DATA + const [rows] = await conn.query(`SELECT * FROM \`${table}\``); + if (rows.length > 0) { + const cols = Object.keys(rows[0]).map(c => `\`${c}\``).join(", "); + const values = rows.map(row => + "(" + Object.values(row).map(v => + v === null ? "NULL" : + v instanceof Date ? `'${v.toISOString().replace('T', ' ').replace('Z', '')}'` : + typeof v === "number" ? v : + `'${String(v).replace(/\\/g, "\\\\").replace(/'/g, "\\'")}'` + ).join(", ") + ")" + ).join(",\n"); + sql += `INSERT INTO \`${table}\` (${cols}) VALUES\n${values};\n\n`; + } + } + + sql += `\nSET FOREIGN_KEY_CHECKS=1;\n-- Fin du dump\n`; + await conn.end(); + + fs.writeFileSync(filePath, sql, "utf8"); + console.log(`[Backup] Dump saved to ${filePath} (${(sql.length / 1024).toFixed(1)} Ko)`); // Retourner le fichier en téléchargement const encodedName = encodeURIComponent(fileName);