From 660d12e48b69f3648a3fa4cce5e49165884753f5 Mon Sep 17 00:00:00 2001 From: Hermes Date: Sun, 23 Aug 2026 01:50:35 +0000 Subject: [PATCH] fix(sync): filter dump to INSERTs so re-sync is idempotent --- src/app/api/admin/sync-from-prod/route.ts | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/app/api/admin/sync-from-prod/route.ts b/src/app/api/admin/sync-from-prod/route.ts index 323b844..509d6a4 100644 --- a/src/app/api/admin/sync-from-prod/route.ts +++ b/src/app/api/admin/sync-from-prod/route.ts @@ -48,11 +48,19 @@ export async function POST(request: NextRequest) { const tmp = path.join(os.tmpdir(), `pulse-restore-${Date.now()}.sql`); try { - fs.writeFileSync(tmp, dump, 'utf-8'); const tableCount = (dump.match(/CREATE TABLE/g) || []).length; - // Keep the same SQLite file inode so the running app's connection stays valid. - // Clear tables (foreign_keys off) then re-import dump into the same file. + // Keep same SQLite inode so live connection stays valid. + // 1) Clear existing rows spawnSync('sqlite3', [dbPath, "PRAGMA foreign_keys=OFF; DELETE FROM time_entries; DELETE FROM employees; DELETE FROM companies; DELETE FROM audit_log; DELETE FROM __drizzle_migrations; DELETE FROM sqlite_sequence;"], { encoding: 'utf-8' }); + // 2) Filter dump to INSERTs only (DDL already exists via migrations) — otherwise CREATE TABLE fails on re-sync + const filtered = dump + .split('\n') + .filter((line) => { + const t = line.trimStart(); + return t.startsWith('INSERT ') || t.startsWith('PRAGMA ') || t.startsWith('BEGIN ') || t.startsWith('COMMIT'); + }) + .join('\n'); + fs.writeFileSync(tmp, filtered, 'utf-8'); const restore = spawnSync('sh', ['-c', `sqlite3 "${dbPath}" < "${tmp}"`], { encoding: 'utf-8', maxBuffer: 10 * 1024 * 1024 }); if (restore.status !== 0) { return NextResponse.json(err('restore failed: ' + (restore.stderr || restore.stdout || '').slice(0, 1500)), { status: 500 });