'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
| Table | Dernière sync | Lignes | Statut |
| Chargement… |
`;