@sfmc-bds/bds-tools 0.2.0-beta.8 → 0.2.0-beta.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. package/dist/bds-manager.d.ts.map +1 -1
  2. package/dist/bds-manager.js +40 -65
  3. package/dist/bds-manager.js.map +2 -2
  4. package/dist/check-update.d.ts.map +1 -1
  5. package/dist/check-update.js +4 -6
  6. package/dist/check-update.js.map +2 -2
  7. package/dist/fsx.d.ts +2 -7
  8. package/dist/fsx.d.ts.map +1 -1
  9. package/dist/fsx.js +0 -11
  10. package/dist/fsx.js.map +2 -2
  11. package/dist/host-platform.d.ts +25 -0
  12. package/dist/host-platform.d.ts.map +1 -0
  13. package/dist/host-platform.js +50 -0
  14. package/dist/host-platform.js.map +7 -0
  15. package/dist/pack-manager.d.ts.map +1 -1
  16. package/dist/pack-manager.js +6 -1
  17. package/dist/pack-manager.js.map +2 -2
  18. package/dist/pack-update/bindings.d.ts +16 -0
  19. package/dist/pack-update/bindings.d.ts.map +1 -0
  20. package/dist/pack-update/bindings.js +69 -0
  21. package/dist/pack-update/bindings.js.map +7 -0
  22. package/dist/pack-update/config.d.ts +16 -0
  23. package/dist/pack-update/config.d.ts.map +1 -0
  24. package/dist/pack-update/config.js +146 -0
  25. package/dist/pack-update/config.js.map +7 -0
  26. package/dist/pack-update/deps.d.ts +28 -0
  27. package/dist/pack-update/deps.d.ts.map +1 -0
  28. package/dist/pack-update/deps.js +20 -0
  29. package/dist/pack-update/deps.js.map +7 -0
  30. package/dist/pack-update/index.d.ts +55 -0
  31. package/dist/pack-update/index.d.ts.map +1 -0
  32. package/dist/pack-update/index.js +72 -0
  33. package/dist/pack-update/index.js.map +7 -0
  34. package/dist/pack-update/providers/curseforge.d.ts +23 -0
  35. package/dist/pack-update/providers/curseforge.d.ts.map +1 -0
  36. package/dist/pack-update/providers/curseforge.js +229 -0
  37. package/dist/pack-update/providers/curseforge.js.map +7 -0
  38. package/dist/pack-update/providers/index.d.ts +16 -0
  39. package/dist/pack-update/providers/index.d.ts.map +1 -0
  40. package/dist/pack-update/providers/index.js +37 -0
  41. package/dist/pack-update/providers/index.js.map +7 -0
  42. package/dist/pack-update/service.d.ts +28 -0
  43. package/dist/pack-update/service.d.ts.map +1 -0
  44. package/dist/pack-update/service.js +570 -0
  45. package/dist/pack-update/service.js.map +7 -0
  46. package/dist/pack-update/types.d.ts +126 -0
  47. package/dist/pack-update/types.d.ts.map +1 -0
  48. package/dist/pack-update/types.js +8 -0
  49. package/dist/pack-update/types.js.map +7 -0
  50. package/dist/pack-update/version-policy.d.ts +81 -0
  51. package/dist/pack-update/version-policy.d.ts.map +1 -0
  52. package/dist/pack-update/version-policy.js +210 -0
  53. package/dist/pack-update/version-policy.js.map +7 -0
  54. package/dist/paths.d.ts +1 -1
  55. package/dist/paths.d.ts.map +1 -1
  56. package/dist/paths.js +3 -5
  57. package/dist/paths.js.map +2 -2
  58. package/dist/process-probe.d.ts +34 -0
  59. package/dist/process-probe.d.ts.map +1 -0
  60. package/dist/process-probe.js +152 -0
  61. package/dist/process-probe.js.map +7 -0
  62. package/dist/qq-events-notify.d.ts +16 -0
  63. package/dist/qq-events-notify.d.ts.map +1 -0
  64. package/dist/qq-events-notify.js +70 -0
  65. package/dist/qq-events-notify.js.map +7 -0
  66. package/dist/qq-events-notify.test.d.ts +5 -0
  67. package/dist/qq-events-notify.test.d.ts.map +1 -0
  68. package/dist/qq-events-notify.test.js +41 -0
  69. package/dist/qq-events-notify.test.js.map +7 -0
  70. package/dist/qqutil.d.ts +2 -1
  71. package/dist/qqutil.d.ts.map +1 -1
  72. package/dist/qqutil.js +49 -8
  73. package/dist/qqutil.js.map +2 -2
  74. package/dist/upstream.d.ts +4 -3
  75. package/dist/upstream.d.ts.map +1 -1
  76. package/dist/upstream.js +8 -7
  77. package/dist/upstream.js.map +2 -2
  78. package/dist/version.js +2 -2
  79. package/dist/version.js.map +2 -2
  80. package/dist/world-packs.d.ts +2 -5
  81. package/dist/world-packs.d.ts.map +1 -1
  82. package/dist/world-packs.js +0 -2
  83. package/dist/world-packs.js.map +2 -2
  84. package/package.json +8 -6
