import { createServer } from "node:http"; import { createReadStream } from "node:fs"; import { stat } from "node:fs/promises"; import { extname, join, normalize, sep } from "node:path"; import { fileURLToPath } from "node:url"; const port = Number(process.env.PORT ?? 7860); const host = process.env.HOST ?? "0.0.0.0"; const clientDir = fileURLToPath(new URL("../dist/client/", import.meta.url)); const { default: app } = await import("../dist/server/server.js"); const contentTypes = { ".css": "text/css; charset=utf-8", ".js": "text/javascript; charset=utf-8", ".svg": "image/svg+xml", ".jpg": "image/jpeg", ".jpeg": "image/jpeg", ".png": "image/png", ".webp": "image/webp", ".ico": "image/x-icon", ".json": "application/json; charset=utf-8", }; function resolveStaticPath(pathname) { if (!pathname.startsWith("/assets/") && pathname !== "/favicon.svg") { return undefined; } const relativePath = normalize(decodeURIComponent(pathname).replace(/^\/+/, "")); const filePath = join(clientDir, relativePath); const clientRoot = clientDir.endsWith(sep) ? clientDir : `${clientDir}${sep}`; if (!filePath.startsWith(clientRoot)) { return undefined; } return filePath; } async function serveStaticAsset(req, res, pathname) { const filePath = resolveStaticPath(pathname); if (!filePath) return false; try { const fileStat = await stat(filePath); if (!fileStat.isFile()) return false; res.writeHead(200, { "content-type": contentTypes[extname(filePath)] ?? "application/octet-stream", "content-length": fileStat.size, "cache-control": pathname.startsWith("/assets/") ? "public, max-age=31536000, immutable" : "public, max-age=3600", }); if (req.method === "HEAD") { res.end(); return true; } createReadStream(filePath).pipe(res); return true; } catch { return false; } } const server = createServer(async (req, res) => { const origin = `http://${req.headers.host ?? `${host}:${port}`}`; const url = new URL(req.url ?? "/", origin); if (await serveStaticAsset(req, res, url.pathname)) { return; } const request = new Request(url, { method: req.method, headers: req.headers, body: req.method === "GET" || req.method === "HEAD" ? undefined : req, duplex: "half", }); try { const response = await app.fetch(request, {}, {}); res.writeHead(response.status, Object.fromEntries(response.headers)); if (response.body) { const reader = response.body.getReader(); while (true) { const { done, value } = await reader.read(); if (done) break; res.write(Buffer.from(value)); } } res.end(); } catch (error) { console.error(error); res.writeHead(500, { "content-type": "text/plain; charset=utf-8" }); res.end("Internal Server Error"); } }); server.listen(port, host, () => { console.log(`Portfolio listening on http://${host}:${port}`); });