feedback5 R1: docs and comments follow the split — DESIGN §2 layout lists server/http/, the README table names the entry and http/, path comments in shared/media.js, public/js/media.js, buildGuard.js, net.js and three tests point at the new modules; .git-blame-ignore-revs lists the pure-move commit

This commit is contained in:
sganggs committed 2026-10-05 16:11:30 +08:00
1 parent 1b38e30819
commit 5f0830cdc5
10 files changed
+29 -11

No files matched your search

+7
View File
@@ -0,0 +1,7 @@
# Commits that only move code. Blame across them with
# git blame -C -C --ignore-revs-file .git-blame-ignore-revs <file>
# (or once: git config blame.ignoreRevsFile .git-blame-ignore-revs; -C -C follows lines into the new files of a split).
# Pure moves only (0.2.0 refactor plan, rule 3): a commit listed here changes nothing but where the code lives.
# feedback5 R1: server/index.js top-level code → server/http/ (config, common, files, static, media, buildTag, websocket, boot)
b48a67caec5ba0699097e21f3db4d4dbb35a2aed
+1 -1
View File
@@ -195,7 +195,7 @@ GOLDEN_FULL=1 node --test test/golden.test.js # 黄金结果:固定
| 路径 | 内容 |
|---|---|
| `server/` | Node HTTP 静态服务 + WebSocket(`/ws`)、大厅、对局引擎(`match/`)、战斗模拟(`sim/`,浏览器与服务器共用) |
| `server/` | 入口 `index.js`;Node HTTP 静态服务 + WebSocket(`/ws`,代码在 `http/`)、大厅、对局引擎(`match/`)、战斗模拟(`sim/`,浏览器与服务器共用) |
| `shared/` | 前后端共用的常量与网络协议 |
| `public/` | 浏览器客户端(原生 ES 模块,PixiJS + pixi-spine、three.js 3D 棋盘、Preact + htm UI) |
| `data/` | 由官方数据表生成的游戏数据与素材清单 `assets.json` |
+11 -1
View File
@@ -41,7 +41,17 @@ Run: `npm install && npm run assets && npm start` → `http://localhost:3000`. F
```
server/
index.js HTTP static server (gzip for .skel/.atlas/.json/.js/.css), WebSocket upgrade at /ws, boot
index.js process entry: startServer() wires server/http/ (plain node:http + ws); boots when run directly
http/
config.js ROOT, served dirs, env (PORT, HOST, TRUST_PROXY, DEBUG), options handed to net.js / lobby.js
websocket.js session wiring (SessionRegistry → Lobby → Network), WebSocket upgrade at /ws (64 KB frames)
static.js mounts / → public, /data/, /shared/, /sim/ (.js only), the /data.js browser stand-in, path guards
media.js /media/… extension-less audio → public/assets/audio
files.js one file → response: MIME, gzip (.skel/.atlas/.json/.js/.css …), ETag / 304, cache policy, ranges
buildTag.js build tag of the served browser runtime (/healthz build, public/js/ui/buildGuard.js)
routes.js request listener: 414 / 400 / 405 guards, GET /healthz, then static files
common.js security headers, URL split, error page, JSON replies, bare 400 for unparseable requests
boot.js boot banner (Local / LAN / tunnel URLs), port-in-use hint, graceful SIGINT / SIGTERM
net.js session registry, send helpers, per-connection rate limit, message validation (uses shared/protocol.js)
lobby.js rooms (4-letter codes), seats, host, AI seats, ready/start, reconnect tokens, room→Match wiring
data.js loads data/*.json once, builds indexes (getChess, getBond, …); frozen objects
+1 -1
View File
@@ -9,7 +9,7 @@
//
// /assets/audio/bgm/act1.mp3 → /media/bgm/act1
//
// `server/index.js` resolves /media/… back to the real file under public/assets/audio and still answers with
// `server/http/media.js` resolves /media/… back to the real file under public/assets/audio and still answers with
// `Content-Type: audio/mpeg` + range support; Web Audio sniffs the container, so the URL is all the same to it.
// A host that does not implement /media/ keeps working: `audio.js` falls back to the original URL whenever the
// /media/ response is unusable (a 404, or a 200 that is not audio at all — some static hosts answer a missing
+1 -1
View File
@@ -5,7 +5,7 @@
// reload. A client-only battle fix shipped exactly that way and stayed invisible on the reporting player's page: the
// nginx log shows the page loaded the PRE-fix module blob and made no module request at all for the rest of the session.
//
// HOW: the server stamps a short hash of the runtime it serves into `/healthz.build` (server/index.js computeBuildTag).
// HOW: the server stamps a short hash of the runtime it serves into `/healthz.build` (server/http/buildTag.js).
// The first successful check of a page records that tag as "the build this page runs" — IN MEMORY, because one page is
// one set of loaded modules: nothing must survive a reload, and a duplicated tab must not inherit the first tab's tag.
// A later check reporting a DIFFERENT tag means the server changed under this page:
+1 -1
View File
@@ -525,7 +525,7 @@ export class Network {
get connectionCount() { return this.conns.size; }
/**
* Upgrade-time admission check (server/index.js): null to accept, otherwise the reason to refuse.
* Upgrade-time admission check (server/http/websocket.js): null to accept, otherwise the reason to refuse.
* @param {import('node:http').IncomingMessage} req
* @returns {null | 'shutdown' | 'full' | 'per-address'}
*/
+2 -2
View File
@@ -6,14 +6,14 @@
//
// /assets/audio/bgm/act1.mp3 → /media/bgm/act1
//
// — and `server/index.js` resolves it back to the real file under public/assets/audio, still answering with
// — and `server/http/media.js` resolves it back to the real file under public/assets/audio, still answering with
// `Content-Type: audio/mpeg`, Range support and the ETag of the file it resolved.
//
// Both sides import this module: the browser to decide which URLs to rewrite (`public/js/media.js`), the server to
// decide which extensions a `/media/…` request may resolve to. A second copy of the list on one side would let them
// drift apart silently — the client would rewrite to a path the server no longer accepts.
/** Prefix of the extension-less audio route served by `server/index.js`. */
/** Prefix of the extension-less audio route served by `server/http/media.js`. */
export const MEDIA_PREFIX = '/media/';
/** Extensions a `/media/…` request may resolve to, in the order the server tries them. */
+3 -2
View File
@@ -1,5 +1,6 @@
// test/build.test.js — the served-runtime build tag (server/index.js computeBuildTag / buildTag): the signal that lets
// an already-open page notice a deploy (public/js/ui/buildGuard.js; /healthz `build`).
// test/build.test.js — the served-runtime build tag (server/http/buildTag.js computeBuildTag / buildTag, exported by
// server/index.js): the signal that lets an already-open page notice a deploy (public/js/ui/buildGuard.js;
// /healthz `build`).
import { test } from 'node:test';
import assert from 'node:assert/strict';
import fs from 'node:fs';
+1 -1
View File
@@ -36,7 +36,7 @@ function walk(dir, ext, out = []) {
return out;
}
/** URL path served by the server → file on disk (mirrors server/index.js mounts). */
/** URL path served by the server → file on disk (mirrors the server/http/static.js mounts). */
function urlPathToFile(urlPath) {
const clean = decodeURIComponent(urlPath.split(/[?#]/)[0]);
if (clean.startsWith('/shared/')) return path.join(ROOT, clean);
+1 -1
View File
@@ -23,7 +23,7 @@ const manifest = {
'ui/battle': { img_chess_level_3: { path: '/assets/local/ui/battle/img_chess_level_3.png', w: 45, h: 45 } },
},
};
// what server/index.js serves when data/local-assets.json is absent
// what the server (server/http/static.js) serves when data/local-assets.json is absent
const EMPTY_LOCAL = { version: 1, source: 'none', count: 0, groups: {} };
let mode = 'ok'; // data/local-assets.json: 'ok' (the manifest above) | 'empty' (the server's stand-in) | 'missing' (404)