CI / Typecheck, lint, tests, e2e (push) Failing after 3m51s
- Title screen over a real-time voxel office rendered at low resolution and quantized to a rotating 32-colour palette with Bayer dithering; day part and season re-light the scene and every surface. - 16-bit UI kit: name-plate dialogs, menu cursor, inventory, XP bar, badges, NPC speech, GAME OVER with CONTINUE, hand-placed 12x12 icons, Fusion Pixel font (Latin subset preloaded). - Sections as a game: quest log (onboarding), character select (AI CEO / AI Co-Founder), inventory (features), party roster (providers), live download XP, save point (all v1.5.1 builds), FAQ as NPC dialog, credits. - Downloads and source point to the Gitea release; the download function only redirects to git.zacharyzhang.com. - Tailwind and the old components removed; unit tests for platform/downloads, rewritten e2e suite. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
58 lines
2.0 KiB
JavaScript
58 lines
2.0 KiB
JavaScript
import { createServer } from "node:http";
|
|
import { readFile, stat } from "node:fs/promises";
|
|
import { extname, join, normalize } from "node:path";
|
|
|
|
// Minimal static server for the exported `out/` directory, used by the e2e
|
|
// suite. Cloudflare Pages Functions are not served here, so `/api/*` answers
|
|
// 404 with the exported 404 page, like any other unknown path.
|
|
|
|
const root = process.argv[2] ?? "out";
|
|
const port = Number(process.argv[3] ?? 4319);
|
|
|
|
const contentTypes = {
|
|
".html": "text/html; charset=utf-8",
|
|
".css": "text/css; charset=utf-8",
|
|
".js": "text/javascript; charset=utf-8",
|
|
".json": "application/json; charset=utf-8",
|
|
".webp": "image/webp",
|
|
".png": "image/png",
|
|
".jpg": "image/jpeg",
|
|
".jpeg": "image/jpeg",
|
|
".svg": "image/svg+xml",
|
|
".ico": "image/x-icon",
|
|
".woff2": "font/woff2",
|
|
".txt": "text/plain; charset=utf-8",
|
|
".xml": "application/xml; charset=utf-8",
|
|
};
|
|
|
|
async function resolvePath(pathname) {
|
|
const clean = normalize(decodeURIComponent(pathname)).replace(/^(\.\.[/\\])+/, "");
|
|
let filePath = join(root, clean);
|
|
try {
|
|
const info = await stat(filePath);
|
|
if (info.isDirectory()) filePath = join(filePath, "index.html");
|
|
} catch {
|
|
if (!extname(filePath)) filePath += ".html";
|
|
}
|
|
return filePath;
|
|
}
|
|
|
|
createServer(async (request, response) => {
|
|
try {
|
|
const url = new URL(request.url, `http://127.0.0.1:${port}`);
|
|
const filePath = await resolvePath(url.pathname);
|
|
const body = await readFile(filePath);
|
|
response.writeHead(200, { "Content-Type": contentTypes[extname(filePath)] ?? "application/octet-stream" });
|
|
response.end(body);
|
|
} catch {
|
|
try {
|
|
const notFound = await readFile(join(root, "404.html"));
|
|
response.writeHead(404, { "Content-Type": "text/html; charset=utf-8" });
|
|
response.end(notFound);
|
|
} catch {
|
|
response.writeHead(404);
|
|
response.end("Not found");
|
|
}
|
|
}
|
|
}).listen(port, "127.0.0.1", () => console.log(`serving ${root} at http://127.0.0.1:${port}`));
|