import http from 'node:http'; import { readFile } from 'node:fs/promises'; import { fileURLToPath } from 'node:url'; import { resolve } from 'node:path'; import { telemetry, profiles } from './telemetry.mjs'; const assets = new Map([ ['/', ['index.html', 'text/html']], ['/index.html', ['index.html', 'text/html']], ['/app.js', ['app.js', 'text/javascript']], ['/styles.css', ['styles.css', 'text/css']] ]); export function createServer() { return http.createServer(async (req, res) => { res.setHeader('X-Content-Type-Options', 'nosniff'); res.setHeader('Cache-Control', 'no-store'); const send = (status, value) => { res.writeHead(status, { 'Content-Type': 'application/json; charset=utf-8' }); res.end(JSON.stringify(value)); }; if (req.method !== 'GET' && req.method !== 'HEAD') return send(405, { error: 'Lecture seule' }); const url = new URL(req.url, 'http://localhost'); if (url.pathname === '/api/health') return send(200, { status: 'ok', source: 'demo' }); if (url.pathname === '/api/telemetry') { const profile = url.searchParams.get('profile') || 'route'; return profiles.includes(profile) ? send(200, telemetry(profile)) : send(400, { error: 'Profil inconnu' }); } const asset = assets.get(url.pathname); if (!asset) return send(404, { error: 'Introuvable' }); try { const content = await readFile(new URL(`../ui/${asset[0]}`, import.meta.url)); res.writeHead(200, { 'Content-Type': `${asset[1]}; charset=utf-8` }); res.end(req.method === 'HEAD' ? undefined : content); } catch { send(500, { error: 'Interface indisponible' }); } }); } if (process.argv[1] && fileURLToPath(import.meta.url) === resolve(process.argv[1])) { const port = Number(process.env.PORT || 8080); createServer().listen(port, process.env.HOST || '0.0.0.0', () => console.log(`CARIA : http://localhost:${port}`)); }