Gameplay (legal moves, move application, pressure maps, PGN parsing) now runs entirely in the browser via a chess.js port of engine.py (static/engine.js + vendored chess.min.js). The app no longer calls the server during play, so it stays instant and works even when the backend is scaled to zero or offline. - engine.js: line-for-line port of engine.py; parity-verified identical output (pressure, FEN, status, SAN/UCI) across all 10 built-in games / 829 frames. - app.js: replace all /api fetches with local engine calls; graceful PGN parse errors; asset paths moved to root for static serving. - Save games to localStorage + load from the game dropdown; export any game as a .pgn file. Minimal additive UI in the existing export row. - games.json generated from games.py (scripts/export_games.py). - Production Dockerfile -> static-web-server (~9MB image, was ~150MB python). - make dev -> bun static server; add make games / make parity targets. - app.py kept as optional fallback (serves static app + /api routes). - parity/: automated JS-vs-python engine parity test. git diff stat: 16 files changed, 722 insertions(+), 128 deletions(-)
29 lines
1.1 KiB
JavaScript
29 lines
1.1 KiB
JavaScript
// Lightweight static dev server for chess-pressure.
|
|
// Serves src/chess_pressure/static/ at the root, matching the production
|
|
// static-web-server layout. Files are read fresh per request, so editing a
|
|
// JS/CSS/HTML file and refreshing the browser picks up changes immediately.
|
|
//
|
|
// bun run dev-server.js # serves http://0.0.0.0:8888
|
|
// PORT=9000 bun run dev-server.js
|
|
|
|
const ROOT = new URL("./src/chess_pressure/static/", import.meta.url).pathname;
|
|
const PORT = Number(process.env.PORT || 8888);
|
|
|
|
Bun.serve({
|
|
port: PORT,
|
|
hostname: "0.0.0.0",
|
|
async fetch(req) {
|
|
let pathname = decodeURIComponent(new URL(req.url).pathname);
|
|
if (pathname === "/" || pathname === "") pathname = "/index.html";
|
|
// Strip leading slashes and neutralize any ".." path traversal.
|
|
const rel = pathname.replace(/^\/+/, "").replace(/\.\.(\/|\\|$)/g, "");
|
|
const file = Bun.file(ROOT + rel);
|
|
if (await file.exists()) {
|
|
return new Response(file, { headers: { "Cache-Control": "no-cache" } });
|
|
}
|
|
return new Response("Not found", { status: 404 });
|
|
},
|
|
});
|
|
|
|
console.log(`chess-pressure dev server → http://0.0.0.0:${PORT} (serving ${ROOT})`);
|