65 lines
2.3 KiB
JavaScript
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}`);
|
|
});
|