import { createApp } from './app'; import { loadConfig } from './config'; import { openDb } from './db'; import { runMigrations } from './db/migrate'; import { createResultsScheduler } from './results/scheduler'; import { createBridge } from './whatsapp/bridge'; import { createSendQueue } from './whatsapp/sendQueue'; import { createConversationSweeper } from './whatsapp/sweep'; async function main(): Promise { const config = loadConfig(); const db = openDb(config.dbPath); const applied = runMigrations(db); if (applied.length > 0) { console.log(JSON.stringify({ level: 'info', msg: 'migrations applied', applied })); } const bridge = createBridge(config.bridgeUrl); let log: (entry: Record) => void = (e) => console.log(JSON.stringify(e)); const sendQueue = createSendQueue(bridge, (e) => log(e)); const app = createApp({ db, config, bridge, sendQueue }, { logger: true }); log = (e) => app.log.info(e); const stopScheduler = createResultsScheduler({ db, log: (e) => app.log.info(e), ...config.results, }).start(); const stopSweeper = createConversationSweeper({ db, settings: config.orders, queue: sendQueue, log: (e) => app.log.info(e), }).start(); await app.listen({ port: config.port, host: config.host }); let stopping = false; const shutdown = async (signal: string): Promise => { if (stopping) return; stopping = true; app.log.info({ signal }, 'shutting down'); setTimeout(() => process.exit(1), 10_000).unref(); stopScheduler(); stopSweeper(); await app.close(); await sendQueue.idle(); db.close(); process.exit(0); }; process.on('SIGTERM', () => void shutdown('SIGTERM')); process.on('SIGINT', () => void shutdown('SIGINT')); } main().catch((err) => { console.error(JSON.stringify({ level: 'fatal', msg: 'failed to start', error: String(err) })); process.exit(1); });