fb5-patch-pkg: the update package's boot step and install check (server/update.js) — before the server starts (runMain: npm start, launch.mjs, the Windows service's run-server.cmd, NSSM, systemd; launch.mjs also before setup) an extracted UPDATE.json is checked: malformed → logged and skipped; the install verified against MANIFEST.json, and a missing or different file the server or browser runs stops the start with the bilingual "download the full package" message (nothing deleted, UPDATE.json kept); else each removed file still holding a base's bytes is deleted (never a changed file, a player's pack, a symlink, a per-machine name or a path outside the install) and UPDATE.json becomes .update-applied.json; doctor gets a MANIFEST.json row; test/update-boot.test.js (10)

This commit is contained in:
sganggs committed 2026-10-07 11:23:42 +08:00
1 parent 0b306baa49
commit d6e40c7235
6 files changed
+710 -7

No files matched your search

+12 -3
View File
@@ -5,9 +5,11 @@
// node scripts/launch.mjs [--port 3000] [--host 0.0.0.0] [--no-open] [--no-setup] [setup options…]
//
// 1. If our server already answers on the port, just open the browser (double-clicking twice is harmless).
// 2. node tools/setup.mjs --quiet (dependencies, vendor libs, art download / resume, optional local extraction);
// 2. An update package extracted over the folder (UPDATE.json) is finished (server/update.js; the server does it too,
// for the routes that skip this script); one that does not fit this install stops here with the message.
// 3. node tools/setup.mjs --quiet (dependencies, vendor libs, art download / resume, optional local extraction);
// setup options such as --no-assets, --no-local, --local, --game <dir>, -y are passed through.
// 3. node server/index.js (PORT / HOST from the options or the environment; SP_COMBAT / SP_VERIFY / TRUST_PROXY /
// 4. node server/index.js (PORT / HOST from the options or the environment; SP_COMBAT / SP_VERIFY / TRUST_PROXY /
// DEBUG are inherited), then — once /healthz answers — prints the addresses to share and opens
// http://localhost:<port> (not with --no-open, SP_NO_BROWSER=1, or on a Linux box without a display).
// Ctrl+C stops the server (it gets the signal from the terminal itself); the exit code is the server's.
@@ -29,6 +31,7 @@ if (Number(process.versions.node.split('.')[0]) < 22) {
const { c, mark } = await import('../tools/setup.mjs');
const { probePort, classifyAddresses, KIND_LABEL } = await import('../tools/doctor.mjs');
const { applyPendingUpdate, UPDATE_FILE } = await import('../server/update.js');
function parseArgs(argv) {
const o = { port: Number(process.env.PORT) || 3000, host: process.env.HOST || '0.0.0.0', open: !/^(1|true|yes)$/i.test(process.env.SP_NO_BROWSER || ''), setup: true, setupArgs: [], help: false };
@@ -81,7 +84,7 @@ async function main() {
const o = parseArgs(process.argv.slice(2));
if (o.help) {
const src = fs.readFileSync(fileURLToPath(import.meta.url), 'utf8').split('\n');
console.log(src.slice(1, 13).map((l) => l.replace(/^\/\/ ?/, '')).join('\n'));
console.log(src.slice(1, 15).map((l) => l.replace(/^\/\/ ?/, '')).join('\n'));
return 0;
}
const localUrl = `http://localhost:${o.port}`;
@@ -89,6 +92,9 @@ async function main() {
const before = await probePort(o.port, o.host);
if (before.state === 'ours') {
console.log(`${mark.ok} 服务器已经在运行(端口 ${o.port}),直接打开浏览器。`);
if (fs.existsSync(path.join(ROOT, UPDATE_FILE))) {
console.log(c.warn(` 解压过的更新包还没有应用:正在运行的仍是旧版本。先停止它(关掉它的窗口;开机自启用 install-service-windows.ps1 -Restart),再重新启动即可。`));
}
printShare(o.port);
if (o.open) openBrowser(localUrl);
return 0;
@@ -99,6 +105,9 @@ async function main() {
return 1;
}
// before setup: setup and the server then see the new version's files (its message explains a refusal)
if (applyPendingUpdate(ROOT).state === 'failed') return 1;
if (o.setup) {
const r = spawnSync(process.execPath, [path.join(ROOT, 'tools', 'setup.mjs'), '--quiet', ...o.setupArgs], { cwd: ROOT, stdio: 'inherit' });
if (r.status !== 0) { console.error(`${mark.err} 准备步骤失败(见上方)。`); return r.status || 1; }