UNPKG

@mesh-tech/mesh-cli

Version:

CLI for Mesh platform development utilities

75 lines (74 loc) 2.98 kB
import { createServer } from "node:http"; import { readFile } from "node:fs/promises"; import { extname, join, normalize, sep } from "node:path"; const CONTENT_TYPES = { ".html": "text/html; charset=utf-8", ".js": "text/javascript; charset=utf-8", ".mjs": "text/javascript; charset=utf-8", ".css": "text/css; charset=utf-8", ".json": "application/json; charset=utf-8", ".map": "application/json; charset=utf-8", ".svg": "image/svg+xml", ".png": "image/png", ".jpg": "image/jpeg", ".jpeg": "image/jpeg", ".gif": "image/gif", ".ico": "image/x-icon", ".woff": "font/woff", ".woff2": "font/woff2", ".txt": "text/plain; charset=utf-8", ".md": "text/markdown; charset=utf-8", ".webmanifest": "application/manifest+json", }; export async function serveDocsSite(args) { const root = normalize(args.root); const rootPrefix = root.endsWith(sep) ? root : root + sep; const server = createServer((req, res) => { void (async () => { const url = new URL(req.url ?? "/", "http://localhost"); const pathname = decodeURIComponent(url.pathname); if (pathname === "/healthz") { res.writeHead(200, { "content-type": "text/plain" }).end("ok"); return; } const candidates = [ pathname, `${pathname}.html`, `${pathname.replace(/\/$/, "")}/index.html`, ]; if (pathname !== "/") candidates.push("/index.html"); for (const candidate of candidates) { const filePath = normalize(join(root, candidate)); if (filePath !== root && !filePath.startsWith(rootPrefix)) continue; try { const body = await readFile(filePath); const type = CONTENT_TYPES[extname(filePath)] ?? "application/octet-stream"; const cache = candidate.includes("/assets/") ? "public, max-age=31536000, immutable" : "no-cache"; res.writeHead(200, { "content-type": type, "cache-control": cache }); res.end(body); return; } catch { } } res.writeHead(404, { "content-type": "text/plain" }).end("not found"); })().catch(() => { res.writeHead(500).end("internal error"); }); }); await new Promise((resolve, reject) => { server.once("error", reject); server.listen(args.port, "127.0.0.1", () => resolve()); }); const address = server.address(); const port = typeof address === "object" && address ? address.port : args.port; return { url: `http://127.0.0.1:${port}`, port, close: () => new Promise((resolve, reject) => { server.close((error) => (error ? reject(error) : resolve())); }), }; }