'use strict'; const express = require('express'); const { getDst } = require('./db'); const { TABLES } = require('./tables'); const app = express(); const PORT = process.env.SYNC_DASHBOARD_PORT || 3002; const TABLES_ORDER = TABLES.map(t => t.name); const TABLES_TOTAL = TABLES_ORDER.length; const state = { running: false, progress: null, }; const logBuffer = []; function pushLog(msg, level = 'info') { logBuffer.push({ ts: new Date().toISOString(), msg, level }); if (logBuffer.length > 300) logBuffer.shift(); } const _log = console.log.bind(console); const _err = console.error.bind(console); console.log = (...a) => { pushLog(a.join(' '), 'info'); _log(...a); }; console.error = (...a) => { pushLog(a.join(' '), 'error'); _err(...a); }; function setProgress(tableName, index) { state.progress = { current: tableName, index, total: TABLES_TOTAL, pct: Math.round((index / TABLES_TOTAL) * 100), startedAt: state.progress?.startedAt || new Date().toISOString(), }; } function clearProgress() { state.progress = null; } let syncAllFn = null; function registerSyncFn(fn) { syncAllFn = fn; } function setSyncRunning(val) { state.running = val; } function isSyncRunning() { return state.running; } app.use(express.json()); app.get('/api/status', async (req, res) => { try { const dst = getDst(); const { rows } = await dst.query( `SELECT table_name, last_sync, rows_synced, status, error_msg FROM sync_log ORDER BY table_name` ); res.json({ running: state.running, progress: state.progress, tables: rows }); } catch (err) { res.status(500).json({ error: err.message }); } }); app.get('/api/logs', (req, res) => { const limit = parseInt(req.query.limit) || 150; res.json(logBuffer.slice(-limit)); }); app.get('/api/next', (req, res) => { const now = new Date(); const next = new Date(now); next.setHours(3, 30, 0, 0); if (next <= now) next.setDate(next.getDate() + 1); res.json({ next: next.toISOString() }); }); app.post('/api/sync/run', async (req, res) => { if (state.running) return res.status(409).json({ error: 'Sync déjà en cours' }); if (!syncAllFn) return res.status(500).json({ error: 'syncAll non enregistré' }); res.json({ message: 'Sync lancée' }); syncAllFn(true).catch(err => console.error('Erreur sync manuelle:', err.message)); }); app.get('/', (req, res) => res.send(HTML)); function startDashboard() { app.listen(PORT, '0.0.0.0', () => { console.log(`Dashboard sync Hostinger : http://0.0.0.0:${PORT}`); }); } module.exports = { startDashboard, registerSyncFn, setSyncRunning, isSyncRunning, setProgress, clearProgress }; const HTML = ` Sync Hostinger

⚡ Sync Hostinger

PG Debian → PG Hostinger Idle
Synchronisation en cours… 0%
Statut des tables
TableDernière syncLignesStatut
Chargement…
Logs
Chargement…
`;