// RĂ´le : sert l'application Vite construite ou les sources publiques en local. import { createReadStream, existsSync, statSync } from "node:fs"; import { loadProjectEnv } from "./scripts/load-project-env.mjs"; import { createServer } from "node:http"; import { extname, join, relative, resolve } from "node:path"; import { fileURLToPath } from "node:url"; const projectRoot = resolve(fileURLToPath(new URL(".", import.meta.url))); const websiteRoot = join(projectRoot, "website"); const distRoot = join(websiteRoot, "dist"); const root = existsSync(distRoot) ? distRoot : websiteRoot; const publicRoot = existsSync(distRoot) ? distRoot : join(websiteRoot, "public"); loadProjectEnv(); const port = Number(process.env.PORT || 5173); const types = { ".html": "text/html; charset=utf-8", ".css": "text/css; charset=utf-8", ".js": "text/javascript; charset=utf-8", ".json": "application/json; charset=utf-8", ".svg": "image/svg+xml", ".ico": "image/x-icon", ".png": "image/png", ".jpg": "image/jpeg", ".jpeg": "image/jpeg", ".webp": "image/webp" }; function isInsideRoot(parent, file) { const relativePath = relative(parent, file); return Boolean(relativePath) && !relativePath.startsWith("..") && !relativePath.startsWith("/"); } function fileIfReadable(file) { return isInsideRoot(root, file) && existsSync(file) && statSync(file).isFile() ? file : null; } function resolvePath(url) { let requested; try { requested = decodeURIComponent(new URL(url, "http://localhost").pathname); } catch { return null; } const candidate = fileIfReadable(resolve(root, `.${requested}`)); if (candidate) return candidate; const publicCandidate = fileIfReadable(resolve(publicRoot, `.${requested}`)); if (publicCandidate && isInsideRoot(publicRoot, publicCandidate)) return publicCandidate; return extname(requested) ? null : join(root, "index.html"); } const server = createServer((req, res) => { const file = resolvePath(req.url || "/"); if (!file || !existsSync(file)) { res.writeHead(404); res.end("Not found"); return; } const extension = extname(file); const cacheControl = extension === ".html" ? "no-store" : extension === ".json" ? "no-cache" : "public, max-age=31536000, immutable"; res.writeHead(200, { "Content-Type": types[extname(file)] || "application/octet-stream", "Cache-Control": cacheControl }); createReadStream(file).pipe(res); }); server.on("error", (error) => { if (error.code === "EADDRINUSE") { console.error(`Port ${port} is already in use. Set PORT to another value.`); process.exit(1); } console.error(error); process.exit(1); }); server.listen(port, () => { console.log(`Sokko G dev server running at http://localhost:${port}`); });