@sfmc-bds/bds-tools 0.2.0-beta.0 → 0.2.0-beta.10
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.
- package/LICENSE +663 -0
- package/dist/bds-manager.d.ts +16 -6
- package/dist/bds-manager.d.ts.map +1 -1
- package/dist/bds-manager.js +40 -65
- package/dist/bds-manager.js.map +2 -2
- package/dist/check-update.d.ts.map +1 -1
- package/dist/check-update.js +15 -17
- package/dist/check-update.js.map +2 -2
- package/dist/cli-pack-manager.js +7 -3
- package/dist/cli-pack-manager.js.map +2 -2
- package/dist/fsx.d.ts +6 -1
- package/dist/fsx.d.ts.map +1 -1
- package/dist/fsx.js +9 -1
- package/dist/fsx.js.map +2 -2
- package/dist/host-platform.d.ts +25 -0
- package/dist/host-platform.d.ts.map +1 -0
- package/dist/host-platform.js +50 -0
- package/dist/host-platform.js.map +7 -0
- package/dist/http.d.ts +49 -11
- package/dist/http.d.ts.map +1 -1
- package/dist/http.js.map +2 -2
- package/dist/log.d.ts +2 -3
- package/dist/log.d.ts.map +1 -1
- package/dist/log.js +0 -1
- package/dist/log.js.map +2 -2
- package/dist/pack-manager-lifecycle.test.js +252 -0
- package/dist/pack-manager-lifecycle.test.js.map +7 -0
- package/dist/pack-manager.d.ts +24 -29
- package/dist/pack-manager.d.ts.map +1 -1
- package/dist/pack-manager.js +11 -4
- package/dist/pack-manager.js.map +2 -2
- package/dist/pack-update/bindings.d.ts +16 -0
- package/dist/pack-update/bindings.d.ts.map +1 -0
- package/dist/pack-update/bindings.js +69 -0
- package/dist/pack-update/bindings.js.map +7 -0
- package/dist/pack-update/config.d.ts +16 -0
- package/dist/pack-update/config.d.ts.map +1 -0
- package/dist/pack-update/config.js +146 -0
- package/dist/pack-update/config.js.map +7 -0
- package/dist/pack-update/config.test.js +75 -0
- package/dist/pack-update/config.test.js.map +7 -0
- package/dist/pack-update/deps.d.ts +28 -0
- package/dist/pack-update/deps.d.ts.map +1 -0
- package/dist/pack-update/deps.js +20 -0
- package/dist/pack-update/deps.js.map +7 -0
- package/dist/pack-update/index.d.ts +55 -0
- package/dist/pack-update/index.d.ts.map +1 -0
- package/dist/pack-update/index.js +72 -0
- package/dist/pack-update/index.js.map +7 -0
- package/dist/pack-update/providers/curseforge.d.ts +23 -0
- package/dist/pack-update/providers/curseforge.d.ts.map +1 -0
- package/dist/pack-update/providers/curseforge.js +229 -0
- package/dist/pack-update/providers/curseforge.js.map +7 -0
- package/dist/pack-update/providers/index.d.ts +16 -0
- package/dist/pack-update/providers/index.d.ts.map +1 -0
- package/dist/pack-update/providers/index.js +37 -0
- package/dist/pack-update/providers/index.js.map +7 -0
- package/dist/pack-update/service.d.ts +28 -0
- package/dist/pack-update/service.d.ts.map +1 -0
- package/dist/pack-update/service.js +570 -0
- package/dist/pack-update/service.js.map +7 -0
- package/dist/pack-update/types.d.ts +126 -0
- package/dist/pack-update/types.d.ts.map +1 -0
- package/dist/pack-update/types.js +8 -0
- package/dist/pack-update/types.js.map +7 -0
- package/dist/pack-update/version-policy.d.ts +81 -0
- package/dist/pack-update/version-policy.d.ts.map +1 -0
- package/dist/pack-update/version-policy.js +210 -0
- package/dist/pack-update/version-policy.js.map +7 -0
- package/dist/pack-update/version-policy.test.js +137 -0
- package/dist/pack-update/version-policy.test.js.map +7 -0
- package/dist/paths.d.ts +1 -1
- package/dist/paths.d.ts.map +1 -1
- package/dist/paths.js +3 -5
- package/dist/paths.js.map +2 -2
- package/dist/process-probe.d.ts +34 -0
- package/dist/process-probe.d.ts.map +1 -0
- package/dist/process-probe.js +152 -0
- package/dist/process-probe.js.map +7 -0
- package/dist/process-probe.test.js +76 -0
- package/dist/process-probe.test.js.map +7 -0
- package/dist/qq-events-notify.d.ts +16 -0
- package/dist/qq-events-notify.d.ts.map +1 -0
- package/dist/qq-events-notify.js +70 -0
- package/dist/qq-events-notify.js.map +7 -0
- package/dist/qqutil.d.ts +10 -5
- package/dist/qqutil.d.ts.map +1 -1
- package/dist/qqutil.js +49 -8
- package/dist/qqutil.js.map +2 -2
- package/dist/update-result.d.ts +8 -2
- package/dist/update-result.d.ts.map +1 -1
- package/dist/update-result.js +7 -5
- package/dist/update-result.js.map +2 -2
- package/dist/upstream.d.ts +18 -9
- package/dist/upstream.d.ts.map +1 -1
- package/dist/upstream.js +8 -7
- package/dist/upstream.js.map +2 -2
- package/dist/version.js +2 -2
- package/dist/version.js.map +2 -2
- package/dist/world-packs.d.ts +158 -5
- package/dist/world-packs.d.ts.map +1 -1
- package/dist/world-packs.js +294 -48
- package/dist/world-packs.js.map +2 -2
- package/dist/world-packs.test.js +676 -0
- package/dist/world-packs.test.js.map +7 -0
- package/dist/zipx.test.js +36 -0
- package/dist/zipx.test.js.map +7 -0
- package/package.json +43 -39
package/dist/bds-manager.d.ts
CHANGED
|
@@ -1,23 +1,33 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* bds-manager.ts — BDS
|
|
2
|
+
* bds-manager.ts — Bedrock Dedicated Server (BDS) 进程生命周期管理器
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
4
|
+
* 核心职责:
|
|
5
|
+
* - 优雅停服:向标准输入发送 `stop` 命令等待自然退出,超时后逐步升级至 SIGTERM 与 SIGKILL
|
|
6
|
+
* - 守护监视(watch):监听进程退出事件并在异常退出时自动延时重启恢复
|
|
7
|
+
* - 生命周期事件广播:分发启动、停止、崩溃等事件,触发运维告警与状态同步
|
|
8
|
+
* - 管道交互与探活:检测进程存活状态并向 BDS stdin 投递控制台指令
|
|
9
9
|
*/
|
|
10
10
|
import { EventEmitter } from "node:events";
|
|
11
|
+
/** BDS 进程管理器统一操作接口。 */
|
|
11
12
|
export interface BdsManager {
|
|
13
|
+
/** 启动 BDS 服务进程。 */
|
|
12
14
|
start(): Promise<void>;
|
|
15
|
+
/** 优雅停止 BDS 服务进程。 */
|
|
13
16
|
stop(): Promise<void>;
|
|
17
|
+
/** 查询 BDS 进程当前是否处于运行状态。 */
|
|
14
18
|
status(): Promise<boolean>;
|
|
19
|
+
/** 向 BDS 控制台管道发送指令。 */
|
|
15
20
|
sendCommand(cmd: string): boolean;
|
|
21
|
+
/** 开启守护监视模式(异常退出时自动拉起)。 */
|
|
16
22
|
watch(): Promise<void>;
|
|
23
|
+
/** 进程生命周期事件发射器。 */
|
|
17
24
|
events: EventEmitter;
|
|
25
|
+
/** 当前是否属于主动调用停服。 */
|
|
18
26
|
isManualStop: boolean;
|
|
27
|
+
/** 获取当前运行中 BDS 进程的 PID。 */
|
|
19
28
|
getPid(): number;
|
|
20
29
|
}
|
|
30
|
+
/** BDS 进程启动选项。 */
|
|
21
31
|
export interface BdsManagerOptions {
|
|
22
32
|
detached?: boolean;
|
|
23
33
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bds-manager.d.ts","sourceRoot":"","sources":["../src/bds-manager.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;
|
|
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,uBAAuB;AACvB,MAAM,WAAW,UAAU;IACzB,mBAAmB;IACnB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,qBAAqB;IACrB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACtB,2BAA2B;IAC3B,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IAC3B,uBAAuB;IACvB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;IAClC,2BAA2B;IAC3B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,mBAAmB;IACnB,MAAM,EAAE,YAAY,CAAC;IACrB,oBAAoB;IACpB,YAAY,EAAE,OAAO,CAAC;IACtB,2BAA2B;IAC3B,MAAM,IAAI,MAAM,CAAC;CAClB;AAED,kBAAkB;AAClB,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AA+BD,wBAAgB,gBAAgB,CAAC,OAAO,GAAE,iBAAsB,GAAG,UAAU,CAiL5E;AAED,eAAO,MAAM,SAAS,EAAE,YAAiC,CAAC;AAC1D,eAAO,MAAM,iBAAiB,QAAO,IAEpC,CAAC"}
|
package/dist/bds-manager.js
CHANGED
|
@@ -1,52 +1,27 @@
|
|
|
1
|
-
import { spawn
|
|
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 {
|
|
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
|
-
|
|
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 =
|
|
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 =
|
|
66
|
-
if (!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
|
-
|
|
85
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 =
|
|
136
|
-
if (existing && await
|
|
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(`
|
|
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
|
-
|
|
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
|
-
|
|
139
|
+
clearBdsPidFile(ROOT_DIR);
|
|
169
140
|
p.process = null;
|
|
170
|
-
|
|
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 =
|
|
181
|
-
const alive = pid > 0 && await
|
|
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
|
-
|
|
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 =
|
|
194
|
-
if (!pid || !await
|
|
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 ??
|
|
181
|
+
return p.process?.pid ?? readBdsPidFile(ROOT_DIR);
|
|
207
182
|
};
|
|
208
183
|
return {
|
|
209
184
|
start,
|
package/dist/bds-manager.js.map
CHANGED
|
@@ -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": "AAUA,SAAS,
|
|
4
|
+
"sourcesContent": ["/**\n * bds-manager.ts \u2014 Bedrock Dedicated Server (BDS) \u8FDB\u7A0B\u751F\u547D\u5468\u671F\u7BA1\u7406\u5668\n *\n * \u6838\u5FC3\u804C\u8D23\uFF1A\n * - \u4F18\u96C5\u505C\u670D\uFF1A\u5411\u6807\u51C6\u8F93\u5165\u53D1\u9001 `stop` \u547D\u4EE4\u7B49\u5F85\u81EA\u7136\u9000\u51FA\uFF0C\u8D85\u65F6\u540E\u9010\u6B65\u5347\u7EA7\u81F3 SIGTERM \u4E0E SIGKILL\n * - \u5B88\u62A4\u76D1\u89C6\uFF08watch\uFF09\uFF1A\u76D1\u542C\u8FDB\u7A0B\u9000\u51FA\u4E8B\u4EF6\u5E76\u5728\u5F02\u5E38\u9000\u51FA\u65F6\u81EA\u52A8\u5EF6\u65F6\u91CD\u542F\u6062\u590D\n * - \u751F\u547D\u5468\u671F\u4E8B\u4EF6\u5E7F\u64AD\uFF1A\u5206\u53D1\u542F\u52A8\u3001\u505C\u6B62\u3001\u5D29\u6E83\u7B49\u4E8B\u4EF6\uFF0C\u89E6\u53D1\u8FD0\u7EF4\u544A\u8B66\u4E0E\u72B6\u6001\u540C\u6B65\n * - \u7BA1\u9053\u4EA4\u4E92\u4E0E\u63A2\u6D3B\uFF1A\u68C0\u6D4B\u8FDB\u7A0B\u5B58\u6D3B\u72B6\u6001\u5E76\u5411 BDS stdin \u6295\u9012\u63A7\u5236\u53F0\u6307\u4EE4\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\n/** BDS \u8FDB\u7A0B\u7BA1\u7406\u5668\u7EDF\u4E00\u64CD\u4F5C\u63A5\u53E3\u3002 */\nexport interface BdsManager {\n /** \u542F\u52A8 BDS \u670D\u52A1\u8FDB\u7A0B\u3002 */\n start(): Promise<void>;\n /** \u4F18\u96C5\u505C\u6B62 BDS \u670D\u52A1\u8FDB\u7A0B\u3002 */\n stop(): Promise<void>;\n /** \u67E5\u8BE2 BDS \u8FDB\u7A0B\u5F53\u524D\u662F\u5426\u5904\u4E8E\u8FD0\u884C\u72B6\u6001\u3002 */\n status(): Promise<boolean>;\n /** \u5411 BDS \u63A7\u5236\u53F0\u7BA1\u9053\u53D1\u9001\u6307\u4EE4\u3002 */\n sendCommand(cmd: string): boolean;\n /** \u5F00\u542F\u5B88\u62A4\u76D1\u89C6\u6A21\u5F0F\uFF08\u5F02\u5E38\u9000\u51FA\u65F6\u81EA\u52A8\u62C9\u8D77\uFF09\u3002 */\n watch(): Promise<void>;\n /** \u8FDB\u7A0B\u751F\u547D\u5468\u671F\u4E8B\u4EF6\u53D1\u5C04\u5668\u3002 */\n events: EventEmitter;\n /** \u5F53\u524D\u662F\u5426\u5C5E\u4E8E\u4E3B\u52A8\u8C03\u7528\u505C\u670D\u3002 */\n isManualStop: boolean;\n /** \u83B7\u53D6\u5F53\u524D\u8FD0\u884C\u4E2D BDS \u8FDB\u7A0B\u7684 PID\u3002 */\n getPid(): number;\n}\n\n/** BDS \u8FDB\u7A0B\u542F\u52A8\u9009\u9879\u3002 */\nexport interface BdsManagerOptions {\n detached?: boolean;\n}\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": "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",
|
|
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;
|
|
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"}
|
package/dist/check-update.js
CHANGED
|
@@ -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";
|
|
@@ -22,7 +23,7 @@ import {
|
|
|
22
23
|
} from "./rollback.js";
|
|
23
24
|
import { ensureEmitServerTelemetry } from "./server-properties.js";
|
|
24
25
|
import { clearTaskbarProgress, isTaskbarSupported, setTaskbarProgress } from "./taskbar.js";
|
|
25
|
-
import { emitUpdateResult } from "./update-result.js";
|
|
26
|
+
import { emitUpdateKv, emitUpdateResult } from "./update-result.js";
|
|
26
27
|
import {
|
|
27
28
|
buildDownloadUrls,
|
|
28
29
|
fetchVersionDetails,
|
|
@@ -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 =
|
|
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;
|
|
@@ -140,9 +141,9 @@ async function runUpdate() {
|
|
|
140
141
|
\u5F53\u524D: ${currentVer}
|
|
141
142
|
\u6700\u65B0: ${latestVer}`);
|
|
142
143
|
}
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
emitUpdateResult("uptodate");
|
|
144
|
+
emitUpdateKv("CURRENT", currentVer, log);
|
|
145
|
+
emitUpdateKv("LATEST", latestVer, log);
|
|
146
|
+
emitUpdateResult("uptodate", log);
|
|
146
147
|
return 0;
|
|
147
148
|
}
|
|
148
149
|
} catch (e) {
|
|
@@ -157,7 +158,7 @@ async function runUpdate() {
|
|
|
157
158
|
if (qqNotify) {
|
|
158
159
|
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`);
|
|
159
160
|
}
|
|
160
|
-
emitUpdateResult("skipped");
|
|
161
|
+
emitUpdateResult("skipped", log);
|
|
161
162
|
return 2;
|
|
162
163
|
}
|
|
163
164
|
let downloadUrls;
|
|
@@ -174,11 +175,11 @@ async function runUpdate() {
|
|
|
174
175
|
return 1;
|
|
175
176
|
}
|
|
176
177
|
if (checkOnly) {
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
emitUpdateResult("check-only");
|
|
178
|
+
emitUpdateKv("CURRENT", currentVer, log);
|
|
179
|
+
emitUpdateKv("LATEST", latestVer, log);
|
|
180
|
+
emitUpdateKv("CHANNEL", channel, log);
|
|
181
|
+
emitUpdateKv("URLS", String(downloadUrls.length), log);
|
|
182
|
+
emitUpdateResult("check-only", log);
|
|
182
183
|
return 0;
|
|
183
184
|
}
|
|
184
185
|
log.info(`\u53D1\u73B0\u65B0\u7248\u672C: ${currentVer} \u2192 ${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
|
|
@@ -379,7 +377,7 @@ ${autoRestart ? "\u670D\u52A1\u5668\u5DF2\u91CD\u65B0\u542F\u52A8" : "\u8BF7\u62
|
|
|
379
377
|
);
|
|
380
378
|
}
|
|
381
379
|
log.info(`===== \u66F4\u65B0\u5B8C\u6210 (${(durationMs / 1e3).toFixed(1)}s) =====`);
|
|
382
|
-
emitUpdateResult("deployed");
|
|
380
|
+
emitUpdateResult("deployed", log);
|
|
383
381
|
return 0;
|
|
384
382
|
}
|
|
385
383
|
function isMain() {
|
package/dist/check-update.js.map
CHANGED
|
@@ -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 { 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 console.log(`CURRENT=${currentVer}`);\n console.log(`LATEST=${latestVer}`);\n emitUpdateResult(\"uptodate\");\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\");\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 console.log(`CURRENT=${currentVer}`);\n console.log(`LATEST=${latestVer}`);\n console.log(`CHANNEL=${channel}`);\n console.log(`URLS=${downloadUrls.length}`);\n emitUpdateResult(\"check-only\");\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\");\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": "AAWA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,OAAO,QAAQ;AACf,OAAO,QAAQ;AACf,OAAO,UAAU;AACjB,SAAS,wBAAwB;AACjC,SAAS,gBAAgB,sBAAsB;AAC/C,SAAS,aAAa,cAAc,eAAe,cAAc;AACjE,SAAS,oBAAoB;AAC7B,SAAS,oBAAoB;AAC7B,SAAS,YAAY,UAAU,oBAAoB;AACnD,SAAS,UAAU,qBAAqB;AACxC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,iCAAiC;AAC1C,SAAS,sBAAsB,oBAAoB,0BAA0B;AAC7E,SAAS,wBAAwB;
|
|
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/cli-pack-manager.js
CHANGED
|
@@ -227,10 +227,14 @@ async function main() {
|
|
|
227
227
|
}
|
|
228
228
|
{
|
|
229
229
|
const root = need(args, "root");
|
|
230
|
-
const depth = args["max-depth"] ? Number(args["max-depth"]) :
|
|
231
|
-
const
|
|
232
|
-
|
|
230
|
+
const depth = args["max-depth"] ? Number(args["max-depth"]) : 4;
|
|
231
|
+
const resolved = await wp.resolvePackRoots(path.resolve(root), { maxDirDepth: depth });
|
|
232
|
+
try {
|
|
233
|
+
process.stdout.write(`${JSON.stringify(resolved.roots)}
|
|
233
234
|
`);
|
|
235
|
+
} finally {
|
|
236
|
+
resolved.dispose();
|
|
237
|
+
}
|
|
234
238
|
return;
|
|
235
239
|
}
|
|
236
240
|
}
|