la-rose/scripts/dev-server.ts

49 lines
1.8 KiB
TypeScript
Raw Normal View History

2026-10-04 19:57:52 +00:00
import { createServer } from 'node:http';
import { readFile } from 'node:fs/promises';
import { extname, join, normalize } from 'node:path';
import { fileURLToPath } from 'node:url';
/**
* Minimal placeholder dev server for the data-layer stage.
*
* The Next.js application shell is a later layer (docs/PLAN.md §8, cards for the
* backend/frontend); until it lands this keeps the project's dev container green.
* It serves `public/` and falls back to index.html.
*/
const PUBLIC_DIR = fileURLToPath(new URL('../public', import.meta.url));
function readPort(): number {
const inline = process.argv.find((arg) => arg.startsWith('--port='));
if (inline) return Number(inline.split('=')[1]);
const idx = process.argv.indexOf('--port');
if (idx >= 0 && process.argv[idx + 1]) return Number(process.argv[idx + 1]);
return Number(process.env.PORT ?? 3000);
}
const CONTENT_TYPES: Record<string, string> = {
'.html': 'text/html; charset=utf-8',
'.css': 'text/css; charset=utf-8',
'.js': 'text/javascript; charset=utf-8',
'.svg': 'image/svg+xml',
'.json': 'application/json; charset=utf-8',
};
const server = createServer(async (req, res) => {
const requestPath = decodeURIComponent((req.url ?? '/').split('?')[0]);
const relative = normalize(requestPath === '/' ? '/index.html' : requestPath).replace(/^(\.\.[/\\])+/, '');
const filePath = join(PUBLIC_DIR, relative);
try {
const body = await readFile(filePath);
res.writeHead(200, { 'content-type': CONTENT_TYPES[extname(filePath)] ?? 'application/octet-stream' });
res.end(body);
} catch {
res.writeHead(404, { 'content-type': 'text/plain; charset=utf-8' });
res.end('Not found');
}
});
const port = readPort();
server.listen(port, () => {
console.log(`La Rose data-layer placeholder server listening on http://localhost:${port}`);
});