locqr/scripts/serve-website.js
2026-08-16 22:00:08 +02:00

65 lines
2.3 KiB
JavaScript

#!/usr/bin/env node
// Serves website/ over HTTPS using the mkcert-issued test.locqr.dev cert
// (dev.md — HTTPS is required, externally_connectable needs a secure
// context). Also mounts sdk/dist under /sdk/, since the test page imports
// the SDK directly and there's no build step tying the two together
// (sdk/claude.md: packaging/distribution is deferred).
//
// Plain Node https + fs — no extra dependency for something this small.
import { createServer } from 'node:https';
import { readFile, stat } from 'node:fs/promises';
import { extname, join, normalize } from 'node:path';
import { dirname } from 'node:path';
import { fileURLToPath } from 'node:url';
const ROOT = dirname(dirname(fileURLToPath(import.meta.url)));
const WEBSITE_DIR = join(ROOT, 'website');
const SDK_DIST_DIR = join(ROOT, 'sdk', 'dist');
const PORT = 5173;
const MIME = {
'.html': 'text/html; charset=utf-8',
'.js': 'text/javascript; charset=utf-8',
'.css': 'text/css; charset=utf-8',
'.json': 'application/json',
};
async function resolveFile(urlPath) {
const [mountPath, baseDir] = urlPath.startsWith('/sdk/')
? [urlPath.slice('/sdk'.length), SDK_DIST_DIR]
: [urlPath, WEBSITE_DIR];
const safePath = normalize(mountPath === '/' ? '/index.html' : mountPath).replace(/^(\.\.[/\\])+/, '');
const filePath = join(baseDir, safePath);
if (!filePath.startsWith(baseDir)) return null; // path traversal guard
try {
const stats = await stat(filePath);
return stats.isFile() ? filePath : null;
} catch {
return null;
}
}
const options = {
cert: await readFile(join(ROOT, 'dev', 'certs', 'test.locqr.dev.pem')),
key: await readFile(join(ROOT, 'dev', 'certs', 'test.locqr.dev-key.pem')),
};
createServer(options, async (req, res) => {
const url = new URL(req.url ?? '/', 'https://test.locqr.dev');
const filePath = await resolveFile(url.pathname);
if (!filePath) {
res.writeHead(404).end('Not found');
return;
}
const body = await readFile(filePath);
res.writeHead(200, { 'Content-Type': MIME[extname(filePath)] ?? 'application/octet-stream' });
res.end(body);
}).listen(PORT, () => {
console.log(`Serving website/ (and sdk/dist/ at /sdk/) -> https://test.locqr.dev:${PORT}`);
});