import { createReadStream, existsSync, statSync } from 'node:fs'; import { createServer } from 'node:http'; import { extname, join, resolve, sep } from 'node:path'; import { fileURLToPath } from 'node:url'; const root = resolve(fileURLToPath(new URL('./dist', import.meta.url))); const port = Number(process.env.PORT) || 3000; const host = process.env.HOST || '0.0.0.0'; const MIME = { '.css': 'text/css; charset=utf-8', '.html': 'text/html; charset=utf-8', '.ico': 'image/x-icon', '.js': 'text/javascript; charset=utf-8', '.json': 'application/json; charset=utf-8', '.map': 'application/json; charset=utf-8', '.png': 'image/png', '.svg': 'image/svg+xml', '.txt': 'text/plain; charset=utf-8', '.webp': 'image/webp', '.woff': 'font/woff', '.woff2': 'font/woff2', }; function fileUnderRoot(urlPath) { const decoded = decodeURIComponent((urlPath ?? '/').split('?')[0] || '/'); const relative = decoded.replace(/^\/+/, '').replaceAll('/', sep); const resolved = resolve(root, relative); const prefix = root.endsWith(sep) ? root : root + sep; if (resolved !== root && !resolved.startsWith(prefix)) return null; return resolved; } function send(res, status, body, type = 'text/plain; charset=utf-8') { res.writeHead(status, { 'Content-Type': type, 'Cache-Control': 'no-cache' }); res.end(body); } const server = createServer((req, res) => { if (req.method === 'GET' && (req.url === '/healthz' || req.url?.startsWith('/healthz?'))) { send(res, 200, 'ok'); return; } if (req.method !== 'GET' && req.method !== 'HEAD') { send(res, 405, 'Method not allowed'); return; } const candidate = fileUnderRoot(req.url ?? '/'); if (!candidate) { send(res, 400, 'Bad request'); return; } let file = candidate; if (!existsSync(file) || statSync(file).isDirectory()) { file = join(root, 'index.html'); } if (!existsSync(file)) { send(res, 500, 'dist/ missing — run npm run build before start'); return; } const type = MIME[extname(file).toLowerCase()] ?? 'application/octet-stream'; res.writeHead(200, { 'Content-Type': type }); if (req.method === 'HEAD') { res.end(); return; } createReadStream(file).pipe(res); }); if (!existsSync(join(root, 'index.html'))) { console.error('dist/index.html missing — run npm run build before start'); process.exit(1); } server.listen(port, host, () => { console.log(`LexAI website listening on http://${host}:${port}`); });