export { _dashboard } from './server.js'; export type { DashboardAPI } from './server.js'; import { readFileSync } from 'fs'; import { fileURLToPath } from 'url'; import { dirname, resolve } from 'path'; import type { ServerResponse } from 'http'; import type { HttpResponse } from 'warpsocket'; const HERE = dirname(fileURLToPath(import.meta.url)); // Bundle lives next to the compiled serve.js (build/dashboard/dashboard.html); // when running from TS source under Bun, fall back to ../build/dashboard/. const CANDIDATES = [ resolve(HERE, 'dashboard.html'), resolve(HERE, '../build/dashboard/dashboard.html'), ]; let cachedHtml: string | undefined; function getHtml(): string { if (cachedHtml === undefined) { let lastErr: any; for (const p of CANDIDATES) { try { cachedHtml = readFileSync(p, 'utf8'); break; } catch (e) { lastErr = e; } } if (cachedHtml === undefined) { cachedHtml = `
Dashboard bundle missing: ${lastErr?.message || lastErr}\n\nDid you run \`npm run build\` in the lowlander package?`;
}
}
return cachedHtml;
}
/**
* Serve the bundled dashboard HTML on an HTTP response. Compatible with
* Node.js `http.ServerResponse`, Bun's node-compat response, and
* warpsocket's `HttpResponse`. Wire into e.g.:
*
* ```ts
* import { serveDashboard } from 'lowlander/dashboard';
* export function handleHttpRequest(req, res) {
* if (req.url === '/_dashboard') return serveDashboard(res);
* }
* ```
*/
export function serveDashboard(res: ServerResponse | HttpResponse): void {
const html = getHtml();
res.statusCode = 200;
res.setHeader('content-type', 'text/html; charset=utf-8');
res.setHeader('cache-control', 'no-store');
res.end(html);
}