@@ -1 +1 @@
1
- {"version":3,"file":"bds-manager.d.ts","sourceRoot":"","sources":["../src/bds-manager.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAMH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAQ3C,MAAM,WAAW,UAAU;IACzB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACtB,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IAC3B,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;IAClC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,MAAM,EAAE,YAAY,CAAC;IACrB,YAAY,EAAE,OAAO,CAAC;IACtB,MAAM,IAAI,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAqED,wBAAgB,gBAAgB,CAAC,OAAO,GAAE,iBAAsB,GAAG,UAAU,CA0K5E;AAED,eAAO,MAAM,SAAS,EAAE,YAAiC,CAAC;AAC1D,eAAO,MAAM,iBAAiB,QAAO,IAA2C,CAAC"}
1
+ {"version":3,"file":"bds-manager.d.ts","sourceRoot":"","sources":["../src/bds-manager.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAgB3C,MAAM,WAAW,UAAU;IACzB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACtB,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IAC3B,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;IAClC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,MAAM,EAAE,YAAY,CAAC;IACrB,YAAY,EAAE,OAAO,CAAC;IACtB,MAAM,IAAI,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AA8BD,wBAAgB,gBAAgB,CAAC,OAAO,GAAE,iBAAsB,GAAG,UAAU,CAiL5E;AAED,eAAO,MAAM,SAAS,EAAE,YAAiC,CAAC;AAC1D,eAAO,MAAM,iBAAiB,QAAO,IAEpC,CAAC"}
@@ -1,52 +1,27 @@
1
- import { spawn, exec } from "node:child_process";
2
- import { promisify } from "node:util";
1
+ import { spawn } from "node:child_process";
3
2
  import fs from "node:fs";
4
3
  import path from "node:path";
5
4
  import { EventEmitter } from "node:events";
5
+ import { bdsExePath, bdsSpawnEnvExtra, ensureBdsExecutable } from "./host-platform.js";
6
6
  import { isMainModule } from "./is-main.js";
7
- import { ensureStateDir, loadConfig, PID_FILE } from "./paths.js";
7
+ import { loadConfig, ROOT_DIR } from "./paths.js";
8
8
  import { log } from "./log.js";
9
+ import { postBdsLifecycleEvent } from "./qq-events-notify.js";
9
10
  import { ensureEmitServerTelemetry } from "./server-properties.js";
10
- const execAsync = promisify(exec);
11
+ import {
12
+ clearBdsPidFile,
13
+ isProcessAlive,
14
+ isProcessAliveSync,
15
+ killBedrockServerByImage,
16
+ readBdsPidFile,
17
+ writeBdsPidFile
18
+ } from "./process-probe.js";
11
19
  let cached = null;
12
- function readPid() {
13
- try {
14
- return parseInt(fs.readFileSync(PID_FILE, "utf-8").trim(), 10) || 0;
15
- } catch {
16
- return 0;
17
- }
18
- }
19
- function writePid(pid) {
20
- try {
21
- ensureStateDir();
22
- fs.writeFileSync(PID_FILE, String(pid));
23
- } catch {
24
- }
25
- }
26
- function clearPid() {
27
- try {
28
- if (fs.existsSync(PID_FILE)) fs.unlinkSync(PID_FILE);
29
- } catch {
30
- }
31
- }
32
- async function isAlive(pid) {
33
- if (!pid) return false;
34
- try {
35
- if (process.platform === "win32") {
36
- const { stdout } = await execAsync(`tasklist /fi "PID eq ${pid}" /nh`, { windowsHide: true });
37
- return stdout.includes(String(pid));
38
- }
39
- process.kill(pid, 0);
40
- return true;
41
- } catch {
42
- return false;
43
- }
44
- }
45
20
  function ensureProc() {
46
21
  if (cached) return cached;
47
22
  const cfg = loadConfig();
48
23
  const bds_path = path.resolve(cfg.bds_path || process.cwd());
49
- const exePath = path.join(bds_path, "bedrock_server.exe");
24
+ const exePath = bdsExePath(bds_path);
50
25
  cached = {
51
26
  process: null,
52
27
  isManualStop: false,
@@ -62,8 +37,8 @@ function createBdsManager(options = {}) {
62
37
  events.setMaxListeners(100);
63
38
  const sendCommand = (cmd) => {
64
39
  const p = ensureProc();
65
- const pid = readPid();
66
- if (!pid || !isAlive(pid)) {
40
+ const pid = readBdsPidFile(ROOT_DIR);
41
+ if (!pid || !isProcessAliveSync(pid)) {
67
42
  log.warn("BDS \u672A\u8FD0\u884C");
68
43
  return false;
69
44
  }
@@ -81,14 +56,14 @@ function createBdsManager(options = {}) {
81
56
  };
82
57
  const stop = async () => {
83
58
  const p = ensureProc();
84
- const pid = readPid();
85
- if (!pid || !await isAlive(pid)) {
59
+ p.isManualStop = true;
60
+ const pid = readBdsPidFile(ROOT_DIR);
61
+ if (!pid || !await isProcessAlive(pid)) {
86
62
  log.info("BDS \u672A\u8FD0\u884C");
87
- clearPid();
63
+ clearBdsPidFile(ROOT_DIR);
88
64
  return;
89
65
  }
90
66
  if (p.process && p.process.pid === pid && p.process.stdin) {
91
- p.isManualStop = true;
92
67
  log.info("\u6B63\u5728\u5173\u95ED BDS...");
93
68
  try {
94
69
  p.process.stdin.write("stop\n");
@@ -117,42 +92,38 @@ function createBdsManager(options = {}) {
117
92
  }
118
93
  } else {
119
94
  log.info("BDS \u7531\u5916\u90E8\u542F\u52A8\uFF0C\u4F7F\u7528 taskkill...");
120
- try {
121
- if (process.platform === "win32") {
122
- await execAsync("taskkill /f /im bedrock_server.exe", { windowsHide: true });
123
- } else {
124
- await execAsync("pkill -f bedrock_server", { windowsHide: true });
125
- }
126
- } catch {
127
- }
95
+ await killBedrockServerByImage();
128
96
  }
129
- clearPid();
97
+ clearBdsPidFile(ROOT_DIR);
130
98
  p.process = null;
131
99
  log.info("BDS \u5DF2\u505C\u6B62");
132
100
  };
133
101
  const start = async () => {
134
102
  const p = ensureProc();
135
- const existing = readPid();
136
- if (existing && await isAlive(existing)) {
103
+ const existing = readBdsPidFile(ROOT_DIR);
104
+ if (existing && await isProcessAlive(existing)) {
137
105
  log.info("BDS \u5DF2\u5728\u8FD0\u884C\u4E2D");
138
106
  return;
139
107
  }
140
108
  if (!fs.existsSync(p.exePath)) {
141
109
  log.error(`\u672A\u627E\u5230 ${p.exePath}`);
142
- throw new Error(`bedrock_server.exe \u4E0D\u5B58\u5728: ${p.exePath}`);
110
+ throw new Error(`BDS \u53EF\u6267\u884C\u6587\u4EF6\u4E0D\u5B58\u5728: ${p.exePath}`);
143
111
  }
144
112
  ensureEmitServerTelemetry(p.bdsPath, log);
113
+ ensureBdsExecutable(p.exePath);
145
114
  log.info("\u6B63\u5728\u542F\u52A8 BDS...");
146
115
  const child = spawn(p.exePath, [], {
147
116
  cwd: p.bdsPath,
117
+ env: { ...process.env, ...bdsSpawnEnvExtra(p.bdsPath) },
148
118
  stdio: options.detached ? "ignore" : ["pipe", "pipe", "pipe"],
149
119
  detached: options.detached,
150
120
  windowsHide: true
151
121
  });
152
122
  if (options.detached) child.unref();
153
123
  p.process = child;
154
- writePid(child.pid ?? 0);
124
+ writeBdsPidFile(child.pid ?? 0, ROOT_DIR);
155
125
  log.info(`BDS \u5DF2\u542F\u52A8 (PID: ${child.pid})`);
126
+ void postBdsLifecycleEvent("start", `pid=${child.pid ?? 0}`);
156
127
  child.stdout?.on("data", (chunk) => {
157
128
  const text = chunk.toString();
158
129
  events.emit("output", text);
@@ -165,9 +136,13 @@ function createBdsManager(options = {}) {
165
136
  });
166
137
  child.on("exit", (code) => {
167
138
  log.info(`BDS \u5DF2\u9000\u51FA (code: ${code})`);
168
- clearPid();
139
+ clearBdsPidFile(ROOT_DIR);
169
140
  p.process = null;
170
- if (!p.isManualStop && p.crashRestart && isMain()) {
141
+ const wasManual = p.isManualStop;
142
+ if (!wasManual) {
143
+ void postBdsLifecycleEvent("crash", `code=${code ?? "?"}`);
144
+ }
145
+ if (!wasManual && p.crashRestart && isMain()) {
171
146
  log.info(`BDS \u610F\u5916\u9000\u51FA\uFF0C${p.crashDelayMs / 1e3}s \u540E\u81EA\u52A8\u91CD\u542F...`);
172
147
  setTimeout(() => {
173
148
  start().catch((e) => log.error(`\u81EA\u52A8\u91CD\u542F\u5931\u8D25: ${e.message}`));
@@ -177,21 +152,21 @@ function createBdsManager(options = {}) {
177
152
  });
178
153
  };
179
154
  const status = async () => {
180
- const pid = readPid();
181
- const alive = pid > 0 && await isAlive(pid);
155
+ const pid = readBdsPidFile(ROOT_DIR);
156
+ const alive = pid > 0 && await isProcessAlive(pid);
182
157
  if (alive) {
183
158
  console.log(`BDS \u8FD0\u884C\u4E2D (PID: ${pid})`);
184
159
  } else {
185
160
  console.log("BDS \u672A\u8FD0\u884C");
186
- clearPid();
161
+ clearBdsPidFile(ROOT_DIR);
187
162
  }
188
163
  return alive;
189
164
  };
190
165
  const watch = async () => {
191
166
  log.info("\u542F\u52A8\u76D1\u62A4\u6A21\u5F0F...");
192
167
  while (true) {
193
- const pid = readPid();
194
- if (!pid || !await isAlive(pid)) {
168
+ const pid = readBdsPidFile(ROOT_DIR);
169
+ if (!pid || !await isProcessAlive(pid)) {
195
170
  try {
196
171
  await start();
197
172
  } catch (e) {
@@ -203,7 +178,7 @@ function createBdsManager(options = {}) {
203
178
  };
204
179
  const getPid = () => {
205
180
  const p = ensureProc();
206
- return p.process?.pid ?? readPid();
181
+ return p.process?.pid ?? readBdsPidFile(ROOT_DIR);
207
182
  };
208
183
  return {
209
184
  start,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/bds-manager.ts"],
4
- "sourcesContent": ["/**\n * bds-manager.ts \u2014 BDS \u8FDB\u7A0B\u7BA1\u7406\u5668\n *\n * \u6539\u8FDB:\n * - \u4F18\u96C5 stop (\u53D1\u9001 stop \u547D\u4EE4 \u2192 \u7B49\u5F85\u9000\u51FA \u2192 SIGTERM \u2192 SIGKILL)\n * - watchdog (\u5D29\u6E83\u81EA\u52A8\u91CD\u542F)\n * - \u5355\u4F8B\u4E8B\u4EF6\u53D1\u5C04\u5668\n * - \u5B8C\u5168\u5F02\u6B65 (fs/promises)\n */\n\nimport { spawn, exec } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { EventEmitter } from \"node:events\";\nimport { isMainModule } from \"./is-main.js\";\nimport { ensureStateDir, loadConfig, PID_FILE } from \"./paths.js\";\nimport { log } from \"./log.js\";\nimport { ensureEmitServerTelemetry } from \"./server-properties.js\";\n\nconst execAsync = promisify(exec);\n\nexport interface BdsManager {\n start(): Promise<void>;\n stop(): Promise<void>;\n status(): Promise<boolean>;\n sendCommand(cmd: string): boolean;\n watch(): Promise<void>;\n events: EventEmitter;\n isManualStop: boolean;\n getPid(): number;\n}\n\nexport interface BdsManagerOptions {\n detached?: boolean;\n}\n\ninterface CachedProc {\n process: ReturnType<typeof spawn> | null;\n isManualStop: boolean;\n crashRestart: boolean;\n crashDelayMs: number;\n exePath: string;\n bdsPath: string;\n}\n\nlet cached: CachedProc | null = null;\n\nfunction readPid(): number {\n try {\n return parseInt(fs.readFileSync(PID_FILE, \"utf-8\").trim(), 10) || 0;\n } catch {\n return 0;\n }\n}\n\nfunction writePid(pid: number): void {\n try {\n ensureStateDir();\n fs.writeFileSync(PID_FILE, String(pid));\n } catch {\n /* ignore */\n }\n}\n\nfunction clearPid(): void {\n try {\n if (fs.existsSync(PID_FILE)) fs.unlinkSync(PID_FILE);\n } catch {\n /* ignore */\n }\n}\n\nasync function isAlive(pid: number): Promise<boolean> {\n if (!pid) return false;\n try {\n if (process.platform === \"win32\") {\n const { stdout } = await execAsync(`tasklist /fi \"PID eq ${pid}\" /nh`, { windowsHide: true });\n return stdout.includes(String(pid));\n }\n process.kill(pid, 0);\n return true;\n } catch {\n return false;\n }\n}\n\nfunction ensureProc(): CachedProc {\n if (cached) return cached;\n const cfg = loadConfig();\n const bds_path = path.resolve(cfg.bds_path || process.cwd());\n const exePath = path.join(bds_path, \"bedrock_server.exe\");\n\n cached = {\n process: null,\n isManualStop: false,\n crashRestart: cfg.crash_restart !== false,\n crashDelayMs: (cfg.crash_restart_delay ?? 5) * 1000,\n exePath,\n bdsPath: bds_path,\n };\n return cached;\n}\n\nexport function createBdsManager(options: BdsManagerOptions = {}): BdsManager {\n const events = new EventEmitter();\n events.setMaxListeners(100);\n\n const sendCommand = (cmd: string): boolean => {\n const p = ensureProc();\n const pid = readPid();\n if (!pid || !isAlive(pid)) {\n log.warn(\"BDS \u672A\u8FD0\u884C\");\n return false;\n }\n if (p.process && p.process.pid === pid && p.process.stdin) {\n try {\n p.process.stdin.write(cmd + \"\\n\");\n log.info(`\u5DF2\u53D1\u9001\u547D\u4EE4: ${cmd}`);\n return true;\n } catch {\n return false;\n }\n }\n log.warn(\"BDS \u7531\u5916\u90E8\u542F\u52A8\uFF0C\u65E0\u6CD5\u53D1\u9001\u547D\u4EE4\u5230 stdin\");\n return false;\n };\n\n const stop = async (): Promise<void> => {\n const p = ensureProc();\n const pid = readPid();\n if (!pid || !(await isAlive(pid))) {\n log.info(\"BDS \u672A\u8FD0\u884C\");\n clearPid();\n return;\n }\n\n if (p.process && p.process.pid === pid && p.process.stdin) {\n p.isManualStop = true;\n log.info(\"\u6B63\u5728\u5173\u95ED BDS...\");\n try {\n p.process.stdin.write(\"stop\\n\");\n } catch (e) {\n log.warn(`\u53D1\u9001 stop \u547D\u4EE4\u5931\u8D25: ${(e as Error).message}`);\n }\n\n await Promise.race([\n new Promise<void>((resolve) => p.process?.once(\"exit\", () => resolve())),\n new Promise<void>((resolve) =>\n setTimeout(() => {\n log.warn(\"30s \u8D85\u65F6\uFF0C\u5F3A\u5236\u7EC8\u6B62...\");\n try { p.process?.kill(\"SIGTERM\"); } catch {}\n setTimeout(resolve, 5000);\n }, 30_000)\n ),\n ]);\n\n if (p.process && p.process.exitCode === null) {\n log.warn(\"\u5F3A\u5236\u7ED3\u675F\u8FDB\u7A0B...\");\n try { p.process.kill(\"SIGKILL\"); } catch {}\n }\n } else {\n // \u5916\u90E8\u542F\u52A8\u7684 BDS \u2014 fallback \u4F7F\u7528 taskkill / pkill\n log.info(\"BDS \u7531\u5916\u90E8\u542F\u52A8\uFF0C\u4F7F\u7528 taskkill...\");\n try {\n if (process.platform === \"win32\") {\n await execAsync(\"taskkill /f /im bedrock_server.exe\", { windowsHide: true });\n } else {\n await execAsync(\"pkill -f bedrock_server\", { windowsHide: true });\n }\n } catch {\n /* ignore */\n }\n }\n\n clearPid();\n p.process = null;\n log.info(\"BDS \u5DF2\u505C\u6B62\");\n };\n\n const start = async (): Promise<void> => {\n const p = ensureProc();\n const existing = readPid();\n if (existing && (await isAlive(existing))) {\n log.info(\"BDS \u5DF2\u5728\u8FD0\u884C\u4E2D\");\n return;\n }\n\n if (!fs.existsSync(p.exePath)) {\n log.error(`\u672A\u627E\u5230 ${p.exePath}`);\n throw new Error(`bedrock_server.exe \u4E0D\u5B58\u5728: ${p.exePath}`);\n }\n\n // \u542F\u52A8\u524D\u5E42\u7B49\u786E\u4FDD\u9065\u6D4B\u5F00\u5173\uFF08\u5B89\u88C5\u9636\u6BB5\u4E5F\u4F1A\u5199\uFF1B\u65E7\u76EE\u5F55\u9996\u6B21\u542F\u52A8\u65F6\u8865\u4E0A\uFF09\n ensureEmitServerTelemetry(p.bdsPath, log);\n\n log.info(\"\u6B63\u5728\u542F\u52A8 BDS...\");\n const child = spawn(p.exePath, [], {\n cwd: p.bdsPath,\n stdio: options.detached ? \"ignore\" : [\"pipe\", \"pipe\", \"pipe\"],\n detached: options.detached,\n windowsHide: true,\n });\n\n if (options.detached) child.unref();\n\n p.process = child;\n writePid(child.pid ?? 0);\n log.info(`BDS \u5DF2\u542F\u52A8 (PID: ${child.pid})`);\n\n child.stdout?.on(\"data\", (chunk: Buffer) => {\n const text = chunk.toString();\n events.emit(\"output\", text);\n if (isMain()) process.stdout.write(text);\n });\n child.stderr?.on(\"data\", (chunk: Buffer) => {\n const text = `[STDERR] ${chunk.toString()}`;\n events.emit(\"output\", text);\n if (isMain()) process.stderr.write(text);\n });\n\n child.on(\"exit\", (code) => {\n log.info(`BDS \u5DF2\u9000\u51FA (code: ${code})`);\n clearPid();\n p.process = null;\n if (!p.isManualStop && p.crashRestart && isMain()) {\n log.info(`BDS \u610F\u5916\u9000\u51FA\uFF0C${p.crashDelayMs / 1000}s \u540E\u81EA\u52A8\u91CD\u542F...`);\n setTimeout(() => {\n start().catch((e) => log.error(`\u81EA\u52A8\u91CD\u542F\u5931\u8D25: ${e.message}`));\n }, p.crashDelayMs);\n }\n p.isManualStop = false;\n });\n };\n\n const status = async (): Promise<boolean> => {\n const pid = readPid();\n const alive = pid > 0 && (await isAlive(pid));\n if (alive) {\n console.log(`BDS \u8FD0\u884C\u4E2D (PID: ${pid})`);\n } else {\n console.log(\"BDS \u672A\u8FD0\u884C\");\n clearPid();\n }\n return alive;\n };\n\n const watch = async (): Promise<void> => {\n log.info(\"\u542F\u52A8\u76D1\u62A4\u6A21\u5F0F...\");\n while (true) {\n const pid = readPid();\n if (!pid || !(await isAlive(pid))) {\n try { await start(); }\n catch (e) { log.error(`\u81EA\u52A8\u542F\u52A8\u5931\u8D25: ${(e as Error).message}`); }\n }\n await new Promise((r) => setTimeout(r, 5_000));\n }\n };\n\n const getPid = (): number => {\n const p = ensureProc();\n return p.process?.pid ?? readPid();\n };\n\n return {\n start,\n stop,\n status,\n sendCommand,\n watch,\n events,\n isManualStop: false,\n getPid,\n };\n}\n\nexport const bdsEvents: EventEmitter = new EventEmitter();\nexport const bdsEvents_enabled = (): void => { bdsEvents.setMaxListeners(100); };\nbdsEvents_enabled();\n\n/** \u5224\u65AD\u5F53\u524D\u662F\u5426\u4F5C\u4E3A CLI \u4E3B\u5165\u53E3\u8FD0\u884C\uFF08\u88AB check-update \u7B49 import \u65F6\u4E3A false\uFF09 */\nfunction isMain(): boolean {\n // sfmc supervisor \u901A\u8FC7 SFMC_SERVICE \u62C9\u8D77\u5B50\u8FDB\u7A0B\u65F6\u4F18\u5148\u5224\u5B9A\uFF08\u4E0E check-update \u5BF9\u79F0\uFF09\n if (process.env.SFMC_SERVICE === \"manager\") return true;\n return isMainModule(import.meta.url);\n}\n\n// CLI \u5165\u53E3\nif (isMain()) {\n const cmd = process.argv[2];\n const bds = createBdsManager();\n const args = process.argv.slice(3);\n\n switch (cmd) {\n case \"start\":\n bds.start().catch((e) => log.error(`\u542F\u52A8\u5931\u8D25: ${e.message}`));\n break;\n case \"stop\":\n bds.stop().catch((e) => log.error(`\u505C\u6B62\u5931\u8D25: ${e.message}`));\n break;\n case \"restart\":\n bds.stop()\n .then(() => bds.start())\n .catch((e) => log.error(`\u91CD\u542F\u5931\u8D25: ${e.message}`));\n break;\n case \"status\":\n bds.status();\n break;\n case \"send\":\n if (args[0]) bds.sendCommand(args.join(\" \"));\n else console.log(\"\u7528\u6CD5: node bds-manager.js send <command>\");\n break;\n case \"watch\":\n bds.watch().catch((e) => log.error(`\u76D1\u62A4\u5F02\u5E38: ${e.message}`));\n break;\n default:\n console.log(`\u7528\u6CD5:\n start \u542F\u52A8 BDS\n stop \u505C\u6B62\n restart \u91CD\u542F\n status \u68C0\u67E5\u72B6\u6001\n send <cmd> \u53D1\u9001\u547D\u4EE4\n watch \u76D1\u62A4\u6A21\u5F0F\uFF08\u5D29\u6E83\u81EA\u52A8\u91CD\u542F\uFF09`);\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * bds-manager.ts \u2014 BDS \u8FDB\u7A0B\u7BA1\u7406\u5668\n *\n * \u6539\u8FDB:\n * - \u4F18\u96C5 stop (\u53D1\u9001 stop \u547D\u4EE4 \u2192 \u7B49\u5F85\u9000\u51FA \u2192 SIGTERM \u2192 SIGKILL)\n * - watchdog (\u5D29\u6E83\u81EA\u52A8\u91CD\u542F)\n * - \u5355\u4F8B\u4E8B\u4EF6\u53D1\u5C04\u5668\n * - \u5B8C\u5168\u5F02\u6B65 (fs/promises)\n */\n\nimport { spawn } from \"node:child_process\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { EventEmitter } from \"node:events\";\nimport { bdsExePath, bdsSpawnEnvExtra, ensureBdsExecutable } from \"./host-platform.js\";\nimport { isMainModule } from \"./is-main.js\";\nimport { loadConfig, ROOT_DIR } from \"./paths.js\";\nimport { log } from \"./log.js\";\nimport { postBdsLifecycleEvent } from \"./qq-events-notify.js\";\nimport { ensureEmitServerTelemetry } from \"./server-properties.js\";\nimport {\n clearBdsPidFile,\n isProcessAlive,\n isProcessAliveSync,\n killBedrockServerByImage,\n readBdsPidFile,\n writeBdsPidFile,\n} from \"./process-probe.js\";\n\nexport interface BdsManager {\n start(): Promise<void>;\n stop(): Promise<void>;\n status(): Promise<boolean>;\n sendCommand(cmd: string): boolean;\n watch(): Promise<void>;\n events: EventEmitter;\n isManualStop: boolean;\n getPid(): number;\n}\n\nexport interface BdsManagerOptions {\n detached?: boolean;\n}\n\ninterface CachedProc {\n process: ReturnType<typeof spawn> | null;\n isManualStop: boolean;\n crashRestart: boolean;\n crashDelayMs: number;\n exePath: string;\n bdsPath: string;\n}\n\nlet cached: CachedProc | null = null;\n\nfunction ensureProc(): CachedProc {\n if (cached) return cached;\n const cfg = loadConfig();\n const bds_path = path.resolve(cfg.bds_path || process.cwd());\n const exePath = bdsExePath(bds_path);\n\n cached = {\n process: null,\n isManualStop: false,\n crashRestart: cfg.crash_restart !== false,\n crashDelayMs: (cfg.crash_restart_delay ?? 5) * 1000,\n exePath,\n bdsPath: bds_path,\n };\n return cached;\n}\n\nexport function createBdsManager(options: BdsManagerOptions = {}): BdsManager {\n const events = new EventEmitter();\n events.setMaxListeners(100);\n\n const sendCommand = (cmd: string): boolean => {\n const p = ensureProc();\n const pid = readBdsPidFile(ROOT_DIR);\n if (!pid || !isProcessAliveSync(pid)) {\n log.warn(\"BDS \u672A\u8FD0\u884C\");\n return false;\n }\n if (p.process && p.process.pid === pid && p.process.stdin) {\n try {\n p.process.stdin.write(cmd + \"\\n\");\n log.info(`\u5DF2\u53D1\u9001\u547D\u4EE4: ${cmd}`);\n return true;\n } catch {\n return false;\n }\n }\n log.warn(\"BDS \u7531\u5916\u90E8\u542F\u52A8\uFF0C\u65E0\u6CD5\u53D1\u9001\u547D\u4EE4\u5230 stdin\");\n return false;\n };\n\n const stop = async (): Promise<void> => {\n const p = ensureProc();\n // \u65E0\u8BBA\u81EA\u7BA1 / \u5916\u90E8\u8FDB\u7A0B\uFF0C\u624B\u52A8 stop \u90FD\u4E0D\u62A5 crash\n p.isManualStop = true;\n const pid = readBdsPidFile(ROOT_DIR);\n if (!pid || !(await isProcessAlive(pid))) {\n log.info(\"BDS \u672A\u8FD0\u884C\");\n clearBdsPidFile(ROOT_DIR);\n return;\n }\n\n if (p.process && p.process.pid === pid && p.process.stdin) {\n log.info(\"\u6B63\u5728\u5173\u95ED BDS...\");\n try {\n p.process.stdin.write(\"stop\\n\");\n } catch (e) {\n log.warn(`\u53D1\u9001 stop \u547D\u4EE4\u5931\u8D25: ${(e as Error).message}`);\n }\n\n await Promise.race([\n new Promise<void>((resolve) => p.process?.once(\"exit\", () => resolve())),\n new Promise<void>((resolve) =>\n setTimeout(() => {\n log.warn(\"30s \u8D85\u65F6\uFF0C\u5F3A\u5236\u7EC8\u6B62...\");\n try {\n p.process?.kill(\"SIGTERM\");\n } catch {}\n setTimeout(resolve, 5000);\n }, 30_000)\n ),\n ]);\n\n if (p.process && p.process.exitCode === null) {\n log.warn(\"\u5F3A\u5236\u7ED3\u675F\u8FDB\u7A0B...\");\n try {\n p.process.kill(\"SIGKILL\");\n } catch {}\n }\n } else {\n // \u5916\u90E8\u542F\u52A8\u7684 BDS \u2014 fallback \u4F7F\u7528 taskkill / pkill\n log.info(\"BDS \u7531\u5916\u90E8\u542F\u52A8\uFF0C\u4F7F\u7528 taskkill...\");\n await killBedrockServerByImage();\n }\n\n clearBdsPidFile(ROOT_DIR);\n p.process = null;\n log.info(\"BDS \u5DF2\u505C\u6B62\");\n };\n\n const start = async (): Promise<void> => {\n const p = ensureProc();\n const existing = readBdsPidFile(ROOT_DIR);\n if (existing && (await isProcessAlive(existing))) {\n log.info(\"BDS \u5DF2\u5728\u8FD0\u884C\u4E2D\");\n return;\n }\n\n if (!fs.existsSync(p.exePath)) {\n log.error(`\u672A\u627E\u5230 ${p.exePath}`);\n throw new Error(`BDS \u53EF\u6267\u884C\u6587\u4EF6\u4E0D\u5B58\u5728: ${p.exePath}`);\n }\n\n // \u542F\u52A8\u524D\u5E42\u7B49\u786E\u4FDD\u9065\u6D4B\u5F00\u5173\uFF08\u5B89\u88C5\u9636\u6BB5\u4E5F\u4F1A\u5199\uFF1B\u65E7\u76EE\u5F55\u9996\u6B21\u542F\u52A8\u65F6\u8865\u4E0A\uFF09\n ensureEmitServerTelemetry(p.bdsPath, log);\n ensureBdsExecutable(p.exePath);\n\n log.info(\"\u6B63\u5728\u542F\u52A8 BDS...\");\n const child = spawn(p.exePath, [], {\n cwd: p.bdsPath,\n env: { ...process.env, ...bdsSpawnEnvExtra(p.bdsPath) },\n stdio: options.detached ? \"ignore\" : [\"pipe\", \"pipe\", \"pipe\"],\n detached: options.detached,\n windowsHide: true,\n });\n\n if (options.detached) child.unref();\n\n p.process = child;\n writeBdsPidFile(child.pid ?? 0, ROOT_DIR);\n log.info(`BDS \u5DF2\u542F\u52A8 (PID: ${child.pid})`);\n void postBdsLifecycleEvent(\"start\", `pid=${child.pid ?? 0}`);\n\n child.stdout?.on(\"data\", (chunk: Buffer) => {\n const text = chunk.toString();\n events.emit(\"output\", text);\n if (isMain()) process.stdout.write(text);\n });\n child.stderr?.on(\"data\", (chunk: Buffer) => {\n const text = `[STDERR] ${chunk.toString()}`;\n events.emit(\"output\", text);\n if (isMain()) process.stderr.write(text);\n });\n\n child.on(\"exit\", (code) => {\n log.info(`BDS \u5DF2\u9000\u51FA (code: ${code})`);\n clearBdsPidFile(ROOT_DIR);\n p.process = null;\n const wasManual = p.isManualStop;\n if (!wasManual) {\n void postBdsLifecycleEvent(\"crash\", `code=${code ?? \"?\"}`);\n }\n if (!wasManual && p.crashRestart && isMain()) {\n log.info(`BDS \u610F\u5916\u9000\u51FA\uFF0C${p.crashDelayMs / 1000}s \u540E\u81EA\u52A8\u91CD\u542F...`);\n setTimeout(() => {\n start().catch((e) => log.error(`\u81EA\u52A8\u91CD\u542F\u5931\u8D25: ${e.message}`));\n }, p.crashDelayMs);\n }\n p.isManualStop = false;\n });\n };\n\n const status = async (): Promise<boolean> => {\n const pid = readBdsPidFile(ROOT_DIR);\n const alive = pid > 0 && (await isProcessAlive(pid));\n if (alive) {\n console.log(`BDS \u8FD0\u884C\u4E2D (PID: ${pid})`);\n } else {\n console.log(\"BDS \u672A\u8FD0\u884C\");\n clearBdsPidFile(ROOT_DIR);\n }\n return alive;\n };\n\n const watch = async (): Promise<void> => {\n log.info(\"\u542F\u52A8\u76D1\u62A4\u6A21\u5F0F...\");\n while (true) {\n const pid = readBdsPidFile(ROOT_DIR);\n if (!pid || !(await isProcessAlive(pid))) {\n try {\n await start();\n } catch (e) {\n log.error(`\u81EA\u52A8\u542F\u52A8\u5931\u8D25: ${(e as Error).message}`);\n }\n }\n await new Promise((r) => setTimeout(r, 5_000));\n }\n };\n\n const getPid = (): number => {\n const p = ensureProc();\n return p.process?.pid ?? readBdsPidFile(ROOT_DIR);\n };\n\n return {\n start,\n stop,\n status,\n sendCommand,\n watch,\n events,\n isManualStop: false,\n getPid,\n };\n}\n\nexport const bdsEvents: EventEmitter = new EventEmitter();\nexport const bdsEvents_enabled = (): void => {\n bdsEvents.setMaxListeners(100);\n};\nbdsEvents_enabled();\n\n/** \u5224\u65AD\u5F53\u524D\u662F\u5426\u4F5C\u4E3A CLI \u4E3B\u5165\u53E3\u8FD0\u884C\uFF08\u88AB check-update \u7B49 import \u65F6\u4E3A false\uFF09 */\nfunction isMain(): boolean {\n // sfmc supervisor \u901A\u8FC7 SFMC_SERVICE \u62C9\u8D77\u5B50\u8FDB\u7A0B\u65F6\u4F18\u5148\u5224\u5B9A\uFF08\u4E0E check-update \u5BF9\u79F0\uFF09\n if (process.env.SFMC_SERVICE === \"manager\") return true;\n return isMainModule(import.meta.url);\n}\n\n// CLI \u5165\u53E3\nif (isMain()) {\n const cmd = process.argv[2];\n const bds = createBdsManager();\n const args = process.argv.slice(3);\n\n switch (cmd) {\n case \"start\":\n bds.start().catch((e) => log.error(`\u542F\u52A8\u5931\u8D25: ${e.message}`));\n break;\n case \"stop\":\n bds.stop().catch((e) => log.error(`\u505C\u6B62\u5931\u8D25: ${e.message}`));\n break;\n case \"restart\":\n bds\n .stop()\n .then(() => bds.start())\n .catch((e) => log.error(`\u91CD\u542F\u5931\u8D25: ${e.message}`));\n break;\n case \"status\":\n bds.status();\n break;\n case \"send\":\n if (args[0]) bds.sendCommand(args.join(\" \"));\n else console.log(\"\u7528\u6CD5: node bds-manager.js send <command>\");\n break;\n case \"watch\":\n bds.watch().catch((e) => log.error(`\u76D1\u62A4\u5F02\u5E38: ${e.message}`));\n break;\n default:\n console.log(`\u7528\u6CD5:\n start \u542F\u52A8 BDS\n stop \u505C\u6B62\n restart \u91CD\u542F\n status \u68C0\u67E5\u72B6\u6001\n send <cmd> \u53D1\u9001\u547D\u4EE4\n watch \u76D1\u62A4\u6A21\u5F0F\uFF08\u5D29\u6E83\u81EA\u52A8\u91CD\u542F\uFF09`);\n }\n}\n"],
5
+ "mappings": "AAUA,SAAS,aAAa;AACtB,OAAO,QAAQ;AACf,OAAO,UAAU;AACjB,SAAS,oBAAoB;AAC7B,SAAS,YAAY,kBAAkB,2BAA2B;AAClE,SAAS,oBAAoB;AAC7B,SAAS,YAAY,gBAAgB;AACrC,SAAS,WAAW;AACpB,SAAS,6BAA6B;AACtC,SAAS,iCAAiC;AAC1C;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AA0BP,IAAI,SAA4B;AAEhC,SAAS,aAAyB;AAChC,MAAI,OAAQ,QAAO;AACnB,QAAM,MAAM,WAAW;AACvB,QAAM,WAAW,KAAK,QAAQ,IAAI,YAAY,QAAQ,IAAI,CAAC;AAC3D,QAAM,UAAU,WAAW,QAAQ;AAEnC,WAAS;AAAA,IACP,SAAS;AAAA,IACT,cAAc;AAAA,IACd,cAAc,IAAI,kBAAkB;AAAA,IACpC,eAAe,IAAI,uBAAuB,KAAK;AAAA,IAC/C;AAAA,IACA,SAAS;AAAA,EACX;AACA,SAAO;AACT;AAEO,SAAS,iBAAiB,UAA6B,CAAC,GAAe;AAC5E,QAAM,SAAS,IAAI,aAAa;AAChC,SAAO,gBAAgB,GAAG;AAE1B,QAAM,cAAc,CAAC,QAAyB;AAC5C,UAAM,IAAI,WAAW;AACrB,UAAM,MAAM,eAAe,QAAQ;AACnC,QAAI,CAAC,OAAO,CAAC,mBAAmB,GAAG,GAAG;AACpC,UAAI,KAAK,wBAAS;AAClB,aAAO;AAAA,IACT;AACA,QAAI,EAAE,WAAW,EAAE,QAAQ,QAAQ,OAAO,EAAE,QAAQ,OAAO;AACzD,UAAI;AACF,UAAE,QAAQ,MAAM,MAAM,MAAM,IAAI;AAChC,YAAI,KAAK,mCAAU,GAAG,EAAE;AACxB,eAAO;AAAA,MACT,QAAQ;AACN,eAAO;AAAA,MACT;AAAA,IACF;AACA,QAAI,KAAK,0FAAyB;AAClC,WAAO;AAAA,EACT;AAEA,QAAM,OAAO,YAA2B;AACtC,UAAM,IAAI,WAAW;AAErB,MAAE,eAAe;AACjB,UAAM,MAAM,eAAe,QAAQ;AACnC,QAAI,CAAC,OAAO,CAAE,MAAM,eAAe,GAAG,GAAI;AACxC,UAAI,KAAK,wBAAS;AAClB,sBAAgB,QAAQ;AACxB;AAAA,IACF;AAEA,QAAI,EAAE,WAAW,EAAE,QAAQ,QAAQ,OAAO,EAAE,QAAQ,OAAO;AACzD,UAAI,KAAK,iCAAa;AACtB,UAAI;AACF,UAAE,QAAQ,MAAM,MAAM,QAAQ;AAAA,MAChC,SAAS,GAAG;AACV,YAAI,KAAK,+CAAkB,EAAY,OAAO,EAAE;AAAA,MAClD;AAEA,YAAM,QAAQ,KAAK;AAAA,QACjB,IAAI,QAAc,CAAC,YAAY,EAAE,SAAS,KAAK,QAAQ,MAAM,QAAQ,CAAC,CAAC;AAAA,QACvE,IAAI;AAAA,UAAc,CAAC,YACjB,WAAW,MAAM;AACf,gBAAI,KAAK,mDAAgB;AACzB,gBAAI;AACF,gBAAE,SAAS,KAAK,SAAS;AAAA,YAC3B,QAAQ;AAAA,YAAC;AACT,uBAAW,SAAS,GAAI;AAAA,UAC1B,GAAG,GAAM;AAAA,QACX;AAAA,MACF,CAAC;AAED,UAAI,EAAE,WAAW,EAAE,QAAQ,aAAa,MAAM;AAC5C,YAAI,KAAK,yCAAW;AACpB,YAAI;AACF,YAAE,QAAQ,KAAK,SAAS;AAAA,QAC1B,QAAQ;AAAA,QAAC;AAAA,MACX;AAAA,IACF,OAAO;AAEL,UAAI,KAAK,kEAA0B;AACnC,YAAM,yBAAyB;AAAA,IACjC;AAEA,oBAAgB,QAAQ;AACxB,MAAE,UAAU;AACZ,QAAI,KAAK,wBAAS;AAAA,EACpB;AAEA,QAAM,QAAQ,YAA2B;AACvC,UAAM,IAAI,WAAW;AACrB,UAAM,WAAW,eAAe,QAAQ;AACxC,QAAI,YAAa,MAAM,eAAe,QAAQ,GAAI;AAChD,UAAI,KAAK,oCAAW;AACpB;AAAA,IACF;AAEA,QAAI,CAAC,GAAG,WAAW,EAAE,OAAO,GAAG;AAC7B,UAAI,MAAM,sBAAO,EAAE,OAAO,EAAE;AAC5B,YAAM,IAAI,MAAM,yDAAiB,EAAE,OAAO,EAAE;AAAA,IAC9C;AAGA,8BAA0B,EAAE,SAAS,GAAG;AACxC,wBAAoB,EAAE,OAAO;AAE7B,QAAI,KAAK,iCAAa;AACtB,UAAM,QAAQ,MAAM,EAAE,SAAS,CAAC,GAAG;AAAA,MACjC,KAAK,EAAE;AAAA,MACP,KAAK,EAAE,GAAG,QAAQ,KAAK,GAAG,iBAAiB,EAAE,OAAO,EAAE;AAAA,MACtD,OAAO,QAAQ,WAAW,WAAW,CAAC,QAAQ,QAAQ,MAAM;AAAA,MAC5D,UAAU,QAAQ;AAAA,MAClB,aAAa;AAAA,IACf,CAAC;AAED,QAAI,QAAQ,SAAU,OAAM,MAAM;AAElC,MAAE,UAAU;AACZ,oBAAgB,MAAM,OAAO,GAAG,QAAQ;AACxC,QAAI,KAAK,gCAAiB,MAAM,GAAG,GAAG;AACtC,SAAK,sBAAsB,SAAS,OAAO,MAAM,OAAO,CAAC,EAAE;AAE3D,UAAM,QAAQ,GAAG,QAAQ,CAAC,UAAkB;AAC1C,YAAM,OAAO,MAAM,SAAS;AAC5B,aAAO,KAAK,UAAU,IAAI;AAC1B,UAAI,OAAO,EAAG,SAAQ,OAAO,MAAM,IAAI;AAAA,IACzC,CAAC;AACD,UAAM,QAAQ,GAAG,QAAQ,CAAC,UAAkB;AAC1C,YAAM,OAAO,YAAY,MAAM,SAAS,CAAC;AACzC,aAAO,KAAK,UAAU,IAAI;AAC1B,UAAI,OAAO,EAAG,SAAQ,OAAO,MAAM,IAAI;AAAA,IACzC,CAAC;AAED,UAAM,GAAG,QAAQ,CAAC,SAAS;AACzB,UAAI,KAAK,iCAAkB,IAAI,GAAG;AAClC,sBAAgB,QAAQ;AACxB,QAAE,UAAU;AACZ,YAAM,YAAY,EAAE;AACpB,UAAI,CAAC,WAAW;AACd,aAAK,sBAAsB,SAAS,QAAQ,QAAQ,GAAG,EAAE;AAAA,MAC3D;AACA,UAAI,CAAC,aAAa,EAAE,gBAAgB,OAAO,GAAG;AAC5C,YAAI,KAAK,qCAAY,EAAE,eAAe,GAAI,qCAAY;AACtD,mBAAW,MAAM;AACf,gBAAM,EAAE,MAAM,CAAC,MAAM,IAAI,MAAM,yCAAW,EAAE,OAAO,EAAE,CAAC;AAAA,QACxD,GAAG,EAAE,YAAY;AAAA,MACnB;AACA,QAAE,eAAe;AAAA,IACnB,CAAC;AAAA,EACH;AAEA,QAAM,SAAS,YAA8B;AAC3C,UAAM,MAAM,eAAe,QAAQ;AACnC,UAAM,QAAQ,MAAM,KAAM,MAAM,eAAe,GAAG;AAClD,QAAI,OAAO;AACT,cAAQ,IAAI,gCAAiB,GAAG,GAAG;AAAA,IACrC,OAAO;AACL,cAAQ,IAAI,wBAAS;AACrB,sBAAgB,QAAQ;AAAA,IAC1B;AACA,WAAO;AAAA,EACT;AAEA,QAAM,QAAQ,YAA2B;AACvC,QAAI,KAAK,yCAAW;AACpB,WAAO,MAAM;AACX,YAAM,MAAM,eAAe,QAAQ;AACnC,UAAI,CAAC,OAAO,CAAE,MAAM,eAAe,GAAG,GAAI;AACxC,YAAI;AACF,gBAAM,MAAM;AAAA,QACd,SAAS,GAAG;AACV,cAAI,MAAM,yCAAY,EAAY,OAAO,EAAE;AAAA,QAC7C;AAAA,MACF;AACA,YAAM,IAAI,QAAQ,CAAC,MAAM,WAAW,GAAG,GAAK,CAAC;AAAA,IAC/C;AAAA,EACF;AAEA,QAAM,SAAS,MAAc;AAC3B,UAAM,IAAI,WAAW;AACrB,WAAO,EAAE,SAAS,OAAO,eAAe,QAAQ;AAAA,EAClD;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,cAAc;AAAA,IACd;AAAA,EACF;AACF;AAEO,MAAM,YAA0B,IAAI,aAAa;AACjD,MAAM,oBAAoB,MAAY;AAC3C,YAAU,gBAAgB,GAAG;AAC/B;AACA,kBAAkB;AAGlB,SAAS,SAAkB;AAEzB,MAAI,QAAQ,IAAI,iBAAiB,UAAW,QAAO;AACnD,SAAO,aAAa,YAAY,GAAG;AACrC;AAGA,IAAI,OAAO,GAAG;AACZ,QAAM,MAAM,QAAQ,KAAK,CAAC;AAC1B,QAAM,MAAM,iBAAiB;AAC7B,QAAM,OAAO,QAAQ,KAAK,MAAM,CAAC;AAEjC,UAAQ,KAAK;AAAA,IACX,KAAK;AACH,UAAI,MAAM,EAAE,MAAM,CAAC,MAAM,IAAI,MAAM,6BAAS,EAAE,OAAO,EAAE,CAAC;AACxD;AAAA,IACF,KAAK;AACH,UAAI,KAAK,EAAE,MAAM,CAAC,MAAM,IAAI,MAAM,6BAAS,EAAE,OAAO,EAAE,CAAC;AACvD;AAAA,IACF,KAAK;AACH,UACG,KAAK,EACL,KAAK,MAAM,IAAI,MAAM,CAAC,EACtB,MAAM,CAAC,MAAM,IAAI,MAAM,6BAAS,EAAE,OAAO,EAAE,CAAC;AAC/C;AAAA,IACF,KAAK;AACH,UAAI,OAAO;AACX;AAAA,IACF,KAAK;AACH,UAAI,KAAK,CAAC,EAAG,KAAI,YAAY,KAAK,KAAK,GAAG,CAAC;AAAA,UACtC,SAAQ,IAAI,kDAAwC;AACzD;AAAA,IACF,KAAK;AACH,UAAI,MAAM,EAAE,MAAM,CAAC,MAAM,IAAI,MAAM,6BAAS,EAAE,OAAO,EAAE,CAAC;AACxD;AAAA,IACF;AACE,cAAQ,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,yFAMW;AAAA,EAC3B;AACF;",
6
6
  "names": []
7
7
  }
@@ -1 +1 @@
1
- {"version":3,"file":"check-update.d.ts","sourceRoot":"","sources":["../src/check-update.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAuJH,wBAAsB,SAAS,IAAI,OAAO,CAAC,MAAM,CAAC,CAyRjD"}
1
+ {"version":3,"file":"check-update.d.ts","sourceRoot":"","sources":["../src/check-update.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAwJH,wBAAsB,SAAS,IAAI,OAAO,CAAC,MAAM,CAAC,CAuRjD"}
@@ -9,6 +9,7 @@ import path from "node:path";
9
9
  import { createBdsManager } from "./bds-manager.js";
10
10
  import { CHANGELOG_BASE, fetchChangelog } from "./changelog.js";
11
11
  import { copyDirSync, emptyDirSync, hashFileAsync, rmSafe } from "./fsx.js";
12
+ import { bdsExePath, bdsInstallRequiredFiles, ensureBdsExecutable } from "./host-platform.js";
12
13
  import { httpDownload } from "./http.js";
13
14
  import { isMainModule } from "./is-main.js";
14
15
  import { loadConfig, LOG_PATH, resolvePaths } from "./paths.js";
@@ -123,7 +124,7 @@ async function runUpdate() {
123
124
  log.info(`===== \u5F00\u59CB\u68C0\u67E5\u66F4\u65B0 (${channel}) =====`);
124
125
  fs.mkdirSync(bdsPath, { recursive: true });
125
126
  fs.mkdirSync(backupDir, { recursive: true });
126
- const exePath = path.join(bdsPath, "bedrock_server.exe");
127
+ const exePath = bdsExePath(bdsPath);
127
128
  const currentVer = await getCurrentVersionAsync(exePath).catch(() => getCurrentVersionSync(exePath));
128
129
  log.info(`\u5F53\u524D\u7248\u672C: ${currentVer}`);
129
130
  let latestVer;
@@ -315,6 +316,7 @@ BDS \u5DF2\u505C\u6B62\uFF0C\u8BF7\u624B\u52A8\u6062\u590D`);
315
316
  log.info("\u89E3\u538B\u4E2D...");
316
317
  emptyDirSync(bdsPath);
317
318
  await extractZipToBds(zipPath, bdsPath);
319
+ ensureBdsExecutable(exePath);
318
320
  log.info("\u89E3\u538B\u5B8C\u6210");
319
321
  } catch (e) {
320
322
  log.error(`\u89E3\u538B\u5931\u8D25: ${e.message}`);
@@ -329,11 +331,7 @@ BDS \u5DF2\u505C\u6B62\uFF0C\u8BF7\u624B\u52A8\u6062\u590D`);
329
331
  } finally {
330
332
  rmSafe(zipPath);
331
333
  }
332
- const verify = verifyBdsInstall(bdsPath, [
333
- "bedrock_server.exe",
334
- /*"bedrock_server_symbols.debug",*/
335
- "permissions.json"
336
- ]);
334
+ const verify = verifyBdsInstall(bdsPath, bdsInstallRequiredFiles());
337
335
  if (!verify.ok) {
338
336
  log.error(`\u89E3\u538B\u540E\u7684 BDS \u4E0D\u5B8C\u6574\uFF0C\u7F3A\u5931\u6587\u4EF6: ${verify.missing.join(", ")}`);
339
337
  await sendText(`\u274C BDS \u66F4\u65B0\u5931\u8D25
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/check-update.ts"],
4
- "sourcesContent": ["/**\n * check-update.ts \u2014 BDS \u81EA\u52A8\u66F4\u65B0\u5668 (\u4E3B\u6D41\u7A0B)\n *\n * 1. \u4E34\u65F6 staging \u76EE\u5F55 (mkdtempSync) - \u907F\u514D\u6C61\u67D3\u6570\u636E\u6839\n * 2. \u4E0B\u8F7D/\u89E3\u538B\u5931\u8D25 \u2192 \u81EA\u52A8\u4ECE\u5907\u4EFD\u56DE\u6EDA preserves\n * 3. \u6D41\u5F0F SHA256 \u6821\u9A8C - \u4E0D\u628A 250MB \u6587\u4EF6\u8BFB\u5165\u5185\u5B58\n * 4. \u517C\u5BB9\u7248\u672C\u767D\u540D\u5355 - \u4E0D\u5339\u914D\u5219\u8DF3\u8FC7\u5347\u7EA7\n * 5. QQ \u901A\u77E5\u7EDF\u4E00\u52A0 5s \u8D85\u65F6 - \u6C38\u8FDC\u4E0D\u963B\u585E\u4E3B\u6D41\u7A0B\n * 6. Rollback marker \u843D\u76D8\u5230 <ROOT>/.sfmc/ - \u8DE8\u8FDB\u7A0B / \u8DE8\u91CD\u542F\u53EF\u6062\u590D\n */\n\nimport {\n bindByteProgressToBar,\n createNodeServiceLogger,\n createTerminalProgress,\n} from \"@sfmc-bds/sdk/logs\";\nimport fs from \"node:fs\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport { createBdsManager } from \"./bds-manager.js\";\nimport { CHANGELOG_BASE, fetchChangelog } from \"./changelog.js\";\nimport { copyDirSync, emptyDirSync, hashFileAsync, rmSafe } from \"./fsx.js\";\nimport { httpDownload } from \"./http.js\";\nimport { isMainModule } from \"./is-main.js\";\nimport { loadConfig, LOG_PATH, resolvePaths } from \"./paths.js\";\nimport { sendText, sendWithImage } from \"./qqutil.js\";\nimport {\n clearRollbackMarker,\n getDirSize,\n rollbackFromBackup,\n verifyBdsInstall,\n writeRollbackMarker,\n} from \"./rollback.js\";\nimport { ensureEmitServerTelemetry } from \"./server-properties.js\";\nimport { clearTaskbarProgress, isTaskbarSupported, setTaskbarProgress } from \"./taskbar.js\";\nimport { emitUpdateKv, emitUpdateResult } from \"./update-result.js\";\nimport {\n buildDownloadUrls,\n fetchVersionDetails,\n getVersionInfo,\n isVersionCompatible,\n verifyFileHash,\n} from \"./upstream.js\";\nimport { compareVersions, getCurrentVersionAsync, getCurrentVersionSync, saveVersionCache } from \"./version.js\";\nimport { extractZipFileToDir } from \"./zipx.js\";\n\n// \u72EC\u7ACB\u5165\u53E3:source = \"updater\",\u4E0E bds-manager \u7684 \"bds-tools\" \u533A\u5206;\u540C\u843D\u76D8 bds-update.log\nconst log = createNodeServiceLogger({ source: \"updater\", logPath: LOG_PATH });\nconst closeLog = (): void => log.close();\n\nfunction parseArgs(argv: string[]): Record<string, string | boolean> {\n const out: Record<string, string | boolean> = {};\n for (const a of argv) {\n const m = a.match(/^--([\\w-]+)(?:=(.+))?$/);\n if (m) out[m[1]!] = m[2] || true;\n }\n return out;\n}\n\ninterface UpdateContext {\n cfg: ReturnType<typeof loadConfig>;\n channel: \"release\" | \"preview\" | string;\n checkOnly: boolean;\n force: boolean;\n bdsPath: string;\n backupDir: string;\n preserve: string[];\n autoRestart: boolean;\n qqNotify: boolean;\n}\n\nfunction buildContext(): UpdateContext {\n const cfg = loadConfig();\n const args = parseArgs(process.argv.slice(2));\n const { bds_path, backup_dir, preserve } = resolvePaths(cfg);\n const channel = String(args[\"channel\"] || cfg.channel || \"release\");\n return {\n cfg,\n channel,\n checkOnly: !!args[\"check-only\"],\n force: !!args[\"force\"],\n bdsPath: bds_path,\n backupDir: backup_dir,\n preserve,\n autoRestart: !args[\"no-start\"] && cfg.auto_restart !== false,\n qqNotify: !!cfg.qq_notify,\n };\n}\n\nasync function doBackup(\n bdsPath: string,\n backupDir: string,\n preserve: string[]\n): Promise<{ path: string; size: number }> {\n const dateStr = new Date().toISOString().slice(0, 10);\n const dest = path.join(backupDir, dateStr);\n fs.mkdirSync(dest, { recursive: true });\n\n let anyCopied = false;\n for (const item of preserve) {\n const src = path.join(bdsPath, item);\n const target = path.join(dest, item);\n if (!fs.existsSync(src)) continue;\n fs.mkdirSync(path.dirname(target), { recursive: true });\n if (fs.statSync(src).isDirectory()) copyDirSync(src, target);\n else fs.copyFileSync(src, target);\n anyCopied = true;\n log.info(`\u5DF2\u5907\u4EFD: ${item}`);\n }\n\n // \u5373\u4F7F\u5168\u90E8 preserve \u90FD\u8DF3\u8FC7\uFF0C\u4E5F\u8BA9\u76EE\u5F55\u5B58\u5728\u4EE5\u4FBF\u8BB0\u5F55\u65F6\u95F4\u6233\n if (!anyCopied) {\n log.info(`\u6CA1\u6709\u9700\u8981\u5907\u4EFD\u7684\u6587\u4EF6 (preserve \u5217\u8868\u4E3A\u7A7A\u6216\u5168\u90E8\u7F3A\u5931)`);\n }\n return { path: dest, size: getDirSize(dest) };\n}\n\n/** \u5F02\u6B65\u6062\u590D preserves \u4ECE\u5907\u4EFD\u5230 BDS \u8DEF\u5F84 */\nasync function restorePreserves(bdsPath: string, backupDir: string, preserve: string[]): Promise<void> {\n for (const item of preserve) {\n const src = path.join(backupDir, item);\n const dest = path.join(bdsPath, item);\n if (!fs.existsSync(src)) continue;\n try {\n if (fs.statSync(src).isDirectory()) {\n if (fs.existsSync(dest)) emptyDirSync(dest);\n copyDirSync(src, dest);\n } else {\n fs.mkdirSync(path.dirname(dest), { recursive: true });\n fs.copyFileSync(src, dest);\n }\n log.info(`\u5DF2\u6062\u590D: ${item}`);\n } catch (e) {\n log.warn(`\u6062\u590D\u5931\u8D25 ${item}: ${(e as Error).message}`);\n }\n }\n}\n\n/** \u628A zip \u89E3\u538B\u5230 destDir (\u8986\u76D6) \u2014 \u7ECF zipx \u5B89\u5168\u89E3\u538B */\nasync function extractZipToBds(zipPath: string, destDir: string): Promise<void> {\n // \u62BD\u51FA\u5230\u4E34\u65F6\u76EE\u5F55\uFF0C\u907F\u514D\u65E7\u5185\u5BB9\u5E72\u6270\n const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), \"bds-extract-\"));\n try {\n await extractZipFileToDir(zipPath, tmpDir);\n // \u628A\u4E34\u65F6\u76EE\u5F55\u91CC\u7684\u5185\u5BB9\u590D\u5236\u5230 BDS \u8DEF\u5F84\n for (const entry of fs.readdirSync(tmpDir)) {\n const srcPath = path.join(tmpDir, entry);\n const destPath = path.join(destDir, entry);\n if (fs.statSync(srcPath).isDirectory()) {\n if (fs.existsSync(destPath)) emptyDirSync(destPath);\n copyDirSync(srcPath, destPath);\n } else {\n fs.copyFileSync(srcPath, destPath);\n }\n }\n } finally {\n rmSafe(tmpDir);\n }\n}\n\nexport async function runUpdate(): Promise<number> {\n const startTime = Date.now();\n const ctx = buildContext();\n const { cfg, channel, checkOnly, force, bdsPath, backupDir, preserve, autoRestart, qqNotify } = ctx;\n\n log.info(`===== \u5F00\u59CB\u68C0\u67E5\u66F4\u65B0 (${channel}) =====`);\n fs.mkdirSync(bdsPath, { recursive: true });\n fs.mkdirSync(backupDir, { recursive: true });\n\n // 1. \u5F53\u524D\u7248\u672C\n const exePath = path.join(bdsPath, \"bedrock_server.exe\");\n const currentVer = await getCurrentVersionAsync(exePath).catch(() => getCurrentVersionSync(exePath));\n log.info(`\u5F53\u524D\u7248\u672C: ${currentVer}`);\n\n // 2. \u83B7\u53D6\u6700\u65B0\u7248\u672C\n let latestVer: string;\n try {\n const info = await getVersionInfo(cfg, channel);\n latestVer = info.version;\n log.info(`\u6700\u65B0\u7248\u672C: ${latestVer}`);\n const cmp = compareVersions(latestVer, currentVer);\n if (cmp <= 0 && !force) {\n log.info(\"\u5DF2\u662F\u6700\u65B0\u7248\u672C\uFF0C\u65E0\u9700\u66F4\u65B0\");\n if (qqNotify) {\n await sendText(`\u2705 BDS \u5DF2\u662F\u6700\u65B0\u7248\u672C\\n\\n\u5F53\u524D: ${currentVer}\\n\u6700\u65B0: ${latestVer}`);\n }\n emitUpdateKv(\"CURRENT\", currentVer, log);\n emitUpdateKv(\"LATEST\", latestVer, log);\n emitUpdateResult(\"uptodate\", log);\n return 0;\n }\n } catch (e) {\n log.error(`\u83B7\u53D6\u7248\u672C\u4FE1\u606F\u5931\u8D25: ${(e as Error).message}`);\n await sendText(`\u274C BDS \u66F4\u65B0\u5931\u8D25\\n\\n\u65E0\u6CD5\u83B7\u53D6\u7248\u672C\u4FE1\u606F: ${(e as Error).message}`);\n return 1;\n }\n\n // \u517C\u5BB9\u6027\u68C0\u67E5\n if (!force && !isVersionCompatible(cfg, latestVer)) {\n log.warn(`${latestVer} \u4E0D\u5728\u517C\u5BB9\u7248\u672C\u767D\u540D\u5355\u4E2D\uFF0C\u8DF3\u8FC7\u5347\u7EA7`);\n if (qqNotify) {\n await sendText(`\u26A0\uFE0F BDS ${latestVer} \u4E0D\u5728\u517C\u5BB9\u6027\u767D\u540D\u5355\uFF0C\u5DF2\u8DF3\u8FC7\u5347\u7EA7\u3002\u8BF7\u4EBA\u5DE5\u786E\u8BA4\u3002`);\n }\n emitUpdateResult(\"skipped\", log);\n return 2;\n }\n\n // 3. \u53D6\u4E0B\u8F7D\u94FE\u63A5\n let downloadUrls: string[];\n let hash: { sha1: string; sha256: string };\n try {\n const details = await fetchVersionDetails(cfg, channel, latestVer);\n downloadUrls = buildDownloadUrls(cfg, channel, latestVer, details);\n hash = { sha1: details.sha1, sha256: details.sha256 };\n } catch (e) {\n log.error(`\u83B7\u53D6\u4E0B\u8F7D\u8BE6\u60C5\u5931\u8D25: ${(e as Error).message}`);\n await sendText(`\u274C BDS \u66F4\u65B0\u5931\u8D25\\n\\n\u4E0B\u8F7D\u8BE6\u60C5\u83B7\u53D6\u5931\u8D25: ${(e as Error).message}`);\n return 1;\n }\n\n if (checkOnly) {\n emitUpdateKv(\"CURRENT\", currentVer, log);\n emitUpdateKv(\"LATEST\", latestVer, log);\n emitUpdateKv(\"CHANNEL\", channel, log);\n emitUpdateKv(\"URLS\", String(downloadUrls.length), log);\n emitUpdateResult(\"check-only\", log);\n return 0;\n }\n\n log.info(`\u53D1\u73B0\u65B0\u7248\u672C: ${currentVer} \u2192 ${latestVer}`);\n\n // 4. QQ \u9884\u544A\n if (qqNotify) {\n await sendText(\n `\uD835\uDC0C\uD835\uDC22\uD835\uDC27\uD835\uDC1E\uD835\uDC1C\uD835\uDC2B\uD835\uDC1A\uD835\uDC1F\uD835\uDC2D \uD835\uDC01\uD835\uDC03\uD835\uDC12 \u66F4\u65B0\u901A\u77E5\\n\\n` +\n `\u68C0\u6D4B\u5230\u65B0\u7248\u672C\uFF01\\n\\n` +\n `\u5F53\u524D: ${currentVer}\\n` +\n `\u6700\u65B0: ${latestVer}\\n` +\n `\u9891\u9053: ${channel === \"preview\" ? \"\u9884\u89C8\u7248\" : \"\u6B63\u5F0F\u7248\"}\\n\\n` +\n `\u670D\u52A1\u5668\u5373\u5C06\u5F00\u59CB\u66F4\u65B0~ \u8BF7\u8010\u5FC3\u7B49\u5F85^(*\uFFE3(oo)\uFFE3)^`\n );\n const cl = await fetchChangelog(channel);\n if (cl) {\n const text = `\uD83D\uDCCB \u66F4\u65B0\u5185\u5BB9\u6982\u8981\\n\\n${cl.text.slice(0, 1500)}\\n\\n\u5B8C\u6574\u65E5\u5FD7: ${CHANGELOG_BASE}`;\n if (cl.imageBase64) await sendWithImage(text, cl.imageBase64);\n else await sendText(text);\n } else {\n await sendText(`\uD83D\uDCCB \u66F4\u65B0\u65E5\u5FD7: ${CHANGELOG_BASE}`);\n }\n }\n\n // 5. \u5907\u4EFD\n let backupInfo: { path: string; size: number };\n try {\n backupInfo = await doBackup(bdsPath, backupDir, preserve);\n log.info(`\u5907\u4EFD\u5B8C\u6210: ${backupInfo.path} (${(backupInfo.size / 1024 / 1024).toFixed(1)} MB)`);\n if (qqNotify) {\n await sendText(`\u2705 \u5907\u4EFD\u5B8C\u6210\\n\\n\u5927\u5C0F: ${(backupInfo.size / 1024 / 1024).toFixed(1)} MB\\n\u4F4D\u7F6E: ${backupInfo.path}`);\n }\n } catch (e) {\n log.error(`\u5907\u4EFD\u5931\u8D25: ${(e as Error).message}`);\n await sendText(`\u274C BDS \u66F4\u65B0\u5931\u8D25\\n\\n\u5907\u4EFD\u5931\u8D25: ${(e as Error).message}\\n\u64CD\u4F5C\u5DF2\u4E2D\u6B62`);\n return 1;\n }\n\n // 6. \u5199\u56DE\u6EDA\u6807\u8BB0 (\u8DE8\u8FDB\u7A0B\u53EF\u6062\u590D)\n writeRollbackMarker({\n timestamp: Date.now(),\n bds_path: bdsPath,\n backup_dir: backupInfo.path,\n preserve,\n previous_version: currentVer,\n });\n\n // 7. \u505C\u670D\n const bds = createBdsManager({ detached: true });\n try {\n log.info(\"\u505C\u6B62 BDS \u670D\u52A1...\");\n await bds.stop();\n log.info(\"BDS \u5DF2\u505C\u6B62\");\n } catch (e) {\n log.warn(`BDS \u505C\u6B62\u5F02\u5E38: ${(e as Error).message}`);\n }\n\n // 8. \u4E0B\u8F7D (\u5168\u90E8\u5931\u8D25\u5219\u56DE\u6EDA)\n // \u7528 mkdtempSync \u521B\u5EFA\u4E34\u65F6 staging \u76EE\u5F55 - \u907F\u514D\u6C61\u67D3 SCRIPT_DIR\n const stagingDir = fs.mkdtempSync(path.join(os.tmpdir(), \"bds-update-\"));\n const zipPath = path.join(stagingDir, `bedrock-server-${latestVer}.zip`);\n let downloaded = false;\n try {\n log.info(`\u5F00\u59CB\u4E0B\u8F7D ${latestVer}...`);\n if (qqNotify) await sendText(`\uD83D\uDCE5 \u6B63\u5728\u4E0B\u8F7D BDS ${latestVer}...`);\n\n let lastErr: Error | null = null;\n const downloadTimeoutMs = (cfg.download_timeout ?? 120) * 1000;\n /* stderr \u88AB pipe \u65F6\u4E0D\u753B bar\uFF1B\u7528\u6587\u672C\u8FDB\u5EA6\u7ED9 sfmc REPL \u7B49\u7236\u8FDB\u7A0B */\n if (isTaskbarSupported() && process.stdout.isTTY) {\n log.info(\"\u68C0\u6D4B\u5230 Windows Terminal,\u4EFB\u52A1\u680F\u8FDB\u5EA6\u5DF2\u542F\u7528 (OSC 9;4)\");\n }\n for (const url of downloadUrls) {\n /* \u6BCF\u6B21\u5C1D\u8BD5\u65B0\u5EFA bar + binder\uFF0C\u907F\u514D\u5931\u8D25\u91CD\u8BD5\u65F6 started \u72B6\u6001\u6B8B\u7559\uFF08LSP\uFF09 */\n const progressBar = createTerminalProgress({\n stream: process.stderr,\n logger: (msg) => log.info(msg.startsWith(\"\u8FDB\u5EA6\") ? `\u4E0B\u8F7D${msg.slice(2)}` : msg),\n format: \"\u4E0B\u8F7D\u8FDB\u5EA6 | {bar} | {percentage}% | {value}/{total} MB | \u901F\u5EA6: {speed}\",\n });\n const onByteProgress = bindByteProgressToBar(progressBar, {\n speedSampleMs: 0,\n onProgress: (dl, total) => {\n const pct = total > 0 ? (dl / total) * 100 : 0;\n setTaskbarProgress(pct);\n },\n });\n try {\n setTaskbarProgress(0);\n await httpDownload(url, zipPath, {\n totalTimeoutMs: Math.max(downloadTimeoutMs, 600_000), // \u4E0D\u5C11\u4E8E 10 \u5206\u949F\n onProgress: onByteProgress,\n });\n if (progressBar.active) progressBar.stop();\n // \u4E0B\u8F7D\u5B8C\u6210,\u4EFB\u52A1\u680F\u6536\u5230 100% \u7EFF\u6761\u540E\u6E05\u6389\n setTaskbarProgress(100);\n clearTaskbarProgress();\n downloaded = true;\n lastErr = null;\n break;\n } catch (e) {\n if (progressBar.active) progressBar.stop();\n // \u4E0B\u8F7D\u5931\u8D25,\u4EFB\u52A1\u680F\u4EAE\u7EA2\n setTaskbarProgress(100, \"error\");\n clearTaskbarProgress();\n lastErr = e as Error;\n log.warn(`${url} \u4E0D\u53EF\u7528: ${lastErr.message}\uFF0C\u5C1D\u8BD5\u5907\u7528\u5730\u5740...`);\n }\n }\n if (!downloaded && lastErr) throw lastErr;\n\n const zipSizeMB = (fs.statSync(zipPath).size / 1024 / 1024).toFixed(1);\n log.info(`\u4E0B\u8F7D\u5B8C\u6210 (${zipSizeMB} MB)`);\n\n // \u6D41\u5F0F\u54C8\u5E0C\u6821\u9A8C\n if (hash.sha1 || hash.sha256) {\n const algo = hash.sha256 ? \"SHA256\" : \"SHA1\";\n log.info(`\u6821\u9A8C\u6587\u4EF6\u5B8C\u6574\u6027 (${algo})...`);\n const ok = await verifyFileHash(zipPath, hash.sha1, hash.sha256);\n if (!ok) throw new Error(`${algo} \u6821\u9A8C\u4E0D\u901A\u8FC7\uFF0C\u6587\u4EF6\u53EF\u80FD\u635F\u574F`);\n log.info(`${algo} \u6821\u9A8C\u901A\u8FC7`);\n }\n } catch (e) {\n log.error(`\u4E0B\u8F7D\u5931\u8D25: ${(e as Error).message}`);\n await sendText(`\u274C BDS \u66F4\u65B0\u5931\u8D25\\n\\n\u4E0B\u8F7D\u5931\u8D25: ${(e as Error).message}\\nBDS \u5DF2\u505C\u6B62\uFF0C\u8BF7\u624B\u52A8\u6062\u590D`);\n // \u81EA\u52A8\u56DE\u6EDA\n rollbackFromBackup({\n timestamp: Date.now(),\n bds_path: bdsPath,\n backup_dir: backupInfo.path,\n preserve,\n previous_version: currentVer,\n });\n rmSafe(stagingDir);\n return 1;\n }\n\n // 9. \u89E3\u538B + \u90E8\u7F72\n try {\n log.info(\"\u89E3\u538B\u4E2D...\");\n // \u5148\u6E05\u7A7A BDS \u76EE\u5F55\n emptyDirSync(bdsPath);\n await extractZipToBds(zipPath, bdsPath);\n log.info(\"\u89E3\u538B\u5B8C\u6210\");\n } catch (e) {\n log.error(`\u89E3\u538B\u5931\u8D25: ${(e as Error).message}`);\n await sendText(`\u274C BDS \u66F4\u65B0\u5931\u8D25\\n\\n\u89E3\u538B\u5931\u8D25: ${(e as Error).message}\\nBDS \u5DF2\u505C\u6B62\uFF0C\u8BF7\u624B\u52A8\u6062\u590D`);\n // \u56DE\u6EDA: \u6E05\u7A7A + \u4ECE\u5907\u4EFD\u6062\u590D preserves\n emptyDirSync(bdsPath);\n await restorePreserves(bdsPath, backupInfo.path, preserve);\n rmSafe(stagingDir);\n return 1;\n } finally {\n rmSafe(zipPath); // \u6E05\u6389 staging zip\n }\n\n // 10. \u5B8C\u6574\u6027\u68C0\u67E5 (\u907F\u514D\u89E3\u538B\u51FA\u7A7A/\u7F3A\u6587\u4EF6\u7684\u75C5\u6001\u5305)\n const verify = verifyBdsInstall(bdsPath, [\n \"bedrock_server.exe\",\n /*\"bedrock_server_symbols.debug\",*/ \"permissions.json\",\n ]);\n if (!verify.ok) {\n log.error(`\u89E3\u538B\u540E\u7684 BDS \u4E0D\u5B8C\u6574\uFF0C\u7F3A\u5931\u6587\u4EF6: ${verify.missing.join(\", \")}`);\n await sendText(`\u274C BDS \u66F4\u65B0\u5931\u8D25\\n\\n\u90E8\u7F72\u540E\u7F3A\u5931\u5173\u952E\u6587\u4EF6: ${verify.missing.join(\", \")}`);\n emptyDirSync(bdsPath);\n await restorePreserves(bdsPath, backupInfo.path, preserve);\n rmSafe(stagingDir);\n return 1;\n }\n\n // 11. \u6062\u590D preserves (zip \u89E3\u538B\u65F6\u8FD9\u4E9B\u76EE\u5F55\u53EF\u80FD\u88AB\u8986\u76D6)\n await restorePreserves(bdsPath, backupInfo.path, preserve);\n\n // 11b. \u5B89\u88C5\u6536\u5C3E\uFF1A\u56E0 EULA \u5DF2\u540C\u610F\uFF0C\u786E\u4FDD\u9065\u6D4B\u5F00\u5173\uFF08\u5DF2\u6709\u5219\u8DF3\u8FC7\uFF09\n ensureEmitServerTelemetry(bdsPath, log);\n\n // 12. \u5199\u5165\u7248\u672C\u7F13\u5B58\n const newExeHash = await hashFileAsync(exePath, \"sha256\").catch(() => \"\");\n if (newExeHash) {\n saveVersionCache(latestVer, newExeHash);\n log.info(`\u5DF2\u8BB0\u5F55\u7248\u672C ${latestVer} \u7684 SHA256`);\n }\n\n // 13. \u542F\u52A8 BDS\n if (autoRestart) {\n try {\n log.info(\"\u542F\u52A8 BDS...\");\n await bds.start();\n } catch (e) {\n log.error(`\u542F\u52A8\u5931\u8D25: ${(e as Error).message}`);\n await sendText(`\u274C BDS \u66F4\u65B0\u5931\u8D25\\n\\n\u542F\u52A8\u5931\u8D25: ${(e as Error).message}\\n\u8BF7\u624B\u52A8\u542F\u52A8 BDS`);\n // \u6CE8\u610F: \u6B64\u65F6 BDS \u5DF2\u7ECF\u90E8\u7F72\u5B8C\u6210\uFF0C\u542F\u52A8\u5931\u8D25 \u2192 \u542F\u52A8\u95EE\u9898\uFF0C\u4E0D\u505A\u6587\u4EF6\u7EA7\u56DE\u6EDA\n rmSafe(stagingDir);\n clearRollbackMarker();\n return 1;\n }\n }\n\n rmSafe(stagingDir);\n clearRollbackMarker();\n\n // 14. QQ \u901A\u77E5\u7ED3\u679C\n const durationMs = Date.now() - startTime;\n if (qqNotify) {\n await sendText(\n `\u2705 BDS \u66F4\u65B0\u5B8C\u6210\\n\\n` +\n `${currentVer} \u2192 ${latestVer}\\n` +\n `\u8017\u65F6: ${(durationMs / 1000).toFixed(1)}s\\n` +\n `${autoRestart ? \"\u670D\u52A1\u5668\u5DF2\u91CD\u65B0\u542F\u52A8\" : \"\u8BF7\u624B\u52A8\u91CD\u542F\u670D\u52A1\u5668\"}`\n );\n }\n log.info(`===== \u66F4\u65B0\u5B8C\u6210 (${(durationMs / 1000).toFixed(1)}s) =====`);\n /* \u673A\u5668\u53EF\u8BFB\u7ED3\u679C\u6807\u8BB0\uFF1A\u4F9B sfmc \u7B49\u76D1\u7763\u5668\u5224\u65AD\u300C\u771F\u6B63\u5B8C\u6210\u90E8\u7F72\u300D\uFF0C\u52FF\u4F9D\u8D56\u672C\u5730\u5316\u65E5\u5FD7\u6587\u6848\u3002 */\n emitUpdateResult(\"deployed\", log);\n return 0;\n}\n\nfunction isMain(): boolean {\n // sfmc supervisor \u901A\u8FC7 SFMC_SERVICE \u62C9\u8D77\u5B50\u8FDB\u7A0B\u65F6\u4F18\u5148\u5224\u5B9A\n if (process.env.SFMC_SERVICE === \"update\") return true;\n return isMainModule(import.meta.url);\n}\n\nif (isMain()) {\n runUpdate()\n .then((code) => {\n closeLog();\n process.exit(code);\n })\n .catch((e) => {\n log.error(`\u672A\u6355\u83B7\u9519\u8BEF: ${(e as Error).message}`);\n closeLog();\n process.exit(1);\n });\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * check-update.ts \u2014 BDS \u81EA\u52A8\u66F4\u65B0\u5668 (\u4E3B\u6D41\u7A0B)\n *\n * 1. \u4E34\u65F6 staging \u76EE\u5F55 (mkdtempSync) - \u907F\u514D\u6C61\u67D3\u6570\u636E\u6839\n * 2. \u4E0B\u8F7D/\u89E3\u538B\u5931\u8D25 \u2192 \u81EA\u52A8\u4ECE\u5907\u4EFD\u56DE\u6EDA preserves\n * 3. \u6D41\u5F0F SHA256 \u6821\u9A8C - \u4E0D\u628A 250MB \u6587\u4EF6\u8BFB\u5165\u5185\u5B58\n * 4. \u517C\u5BB9\u7248\u672C\u767D\u540D\u5355 - \u4E0D\u5339\u914D\u5219\u8DF3\u8FC7\u5347\u7EA7\n * 5. QQ \u901A\u77E5\u7EDF\u4E00\u52A0 5s \u8D85\u65F6 - \u6C38\u8FDC\u4E0D\u963B\u585E\u4E3B\u6D41\u7A0B\n * 6. Rollback marker \u843D\u76D8\u5230 <ROOT>/.sfmc/ - \u8DE8\u8FDB\u7A0B / \u8DE8\u91CD\u542F\u53EF\u6062\u590D\n */\n\nimport {\n bindByteProgressToBar,\n createNodeServiceLogger,\n createTerminalProgress,\n} from \"@sfmc-bds/sdk/logs\";\nimport fs from \"node:fs\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport { createBdsManager } from \"./bds-manager.js\";\nimport { CHANGELOG_BASE, fetchChangelog } from \"./changelog.js\";\nimport { copyDirSync, emptyDirSync, hashFileAsync, rmSafe } from \"./fsx.js\";\nimport { bdsExePath, bdsInstallRequiredFiles, ensureBdsExecutable } from \"./host-platform.js\";\nimport { httpDownload } from \"./http.js\";\nimport { isMainModule } from \"./is-main.js\";\nimport { loadConfig, LOG_PATH, resolvePaths } from \"./paths.js\";\nimport { sendText, sendWithImage } from \"./qqutil.js\";\nimport {\n clearRollbackMarker,\n getDirSize,\n rollbackFromBackup,\n verifyBdsInstall,\n writeRollbackMarker,\n} from \"./rollback.js\";\nimport { ensureEmitServerTelemetry } from \"./server-properties.js\";\nimport { clearTaskbarProgress, isTaskbarSupported, setTaskbarProgress } from \"./taskbar.js\";\nimport { emitUpdateKv, emitUpdateResult } from \"./update-result.js\";\nimport {\n buildDownloadUrls,\n fetchVersionDetails,\n getVersionInfo,\n isVersionCompatible,\n verifyFileHash,\n} from \"./upstream.js\";\nimport { compareVersions, getCurrentVersionAsync, getCurrentVersionSync, saveVersionCache } from \"./version.js\";\nimport { extractZipFileToDir } from \"./zipx.js\";\n\n// \u72EC\u7ACB\u5165\u53E3:source = \"updater\",\u4E0E bds-manager \u7684 \"bds-tools\" \u533A\u5206;\u540C\u843D\u76D8 bds-update.log\nconst log = createNodeServiceLogger({ source: \"updater\", logPath: LOG_PATH });\nconst closeLog = (): void => log.close();\n\nfunction parseArgs(argv: string[]): Record<string, string | boolean> {\n const out: Record<string, string | boolean> = {};\n for (const a of argv) {\n const m = a.match(/^--([\\w-]+)(?:=(.+))?$/);\n if (m) out[m[1]!] = m[2] || true;\n }\n return out;\n}\n\ninterface UpdateContext {\n cfg: ReturnType<typeof loadConfig>;\n channel: \"release\" | \"preview\" | string;\n checkOnly: boolean;\n force: boolean;\n bdsPath: string;\n backupDir: string;\n preserve: string[];\n autoRestart: boolean;\n qqNotify: boolean;\n}\n\nfunction buildContext(): UpdateContext {\n const cfg = loadConfig();\n const args = parseArgs(process.argv.slice(2));\n const { bds_path, backup_dir, preserve } = resolvePaths(cfg);\n const channel = String(args[\"channel\"] || cfg.channel || \"release\");\n return {\n cfg,\n channel,\n checkOnly: !!args[\"check-only\"],\n force: !!args[\"force\"],\n bdsPath: bds_path,\n backupDir: backup_dir,\n preserve,\n autoRestart: !args[\"no-start\"] && cfg.auto_restart !== false,\n qqNotify: !!cfg.qq_notify,\n };\n}\n\nasync function doBackup(\n bdsPath: string,\n backupDir: string,\n preserve: string[]\n): Promise<{ path: string; size: number }> {\n const dateStr = new Date().toISOString().slice(0, 10);\n const dest = path.join(backupDir, dateStr);\n fs.mkdirSync(dest, { recursive: true });\n\n let anyCopied = false;\n for (const item of preserve) {\n const src = path.join(bdsPath, item);\n const target = path.join(dest, item);\n if (!fs.existsSync(src)) continue;\n fs.mkdirSync(path.dirname(target), { recursive: true });\n if (fs.statSync(src).isDirectory()) copyDirSync(src, target);\n else fs.copyFileSync(src, target);\n anyCopied = true;\n log.info(`\u5DF2\u5907\u4EFD: ${item}`);\n }\n\n // \u5373\u4F7F\u5168\u90E8 preserve \u90FD\u8DF3\u8FC7\uFF0C\u4E5F\u8BA9\u76EE\u5F55\u5B58\u5728\u4EE5\u4FBF\u8BB0\u5F55\u65F6\u95F4\u6233\n if (!anyCopied) {\n log.info(`\u6CA1\u6709\u9700\u8981\u5907\u4EFD\u7684\u6587\u4EF6 (preserve \u5217\u8868\u4E3A\u7A7A\u6216\u5168\u90E8\u7F3A\u5931)`);\n }\n return { path: dest, size: getDirSize(dest) };\n}\n\n/** \u5F02\u6B65\u6062\u590D preserves \u4ECE\u5907\u4EFD\u5230 BDS \u8DEF\u5F84 */\nasync function restorePreserves(bdsPath: string, backupDir: string, preserve: string[]): Promise<void> {\n for (const item of preserve) {\n const src = path.join(backupDir, item);\n const dest = path.join(bdsPath, item);\n if (!fs.existsSync(src)) continue;\n try {\n if (fs.statSync(src).isDirectory()) {\n if (fs.existsSync(dest)) emptyDirSync(dest);\n copyDirSync(src, dest);\n } else {\n fs.mkdirSync(path.dirname(dest), { recursive: true });\n fs.copyFileSync(src, dest);\n }\n log.info(`\u5DF2\u6062\u590D: ${item}`);\n } catch (e) {\n log.warn(`\u6062\u590D\u5931\u8D25 ${item}: ${(e as Error).message}`);\n }\n }\n}\n\n/** \u628A zip \u89E3\u538B\u5230 destDir (\u8986\u76D6) \u2014 \u7ECF zipx \u5B89\u5168\u89E3\u538B */\nasync function extractZipToBds(zipPath: string, destDir: string): Promise<void> {\n // \u62BD\u51FA\u5230\u4E34\u65F6\u76EE\u5F55\uFF0C\u907F\u514D\u65E7\u5185\u5BB9\u5E72\u6270\n const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), \"bds-extract-\"));\n try {\n await extractZipFileToDir(zipPath, tmpDir);\n // \u628A\u4E34\u65F6\u76EE\u5F55\u91CC\u7684\u5185\u5BB9\u590D\u5236\u5230 BDS \u8DEF\u5F84\n for (const entry of fs.readdirSync(tmpDir)) {\n const srcPath = path.join(tmpDir, entry);\n const destPath = path.join(destDir, entry);\n if (fs.statSync(srcPath).isDirectory()) {\n if (fs.existsSync(destPath)) emptyDirSync(destPath);\n copyDirSync(srcPath, destPath);\n } else {\n fs.copyFileSync(srcPath, destPath);\n }\n }\n } finally {\n rmSafe(tmpDir);\n }\n}\n\nexport async function runUpdate(): Promise<number> {\n const startTime = Date.now();\n const ctx = buildContext();\n const { cfg, channel, checkOnly, force, bdsPath, backupDir, preserve, autoRestart, qqNotify } = ctx;\n\n log.info(`===== \u5F00\u59CB\u68C0\u67E5\u66F4\u65B0 (${channel}) =====`);\n fs.mkdirSync(bdsPath, { recursive: true });\n fs.mkdirSync(backupDir, { recursive: true });\n\n // 1. \u5F53\u524D\u7248\u672C\n const exePath = bdsExePath(bdsPath);\n const currentVer = await getCurrentVersionAsync(exePath).catch(() => getCurrentVersionSync(exePath));\n log.info(`\u5F53\u524D\u7248\u672C: ${currentVer}`);\n\n // 2. \u83B7\u53D6\u6700\u65B0\u7248\u672C\n let latestVer: string;\n try {\n const info = await getVersionInfo(cfg, channel);\n latestVer = info.version;\n log.info(`\u6700\u65B0\u7248\u672C: ${latestVer}`);\n const cmp = compareVersions(latestVer, currentVer);\n if (cmp <= 0 && !force) {\n log.info(\"\u5DF2\u662F\u6700\u65B0\u7248\u672C\uFF0C\u65E0\u9700\u66F4\u65B0\");\n if (qqNotify) {\n await sendText(`\u2705 BDS \u5DF2\u662F\u6700\u65B0\u7248\u672C\\n\\n\u5F53\u524D: ${currentVer}\\n\u6700\u65B0: ${latestVer}`);\n }\n emitUpdateKv(\"CURRENT\", currentVer, log);\n emitUpdateKv(\"LATEST\", latestVer, log);\n emitUpdateResult(\"uptodate\", log);\n return 0;\n }\n } catch (e) {\n log.error(`\u83B7\u53D6\u7248\u672C\u4FE1\u606F\u5931\u8D25: ${(e as Error).message}`);\n await sendText(`\u274C BDS \u66F4\u65B0\u5931\u8D25\\n\\n\u65E0\u6CD5\u83B7\u53D6\u7248\u672C\u4FE1\u606F: ${(e as Error).message}`);\n return 1;\n }\n\n // \u517C\u5BB9\u6027\u68C0\u67E5\n if (!force && !isVersionCompatible(cfg, latestVer)) {\n log.warn(`${latestVer} \u4E0D\u5728\u517C\u5BB9\u7248\u672C\u767D\u540D\u5355\u4E2D\uFF0C\u8DF3\u8FC7\u5347\u7EA7`);\n if (qqNotify) {\n await sendText(`\u26A0\uFE0F BDS ${latestVer} \u4E0D\u5728\u517C\u5BB9\u6027\u767D\u540D\u5355\uFF0C\u5DF2\u8DF3\u8FC7\u5347\u7EA7\u3002\u8BF7\u4EBA\u5DE5\u786E\u8BA4\u3002`);\n }\n emitUpdateResult(\"skipped\", log);\n return 2;\n }\n\n // 3. \u53D6\u4E0B\u8F7D\u94FE\u63A5\n let downloadUrls: string[];\n let hash: { sha1: string; sha256: string };\n try {\n const details = await fetchVersionDetails(cfg, channel, latestVer);\n downloadUrls = buildDownloadUrls(cfg, channel, latestVer, details);\n hash = { sha1: details.sha1, sha256: details.sha256 };\n } catch (e) {\n log.error(`\u83B7\u53D6\u4E0B\u8F7D\u8BE6\u60C5\u5931\u8D25: ${(e as Error).message}`);\n await sendText(`\u274C BDS \u66F4\u65B0\u5931\u8D25\\n\\n\u4E0B\u8F7D\u8BE6\u60C5\u83B7\u53D6\u5931\u8D25: ${(e as Error).message}`);\n return 1;\n }\n\n if (checkOnly) {\n emitUpdateKv(\"CURRENT\", currentVer, log);\n emitUpdateKv(\"LATEST\", latestVer, log);\n emitUpdateKv(\"CHANNEL\", channel, log);\n emitUpdateKv(\"URLS\", String(downloadUrls.length), log);\n emitUpdateResult(\"check-only\", log);\n return 0;\n }\n\n log.info(`\u53D1\u73B0\u65B0\u7248\u672C: ${currentVer} \u2192 ${latestVer}`);\n\n // 4. QQ \u9884\u544A\n if (qqNotify) {\n await sendText(\n `\uD835\uDC0C\uD835\uDC22\uD835\uDC27\uD835\uDC1E\uD835\uDC1C\uD835\uDC2B\uD835\uDC1A\uD835\uDC1F\uD835\uDC2D \uD835\uDC01\uD835\uDC03\uD835\uDC12 \u66F4\u65B0\u901A\u77E5\\n\\n` +\n `\u68C0\u6D4B\u5230\u65B0\u7248\u672C\uFF01\\n\\n` +\n `\u5F53\u524D: ${currentVer}\\n` +\n `\u6700\u65B0: ${latestVer}\\n` +\n `\u9891\u9053: ${channel === \"preview\" ? \"\u9884\u89C8\u7248\" : \"\u6B63\u5F0F\u7248\"}\\n\\n` +\n `\u670D\u52A1\u5668\u5373\u5C06\u5F00\u59CB\u66F4\u65B0~ \u8BF7\u8010\u5FC3\u7B49\u5F85^(*\uFFE3(oo)\uFFE3)^`\n );\n const cl = await fetchChangelog(channel);\n if (cl) {\n const text = `\uD83D\uDCCB \u66F4\u65B0\u5185\u5BB9\u6982\u8981\\n\\n${cl.text.slice(0, 1500)}\\n\\n\u5B8C\u6574\u65E5\u5FD7: ${CHANGELOG_BASE}`;\n if (cl.imageBase64) await sendWithImage(text, cl.imageBase64);\n else await sendText(text);\n } else {\n await sendText(`\uD83D\uDCCB \u66F4\u65B0\u65E5\u5FD7: ${CHANGELOG_BASE}`);\n }\n }\n\n // 5. \u5907\u4EFD\n let backupInfo: { path: string; size: number };\n try {\n backupInfo = await doBackup(bdsPath, backupDir, preserve);\n log.info(`\u5907\u4EFD\u5B8C\u6210: ${backupInfo.path} (${(backupInfo.size / 1024 / 1024).toFixed(1)} MB)`);\n if (qqNotify) {\n await sendText(`\u2705 \u5907\u4EFD\u5B8C\u6210\\n\\n\u5927\u5C0F: ${(backupInfo.size / 1024 / 1024).toFixed(1)} MB\\n\u4F4D\u7F6E: ${backupInfo.path}`);\n }\n } catch (e) {\n log.error(`\u5907\u4EFD\u5931\u8D25: ${(e as Error).message}`);\n await sendText(`\u274C BDS \u66F4\u65B0\u5931\u8D25\\n\\n\u5907\u4EFD\u5931\u8D25: ${(e as Error).message}\\n\u64CD\u4F5C\u5DF2\u4E2D\u6B62`);\n return 1;\n }\n\n // 6. \u5199\u56DE\u6EDA\u6807\u8BB0 (\u8DE8\u8FDB\u7A0B\u53EF\u6062\u590D)\n writeRollbackMarker({\n timestamp: Date.now(),\n bds_path: bdsPath,\n backup_dir: backupInfo.path,\n preserve,\n previous_version: currentVer,\n });\n\n // 7. \u505C\u670D\n const bds = createBdsManager({ detached: true });\n try {\n log.info(\"\u505C\u6B62 BDS \u670D\u52A1...\");\n await bds.stop();\n log.info(\"BDS \u5DF2\u505C\u6B62\");\n } catch (e) {\n log.warn(`BDS \u505C\u6B62\u5F02\u5E38: ${(e as Error).message}`);\n }\n\n // 8. \u4E0B\u8F7D (\u5168\u90E8\u5931\u8D25\u5219\u56DE\u6EDA)\n // \u7528 mkdtempSync \u521B\u5EFA\u4E34\u65F6 staging \u76EE\u5F55 - \u907F\u514D\u6C61\u67D3 SCRIPT_DIR\n const stagingDir = fs.mkdtempSync(path.join(os.tmpdir(), \"bds-update-\"));\n const zipPath = path.join(stagingDir, `bedrock-server-${latestVer}.zip`);\n let downloaded = false;\n try {\n log.info(`\u5F00\u59CB\u4E0B\u8F7D ${latestVer}...`);\n if (qqNotify) await sendText(`\uD83D\uDCE5 \u6B63\u5728\u4E0B\u8F7D BDS ${latestVer}...`);\n\n let lastErr: Error | null = null;\n const downloadTimeoutMs = (cfg.download_timeout ?? 120) * 1000;\n /* stderr \u88AB pipe \u65F6\u4E0D\u753B bar\uFF1B\u7528\u6587\u672C\u8FDB\u5EA6\u7ED9 sfmc REPL \u7B49\u7236\u8FDB\u7A0B */\n if (isTaskbarSupported() && process.stdout.isTTY) {\n log.info(\"\u68C0\u6D4B\u5230 Windows Terminal,\u4EFB\u52A1\u680F\u8FDB\u5EA6\u5DF2\u542F\u7528 (OSC 9;4)\");\n }\n for (const url of downloadUrls) {\n /* \u6BCF\u6B21\u5C1D\u8BD5\u65B0\u5EFA bar + binder\uFF0C\u907F\u514D\u5931\u8D25\u91CD\u8BD5\u65F6 started \u72B6\u6001\u6B8B\u7559\uFF08LSP\uFF09 */\n const progressBar = createTerminalProgress({\n stream: process.stderr,\n logger: (msg) => log.info(msg.startsWith(\"\u8FDB\u5EA6\") ? `\u4E0B\u8F7D${msg.slice(2)}` : msg),\n format: \"\u4E0B\u8F7D\u8FDB\u5EA6 | {bar} | {percentage}% | {value}/{total} MB | \u901F\u5EA6: {speed}\",\n });\n const onByteProgress = bindByteProgressToBar(progressBar, {\n speedSampleMs: 0,\n onProgress: (dl, total) => {\n const pct = total > 0 ? (dl / total) * 100 : 0;\n setTaskbarProgress(pct);\n },\n });\n try {\n setTaskbarProgress(0);\n await httpDownload(url, zipPath, {\n totalTimeoutMs: Math.max(downloadTimeoutMs, 600_000), // \u4E0D\u5C11\u4E8E 10 \u5206\u949F\n onProgress: onByteProgress,\n });\n if (progressBar.active) progressBar.stop();\n // \u4E0B\u8F7D\u5B8C\u6210,\u4EFB\u52A1\u680F\u6536\u5230 100% \u7EFF\u6761\u540E\u6E05\u6389\n setTaskbarProgress(100);\n clearTaskbarProgress();\n downloaded = true;\n lastErr = null;\n break;\n } catch (e) {\n if (progressBar.active) progressBar.stop();\n // \u4E0B\u8F7D\u5931\u8D25,\u4EFB\u52A1\u680F\u4EAE\u7EA2\n setTaskbarProgress(100, \"error\");\n clearTaskbarProgress();\n lastErr = e as Error;\n log.warn(`${url} \u4E0D\u53EF\u7528: ${lastErr.message}\uFF0C\u5C1D\u8BD5\u5907\u7528\u5730\u5740...`);\n }\n }\n if (!downloaded && lastErr) throw lastErr;\n\n const zipSizeMB = (fs.statSync(zipPath).size / 1024 / 1024).toFixed(1);\n log.info(`\u4E0B\u8F7D\u5B8C\u6210 (${zipSizeMB} MB)`);\n\n // \u6D41\u5F0F\u54C8\u5E0C\u6821\u9A8C\n if (hash.sha1 || hash.sha256) {\n const algo = hash.sha256 ? \"SHA256\" : \"SHA1\";\n log.info(`\u6821\u9A8C\u6587\u4EF6\u5B8C\u6574\u6027 (${algo})...`);\n const ok = await verifyFileHash(zipPath, hash.sha1, hash.sha256);\n if (!ok) throw new Error(`${algo} \u6821\u9A8C\u4E0D\u901A\u8FC7\uFF0C\u6587\u4EF6\u53EF\u80FD\u635F\u574F`);\n log.info(`${algo} \u6821\u9A8C\u901A\u8FC7`);\n }\n } catch (e) {\n log.error(`\u4E0B\u8F7D\u5931\u8D25: ${(e as Error).message}`);\n await sendText(`\u274C BDS \u66F4\u65B0\u5931\u8D25\\n\\n\u4E0B\u8F7D\u5931\u8D25: ${(e as Error).message}\\nBDS \u5DF2\u505C\u6B62\uFF0C\u8BF7\u624B\u52A8\u6062\u590D`);\n // \u81EA\u52A8\u56DE\u6EDA\n rollbackFromBackup({\n timestamp: Date.now(),\n bds_path: bdsPath,\n backup_dir: backupInfo.path,\n preserve,\n previous_version: currentVer,\n });\n rmSafe(stagingDir);\n return 1;\n }\n\n // 9. \u89E3\u538B + \u90E8\u7F72\n try {\n log.info(\"\u89E3\u538B\u4E2D...\");\n // \u5148\u6E05\u7A7A BDS \u76EE\u5F55\n emptyDirSync(bdsPath);\n await extractZipToBds(zipPath, bdsPath);\n ensureBdsExecutable(exePath);\n log.info(\"\u89E3\u538B\u5B8C\u6210\");\n } catch (e) {\n log.error(`\u89E3\u538B\u5931\u8D25: ${(e as Error).message}`);\n await sendText(`\u274C BDS \u66F4\u65B0\u5931\u8D25\\n\\n\u89E3\u538B\u5931\u8D25: ${(e as Error).message}\\nBDS \u5DF2\u505C\u6B62\uFF0C\u8BF7\u624B\u52A8\u6062\u590D`);\n // \u56DE\u6EDA: \u6E05\u7A7A + \u4ECE\u5907\u4EFD\u6062\u590D preserves\n emptyDirSync(bdsPath);\n await restorePreserves(bdsPath, backupInfo.path, preserve);\n rmSafe(stagingDir);\n return 1;\n } finally {\n rmSafe(zipPath); // \u6E05\u6389 staging zip\n }\n\n // 10. \u5B8C\u6574\u6027\u68C0\u67E5 (\u907F\u514D\u89E3\u538B\u51FA\u7A7A/\u7F3A\u6587\u4EF6\u7684\u75C5\u6001\u5305)\n const verify = verifyBdsInstall(bdsPath, bdsInstallRequiredFiles());\n if (!verify.ok) {\n log.error(`\u89E3\u538B\u540E\u7684 BDS \u4E0D\u5B8C\u6574\uFF0C\u7F3A\u5931\u6587\u4EF6: ${verify.missing.join(\", \")}`);\n await sendText(`\u274C BDS \u66F4\u65B0\u5931\u8D25\\n\\n\u90E8\u7F72\u540E\u7F3A\u5931\u5173\u952E\u6587\u4EF6: ${verify.missing.join(\", \")}`);\n emptyDirSync(bdsPath);\n await restorePreserves(bdsPath, backupInfo.path, preserve);\n rmSafe(stagingDir);\n return 1;\n }\n\n // 11. \u6062\u590D preserves (zip \u89E3\u538B\u65F6\u8FD9\u4E9B\u76EE\u5F55\u53EF\u80FD\u88AB\u8986\u76D6)\n await restorePreserves(bdsPath, backupInfo.path, preserve);\n\n // 11b. \u5B89\u88C5\u6536\u5C3E\uFF1A\u56E0 EULA \u5DF2\u540C\u610F\uFF0C\u786E\u4FDD\u9065\u6D4B\u5F00\u5173\uFF08\u5DF2\u6709\u5219\u8DF3\u8FC7\uFF09\n ensureEmitServerTelemetry(bdsPath, log);\n\n // 12. \u5199\u5165\u7248\u672C\u7F13\u5B58\n const newExeHash = await hashFileAsync(exePath, \"sha256\").catch(() => \"\");\n if (newExeHash) {\n saveVersionCache(latestVer, newExeHash);\n log.info(`\u5DF2\u8BB0\u5F55\u7248\u672C ${latestVer} \u7684 SHA256`);\n }\n\n // 13. \u542F\u52A8 BDS\n if (autoRestart) {\n try {\n log.info(\"\u542F\u52A8 BDS...\");\n await bds.start();\n } catch (e) {\n log.error(`\u542F\u52A8\u5931\u8D25: ${(e as Error).message}`);\n await sendText(`\u274C BDS \u66F4\u65B0\u5931\u8D25\\n\\n\u542F\u52A8\u5931\u8D25: ${(e as Error).message}\\n\u8BF7\u624B\u52A8\u542F\u52A8 BDS`);\n // \u6CE8\u610F: \u6B64\u65F6 BDS \u5DF2\u7ECF\u90E8\u7F72\u5B8C\u6210\uFF0C\u542F\u52A8\u5931\u8D25 \u2192 \u542F\u52A8\u95EE\u9898\uFF0C\u4E0D\u505A\u6587\u4EF6\u7EA7\u56DE\u6EDA\n rmSafe(stagingDir);\n clearRollbackMarker();\n return 1;\n }\n }\n\n rmSafe(stagingDir);\n clearRollbackMarker();\n\n // 14. QQ \u901A\u77E5\u7ED3\u679C\n const durationMs = Date.now() - startTime;\n if (qqNotify) {\n await sendText(\n `\u2705 BDS \u66F4\u65B0\u5B8C\u6210\\n\\n` +\n `${currentVer} \u2192 ${latestVer}\\n` +\n `\u8017\u65F6: ${(durationMs / 1000).toFixed(1)}s\\n` +\n `${autoRestart ? \"\u670D\u52A1\u5668\u5DF2\u91CD\u65B0\u542F\u52A8\" : \"\u8BF7\u624B\u52A8\u91CD\u542F\u670D\u52A1\u5668\"}`\n );\n }\n log.info(`===== \u66F4\u65B0\u5B8C\u6210 (${(durationMs / 1000).toFixed(1)}s) =====`);\n /* \u673A\u5668\u53EF\u8BFB\u7ED3\u679C\u6807\u8BB0\uFF1A\u4F9B sfmc \u7B49\u76D1\u7763\u5668\u5224\u65AD\u300C\u771F\u6B63\u5B8C\u6210\u90E8\u7F72\u300D\uFF0C\u52FF\u4F9D\u8D56\u672C\u5730\u5316\u65E5\u5FD7\u6587\u6848\u3002 */\n emitUpdateResult(\"deployed\", log);\n return 0;\n}\n\nfunction isMain(): boolean {\n // sfmc supervisor \u901A\u8FC7 SFMC_SERVICE \u62C9\u8D77\u5B50\u8FDB\u7A0B\u65F6\u4F18\u5148\u5224\u5B9A\n if (process.env.SFMC_SERVICE === \"update\") return true;\n return isMainModule(import.meta.url);\n}\n\nif (isMain()) {\n runUpdate()\n .then((code) => {\n closeLog();\n process.exit(code);\n })\n .catch((e) => {\n log.error(`\u672A\u6355\u83B7\u9519\u8BEF: ${(e as Error).message}`);\n closeLog();\n process.exit(1);\n });\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
package/dist/fsx.d.ts CHANGED
@@ -3,7 +3,7 @@
3
3
  */
4
4
  /**
5
5
  * 流式计算文件哈希 (sha1 / sha256),
6
- * 用于大文件 (例如 bedrock_server.exe ~80MB),不会 OOM。
6
+ * 用于大文件 (例如 BDS 可执行文件 ~80MB),不会 OOM。
7
7
  */
8
8
  export declare function hashFileAsync(filePath: string, algo?: "sha1" | "sha256"): Promise<string>;
9
9
  /** 同步版本(用于小文件) */
@@ -24,12 +24,7 @@ export declare function rmSafe(path: string): void;
24
24
  export declare function writeFileSafe(filePath: string, data: string | Buffer): void;
25
25
  /**
26
26
  * 读 JSON 文件(utf8)。
27
- * 若文件以 UTF-8 BOM(U+FEFF)开头则剥离后再解析(兼容记事本「UTF-8 with BOM」)。
28
- * Utf8BomError 已弃用且不再抛出,保留类仅供旧调用方类型兼容。
27
+ * 若文件以 UTF-8 BOM(U+FEFF)开头则剥离后再解析(记事本「UTF-8 with BOM」)。
29
28
  */
30
- export declare class Utf8BomError extends Error {
31
- readonly filePath: string;
32
- constructor(filePath: string);
33
- }
34
29
  export declare function readJsonFile<T = unknown>(filePath: string): T;
35
30
  //# sourceMappingURL=fsx.d.ts.map
package/dist/fsx.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"fsx.d.ts","sourceRoot":"","sources":["../src/fsx.ts"],"names":[],"mappings":"AAAA;;GAEG;AAOH;;;GAGG;AACH,wBAAsB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,GAAE,MAAM,GAAG,QAAmB,GAAG,OAAO,CAAC,MAAM,CAAC,CAUzG;AAED,kBAAkB;AAClB,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,GAAE,MAAM,GAAG,QAAmB,GAAG,MAAM,CAQzF;AAED,sBAAsB;AACtB,wBAAsB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE5E;AAED,kBAAkB;AAClB,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAW3D;AAED,mBAAmB;AACnB,wBAAsB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAc3E;AAED,kBAAkB;AAClB,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAU9C;AAED,yBAAyB;AACzB,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAY9C;AAED,eAAe;AACf,wBAAgB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAMzC;AAED,iCAAiC;AACjC,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAM3E;AAED;;;;GAIG;AACH,qBAAa,YAAa,SAAQ,KAAK;IACrC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,YAAY,QAAQ,EAAE,MAAM,EAM3B;CACF;AAED,wBAAgB,YAAY,CAAC,CAAC,GAAG,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,CAAC,CAM7D"}
1
+ {"version":3,"file":"fsx.d.ts","sourceRoot":"","sources":["../src/fsx.ts"],"names":[],"mappings":"AAAA;;GAEG;AAOH;;;GAGG;AACH,wBAAsB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,GAAE,MAAM,GAAG,QAAmB,GAAG,OAAO,CAAC,MAAM,CAAC,CAUzG;AAED,kBAAkB;AAClB,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,GAAE,MAAM,GAAG,QAAmB,GAAG,MAAM,CAQzF;AAED,sBAAsB;AACtB,wBAAsB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE5E;AAED,kBAAkB;AAClB,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAW3D;AAED,mBAAmB;AACnB,wBAAsB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAc3E;AAED,kBAAkB;AAClB,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAU9C;AAED,yBAAyB;AACzB,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAY9C;AAED,eAAe;AACf,wBAAgB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAMzC;AAED,iCAAiC;AACjC,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAM3E;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,CAAC,GAAG,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,CAAC,CAM7D"}
package/dist/fsx.js CHANGED
@@ -89,16 +89,6 @@ function writeFileSafe(filePath, data) {
89
89
  fs.writeFileSync(tmp, data);
90
90
  fs.renameSync(tmp, filePath);
91
91
  }
92
- class Utf8BomError extends Error {
93
- filePath;
94
- constructor(filePath) {
95
- super(
96
- `UTF-8 BOM in ${filePath}: re-save as UTF-8 without BOM (Notepad "UTF-8 with BOM" is not valid for Bedrock packs)`
97
- );
98
- this.name = "Utf8BomError";
99
- this.filePath = filePath;
100
- }
101
- }
102
92
  function readJsonFile(filePath) {
103
93
  let text = fs.readFileSync(filePath, "utf8");
104
94
  if (text.length > 0 && text.charCodeAt(0) === 65279) {
@@ -107,7 +97,6 @@ function readJsonFile(filePath) {
107
97
  return JSON.parse(text);
108
98
  }
109
99
  export {
110
- Utf8BomError,
111
100
  copyDirAsync,
112
101
  copyDirSync,
113
102
  copyFileAsync,
package/dist/fsx.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/fsx.ts"],
4
- "sourcesContent": ["/**\n * fsx.ts \u2014 \u5F02\u6B65/\u6D41\u5F0F\u6587\u4EF6\u64CD\u4F5C (\u907F\u514D\u5927\u6587\u4EF6\u52A0\u8F7D\u8FDB\u5185\u5B58)\n */\n\nimport crypto from \"node:crypto\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { pipeline } from \"node:stream/promises\";\n\n/**\n * \u6D41\u5F0F\u8BA1\u7B97\u6587\u4EF6\u54C8\u5E0C (sha1 / sha256)\uFF0C\n * \u7528\u4E8E\u5927\u6587\u4EF6 (\u4F8B\u5982 bedrock_server.exe ~80MB)\uFF0C\u4E0D\u4F1A OOM\u3002\n */\nexport async function hashFileAsync(filePath: string, algo: \"sha1\" | \"sha256\" = \"sha256\"): Promise<string> {\n return new Promise((resolve, reject) => {\n const h = crypto.createHash(algo);\n const stream = fs.createReadStream(filePath);\n stream.on(\"data\", (chunk: Buffer | string) => {\n h.update(typeof chunk === \"string\" ? Buffer.from(chunk) : chunk);\n });\n stream.on(\"end\", () => resolve(h.digest(\"hex\").toLowerCase()));\n stream.on(\"error\", reject);\n });\n}\n\n/** \u540C\u6B65\u7248\u672C\uFF08\u7528\u4E8E\u5C0F\u6587\u4EF6\uFF09 */\nexport function hashFileSync(filePath: string, algo: \"sha1\" | \"sha256\" = \"sha256\"): string {\n try {\n const h = crypto.createHash(algo);\n h.update(fs.readFileSync(filePath));\n return h.digest(\"hex\").toLowerCase();\n } catch {\n return \"\";\n }\n}\n\n/** \u540C\u6B65\u6D41\u5F0F\u62F7\u8D1D\u5355\u6587\u4EF6 (\u590D\u5236\u4E2D) */\nexport async function copyFileAsync(src: string, dest: string): Promise<void> {\n await pipeline(fs.createReadStream(src), fs.createWriteStream(dest));\n}\n\n/** \u540C\u6B65\u76EE\u5F55\u590D\u5236 (\u9012\u5F52) */\nexport function copyDirSync(src: string, dest: string): void {\n fs.mkdirSync(dest, { recursive: true });\n for (const entry of fs.readdirSync(src)) {\n const srcPath = path.join(src, entry);\n const destPath = path.join(dest, entry);\n if (fs.statSync(srcPath).isDirectory()) {\n copyDirSync(srcPath, destPath);\n } else {\n fs.copyFileSync(srcPath, destPath);\n }\n }\n}\n\n/** \u5F02\u6B65\u76EE\u5F55\u590D\u5236 (\u57FA\u4E8E\u6D41) */\nexport async function copyDirAsync(src: string, dest: string): Promise<void> {\n fs.mkdirSync(dest, { recursive: true });\n await Promise.all(\n fs.readdirSync(src).map(async (entry) => {\n const srcPath = path.join(src, entry);\n const destPath = path.join(dest, entry);\n const stat = fs.statSync(srcPath);\n if (stat.isDirectory()) {\n await copyDirAsync(srcPath, destPath);\n } else {\n await copyFileAsync(srcPath, destPath);\n }\n })\n );\n}\n\n/** \u8BA1\u7B97\u76EE\u5F55\u5927\u5C0F (\u5B57\u8282) */\nexport function getDirSize(dir: string): number {\n let total = 0;\n try {\n for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {\n const full = path.join(dir, entry.name);\n if (entry.isDirectory()) total += getDirSize(full);\n else if (entry.isFile()) total += fs.statSync(full).size;\n }\n } catch {}\n return total;\n}\n\n/** \u5F3A\u5236\u6E05\u7A7A\u76EE\u5F55\u5185\u5BB9 (\u4F46\u4FDD\u7559\u76EE\u5F55\u672C\u8EAB) */\nexport function emptyDirSync(dir: string): void {\n if (!fs.existsSync(dir)) return;\n for (const entry of fs.readdirSync(dir)) {\n const full = path.join(dir, entry);\n try {\n const stat = fs.statSync(full);\n if (stat.isDirectory()) fs.rmSync(full, { recursive: true, force: true });\n else fs.unlinkSync(full);\n } catch (e) {\n // \u5FFD\u7565: \u9876\u5C42\u4ECD\u4FDD\u7559\u76EE\u5F55\uFF0C\u5373\u4F7F\u90E8\u5206\u5B50\u9879\u65E0\u6CD5\u5220\u9664\n }\n }\n}\n\n/** \u5B89\u5168\u5220\u9664\u6574\u4E2A\u76EE\u5F55 */\nexport function rmSafe(path: string): void {\n try {\n fs.rmSync(path, { recursive: true, force: true });\n } catch {\n /* ignore */\n }\n}\n\n/** \u5B89\u5168\u5199\u6587\u4EF6 (\u539F\u5B50: \u5199\u4E34\u65F6\u6587\u4EF6 \u2192 rename) */\nexport function writeFileSafe(filePath: string, data: string | Buffer): void {\n const dir = path.dirname(filePath);\n fs.mkdirSync(dir, { recursive: true });\n const tmp = `${filePath}.${process.pid}.tmp`;\n fs.writeFileSync(tmp, data);\n fs.renameSync(tmp, filePath);\n}\n\n/**\n * \u8BFB JSON \u6587\u4EF6\uFF08utf8\uFF09\u3002\n * \u82E5\u6587\u4EF6\u4EE5 UTF-8 BOM\uFF08U+FEFF\uFF09\u5F00\u5934\u5219\u5265\u79BB\u540E\u518D\u89E3\u6790\uFF08\u517C\u5BB9\u8BB0\u4E8B\u672C\u300CUTF-8 with BOM\u300D\uFF09\u3002\n * Utf8BomError \u5DF2\u5F03\u7528\u4E14\u4E0D\u518D\u629B\u51FA\uFF0C\u4FDD\u7559\u7C7B\u4EC5\u4F9B\u65E7\u8C03\u7528\u65B9\u7C7B\u578B\u517C\u5BB9\u3002\n */\nexport class Utf8BomError extends Error {\n readonly filePath: string;\n constructor(filePath: string) {\n super(\n `UTF-8 BOM in ${filePath}: re-save as UTF-8 without BOM (Notepad \"UTF-8 with BOM\" is not valid for Bedrock packs)`\n );\n this.name = \"Utf8BomError\";\n this.filePath = filePath;\n }\n}\n\nexport function readJsonFile<T = unknown>(filePath: string): T {\n let text = fs.readFileSync(filePath, \"utf8\");\n if (text.length > 0 && text.charCodeAt(0) === 0xfeff) {\n text = text.slice(1);\n }\n return JSON.parse(text) as T;\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * fsx.ts \u2014 \u5F02\u6B65/\u6D41\u5F0F\u6587\u4EF6\u64CD\u4F5C (\u907F\u514D\u5927\u6587\u4EF6\u52A0\u8F7D\u8FDB\u5185\u5B58)\n */\n\nimport crypto from \"node:crypto\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { pipeline } from \"node:stream/promises\";\n\n/**\n * \u6D41\u5F0F\u8BA1\u7B97\u6587\u4EF6\u54C8\u5E0C (sha1 / sha256)\uFF0C\n * \u7528\u4E8E\u5927\u6587\u4EF6 (\u4F8B\u5982 BDS \u53EF\u6267\u884C\u6587\u4EF6 ~80MB)\uFF0C\u4E0D\u4F1A OOM\u3002\n */\nexport async function hashFileAsync(filePath: string, algo: \"sha1\" | \"sha256\" = \"sha256\"): Promise<string> {\n return new Promise((resolve, reject) => {\n const h = crypto.createHash(algo);\n const stream = fs.createReadStream(filePath);\n stream.on(\"data\", (chunk: Buffer | string) => {\n h.update(typeof chunk === \"string\" ? Buffer.from(chunk) : chunk);\n });\n stream.on(\"end\", () => resolve(h.digest(\"hex\").toLowerCase()));\n stream.on(\"error\", reject);\n });\n}\n\n/** \u540C\u6B65\u7248\u672C\uFF08\u7528\u4E8E\u5C0F\u6587\u4EF6\uFF09 */\nexport function hashFileSync(filePath: string, algo: \"sha1\" | \"sha256\" = \"sha256\"): string {\n try {\n const h = crypto.createHash(algo);\n h.update(fs.readFileSync(filePath));\n return h.digest(\"hex\").toLowerCase();\n } catch {\n return \"\";\n }\n}\n\n/** \u540C\u6B65\u6D41\u5F0F\u62F7\u8D1D\u5355\u6587\u4EF6 (\u590D\u5236\u4E2D) */\nexport async function copyFileAsync(src: string, dest: string): Promise<void> {\n await pipeline(fs.createReadStream(src), fs.createWriteStream(dest));\n}\n\n/** \u540C\u6B65\u76EE\u5F55\u590D\u5236 (\u9012\u5F52) */\nexport function copyDirSync(src: string, dest: string): void {\n fs.mkdirSync(dest, { recursive: true });\n for (const entry of fs.readdirSync(src)) {\n const srcPath = path.join(src, entry);\n const destPath = path.join(dest, entry);\n if (fs.statSync(srcPath).isDirectory()) {\n copyDirSync(srcPath, destPath);\n } else {\n fs.copyFileSync(srcPath, destPath);\n }\n }\n}\n\n/** \u5F02\u6B65\u76EE\u5F55\u590D\u5236 (\u57FA\u4E8E\u6D41) */\nexport async function copyDirAsync(src: string, dest: string): Promise<void> {\n fs.mkdirSync(dest, { recursive: true });\n await Promise.all(\n fs.readdirSync(src).map(async (entry) => {\n const srcPath = path.join(src, entry);\n const destPath = path.join(dest, entry);\n const stat = fs.statSync(srcPath);\n if (stat.isDirectory()) {\n await copyDirAsync(srcPath, destPath);\n } else {\n await copyFileAsync(srcPath, destPath);\n }\n })\n );\n}\n\n/** \u8BA1\u7B97\u76EE\u5F55\u5927\u5C0F (\u5B57\u8282) */\nexport function getDirSize(dir: string): number {\n let total = 0;\n try {\n for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {\n const full = path.join(dir, entry.name);\n if (entry.isDirectory()) total += getDirSize(full);\n else if (entry.isFile()) total += fs.statSync(full).size;\n }\n } catch {}\n return total;\n}\n\n/** \u5F3A\u5236\u6E05\u7A7A\u76EE\u5F55\u5185\u5BB9 (\u4F46\u4FDD\u7559\u76EE\u5F55\u672C\u8EAB) */\nexport function emptyDirSync(dir: string): void {\n if (!fs.existsSync(dir)) return;\n for (const entry of fs.readdirSync(dir)) {\n const full = path.join(dir, entry);\n try {\n const stat = fs.statSync(full);\n if (stat.isDirectory()) fs.rmSync(full, { recursive: true, force: true });\n else fs.unlinkSync(full);\n } catch (e) {\n // \u5FFD\u7565: \u9876\u5C42\u4ECD\u4FDD\u7559\u76EE\u5F55\uFF0C\u5373\u4F7F\u90E8\u5206\u5B50\u9879\u65E0\u6CD5\u5220\u9664\n }\n }\n}\n\n/** \u5B89\u5168\u5220\u9664\u6574\u4E2A\u76EE\u5F55 */\nexport function rmSafe(path: string): void {\n try {\n fs.rmSync(path, { recursive: true, force: true });\n } catch {\n /* ignore */\n }\n}\n\n/** \u5B89\u5168\u5199\u6587\u4EF6 (\u539F\u5B50: \u5199\u4E34\u65F6\u6587\u4EF6 \u2192 rename) */\nexport function writeFileSafe(filePath: string, data: string | Buffer): void {\n const dir = path.dirname(filePath);\n fs.mkdirSync(dir, { recursive: true });\n const tmp = `${filePath}.${process.pid}.tmp`;\n fs.writeFileSync(tmp, data);\n fs.renameSync(tmp, filePath);\n}\n\n/**\n * \u8BFB JSON \u6587\u4EF6\uFF08utf8\uFF09\u3002\n * \u82E5\u6587\u4EF6\u4EE5 UTF-8 BOM\uFF08U+FEFF\uFF09\u5F00\u5934\u5219\u5265\u79BB\u540E\u518D\u89E3\u6790\uFF08\u8BB0\u4E8B\u672C\u300CUTF-8 with BOM\u300D\uFF09\u3002\n */\nexport function readJsonFile<T = unknown>(filePath: string): T {\n let text = fs.readFileSync(filePath, \"utf8\");\n if (text.length > 0 && text.charCodeAt(0) === 0xfeff) {\n text = text.slice(1);\n }\n return JSON.parse(text) as T;\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["path"]
7
7
  }
@@ -0,0 +1,25 @@
1
+ /**
2
+ * host-platform.ts — BDS 宿主平台契约(单一权威来源)
3
+ *
4
+ * Windows / Linux 官方 BDS 的可执行文件名、CDN 路径、启动环境不同。
5
+ * 启动器与更新器只依赖本模块,禁止在业务里再写 bedrock_server.exe / bin-win。
6
+ * macOS 无官方 BDS,按 linux 处理(调用方应避免在 darwin 上当生产宿主)。
7
+ */
8
+ export type BdsHostOs = "windows" | "linux";
9
+ export declare function bdsHostOs(platform?: NodeJS.Platform): BdsHostOs;
10
+ export declare function bdsExeName(os?: BdsHostOs): string;
11
+ export declare function bdsExePath(bdsPath: string, os?: BdsHostOs): string;
12
+ /** BDS-Versions 详情 JSON 的 platform 段:windows / windows_preview / linux / linux_preview */
13
+ export declare function bdsDetailsPlatformKey(channel: string, os?: BdsHostOs): string;
14
+ /** minecraft.net / azureedge CDN 上的 zip 相对路径 */
15
+ export declare function bdsCdnZipSuffix(channel: string, version: string, os?: BdsHostOs): string;
16
+ /** 解压后完整性检查的必备相对路径 */
17
+ export declare function bdsInstallRequiredFiles(os?: BdsHostOs): string[];
18
+ /**
19
+ * 仅返回需覆盖进 spawn env 的键。
20
+ * Linux 官方 BDS 依赖同目录 lib*.so,须把安装目录放进 LD_LIBRARY_PATH。
21
+ */
22
+ export declare function bdsSpawnEnvExtra(bdsPath: string, os?: BdsHostOs): Record<string, string>;
23
+ /** Linux zip 解压后往往没有 +x,启动前补上 */
24
+ export declare function ensureBdsExecutable(exePath: string, os?: BdsHostOs): void;
25
+ //# sourceMappingURL=host-platform.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"host-platform.d.ts","sourceRoot":"","sources":["../src/host-platform.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH,MAAM,MAAM,SAAS,GAAG,SAAS,GAAG,OAAO,CAAC;AAE5C,wBAAgB,SAAS,CAAC,QAAQ,kBAAmB,GAAG,SAAS,CAEhE;AAED,wBAAgB,UAAU,CAAC,EAAE,GAAE,SAAuB,GAAG,MAAM,CAE9D;AAED,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,GAAE,SAAuB,GAAG,MAAM,CAE/E;AAED,0FAA0F;AAC1F,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,GAAE,SAAuB,GAAG,MAAM,CAI1F;AAED,gDAAgD;AAChD,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,GAAE,SAAuB,GAAG,MAAM,CAUrG;AAED,sBAAsB;AACtB,wBAAgB,uBAAuB,CAAC,EAAE,GAAE,SAAuB,GAAG,MAAM,EAAE,CAE7E;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,GAAE,SAAuB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAKrG;AAED,iCAAiC;AACjC,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,GAAE,SAAuB,GAAG,IAAI,CAOtF"}