// Simple server-side event receiver (Node.js example) // Save as: server/index.js const express = require('express'); const crypto = require('crypto'); const app = express(); app.use(express.json()); // In-memory store (use Redis/DB in production) const events = []; const routers = new Map(); // Authentication middleware function authenticate(req, res, next) { const token = req.headers.authorization?.replace('Bearer ', ''); if (!token || token !== process.env.EVENT_TOKEN) { return res.status(401).json({ error: 'Unauthorized' }); } next(); } // Event endpoint app.post('/api/events', authenticate, (req, res) => { const event = { id: crypto.randomUUID(), ...req.body, received_at: new Date().toISOString() }; // Store events.push(event); if (events.length > 10000) events.shift(); // Track router routers.set(event.router_id, { last_seen: new Date(), last_event: event.event_type }); // Log console.log(`[${event.router_id}] ${event.event_type}`, event.payload); // Emit real-time (WebSocket) // io.emit('event', event); res.json({ success: true, event_id: event.id }); }); // routers endpoint app.get('/api/routers', (req, res) => { const online = Array.from(routers.entries()).map(([id, data]) => ({ id, ...data, online: (Date.now() - data.last_seen < 300000) // 5 min })); res.json({ routers: online }); }); // events endpoint app.get('/api/events', (req, res) => { const limit = parseInt(req.query.limit) || 100; const type = req.query.type; let filtered = events; if (type) filtered = events.filter(e => e.event_type === type); res.json({ events: filtered.slice(-limit), total: filtered.length }); }); // Health check app.get('/health', (req, res) => { res.json({ status: 'ok', events: events.length, routers: routers.size }); }); const PORT = process.env.PORT || 3000; app.listen(PORT, () => { console.log(`📡 Event server listening on port ${PORT}`); });