sokko-g/server.mjs
Shinuwa 748415082b
Some checks failed
Deploy Sokko G / deploy (push) Failing after 2s
Coalesce quota refreshes and consolidate shared helpers
2026-09-10 20:03:57 +02:00

90 lines
2.7 KiB
JavaScript

// 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}`);
});