@sfmc-bds/bds-tools 0.1.0

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 (70) hide show
  1. package/README.md +18 -0
  2. package/dist/bds-manager.d.ts +27 -0
  3. package/dist/bds-manager.d.ts.map +1 -0
  4. package/dist/bds-manager.js +294 -0
  5. package/dist/bds-manager.js.map +1 -0
  6. package/dist/changelog.d.ts +9 -0
  7. package/dist/changelog.d.ts.map +1 -0
  8. package/dist/changelog.js +59 -0
  9. package/dist/changelog.js.map +1 -0
  10. package/dist/check-update.d.ts +12 -0
  11. package/dist/check-update.d.ts.map +1 -0
  12. package/dist/check-update.js +442 -0
  13. package/dist/check-update.js.map +1 -0
  14. package/dist/cli-pack-manager.d.ts +19 -0
  15. package/dist/cli-pack-manager.d.ts.map +1 -0
  16. package/dist/cli-pack-manager.js +154 -0
  17. package/dist/cli-pack-manager.js.map +1 -0
  18. package/dist/fsx.d.ts +25 -0
  19. package/dist/fsx.d.ts.map +1 -0
  20. package/dist/fsx.js +117 -0
  21. package/dist/fsx.js.map +1 -0
  22. package/dist/http.d.ts +37 -0
  23. package/dist/http.d.ts.map +1 -0
  24. package/dist/http.js +203 -0
  25. package/dist/http.js.map +1 -0
  26. package/dist/log.d.ts +13 -0
  27. package/dist/log.d.ts.map +1 -0
  28. package/dist/log.js +22 -0
  29. package/dist/log.js.map +1 -0
  30. package/dist/logger.d.ts +10 -0
  31. package/dist/logger.d.ts.map +1 -0
  32. package/dist/logger.js +10 -0
  33. package/dist/logger.js.map +1 -0
  34. package/dist/pack-manager.d.ts +136 -0
  35. package/dist/pack-manager.d.ts.map +1 -0
  36. package/dist/pack-manager.js +264 -0
  37. package/dist/pack-manager.js.map +1 -0
  38. package/dist/paths.d.ts +28 -0
  39. package/dist/paths.d.ts.map +1 -0
  40. package/dist/paths.js +47 -0
  41. package/dist/paths.js.map +1 -0
  42. package/dist/qqutil.d.ts +13 -0
  43. package/dist/qqutil.d.ts.map +1 -0
  44. package/dist/qqutil.js +101 -0
  45. package/dist/qqutil.js.map +1 -0
  46. package/dist/recovery.d.ts +8 -0
  47. package/dist/recovery.d.ts.map +1 -0
  48. package/dist/recovery.js +45 -0
  49. package/dist/recovery.js.map +1 -0
  50. package/dist/rollback.d.ts +36 -0
  51. package/dist/rollback.d.ts.map +1 -0
  52. package/dist/rollback.js +87 -0
  53. package/dist/rollback.js.map +1 -0
  54. package/dist/taskbar.d.ts +42 -0
  55. package/dist/taskbar.d.ts.map +1 -0
  56. package/dist/taskbar.js +94 -0
  57. package/dist/taskbar.js.map +1 -0
  58. package/dist/types.d.ts +56 -0
  59. package/dist/types.d.ts.map +1 -0
  60. package/dist/types.js +5 -0
  61. package/dist/types.js.map +1 -0
  62. package/dist/upstream.d.ts +20 -0
  63. package/dist/upstream.d.ts.map +1 -0
  64. package/dist/upstream.js +126 -0
  65. package/dist/upstream.js.map +1 -0
  66. package/dist/version.d.ts +20 -0
  67. package/dist/version.d.ts.map +1 -0
  68. package/dist/version.js +97 -0
  69. package/dist/version.js.map +1 -0
  70. package/package.json +62 -0
@@ -0,0 +1,87 @@
1
+ /**
2
+ * rollback.ts — 回滚支持
3
+ *
4
+ * 在更新开始前记录: 当前 BDS 目录 + 备份目录。
5
+ * 主流程任意阶段失败时,尝试反向恢复 preserves 到 BDS_PATH,
6
+ * 然后从备份重新放回 preserve 内容,恢复旧配置。
7
+ *
8
+ * 持久化: ROLLBACK_MARKER (BDSTools/.last_update_rollback.json) 用于跨进程记录。
9
+ */
10
+ import { readJson, writeJson } from "@sfmc-bds/sdk/node/config";
11
+ import fs from "node:fs";
12
+ import path from "node:path";
13
+ import { ROLLBACK_MARKER } from "./paths.js";
14
+ import { copyDirSync, getDirSize, emptyDirSync } from "./fsx.js";
15
+ import { log } from "./log.js";
16
+ /** 在备份完成后调用: 记录快照指示符。 */
17
+ export function writeRollbackMarker(marker) {
18
+ try {
19
+ writeJson(ROLLBACK_MARKER, marker);
20
+ log.info(`[回滚] 已记录回滚标记 -> ${ROLLBACK_MARKER}`);
21
+ }
22
+ catch (e) {
23
+ log.warn(`[回滚] 无法写入标记: ${e.message}`);
24
+ }
25
+ }
26
+ export function clearRollbackMarker() {
27
+ try {
28
+ if (fs.existsSync(ROLLBACK_MARKER))
29
+ fs.unlinkSync(ROLLBACK_MARKER);
30
+ }
31
+ catch {
32
+ /* ignore */
33
+ }
34
+ }
35
+ export function readRollbackMarker() {
36
+ return readJson(ROLLBACK_MARKER) ?? null;
37
+ }
38
+ /**
39
+ * 紧急回滚: 把 preserve 项从 backup_dir 拷回 bds_path。
40
+ * 用法: 在 catch 分支调用,如果主流程失败导致 BDS 目录破坏。
41
+ */
42
+ export function rollbackFromBackup(marker) {
43
+ const { bds_path, backup_dir, preserve } = marker;
44
+ if (!fs.existsSync(backup_dir)) {
45
+ return { ok: false, reason: `备份目录不存在: ${backup_dir}` };
46
+ }
47
+ log.warn(`[回滚] 开始恢复 ${preserve.length} 项到 ${bds_path}`);
48
+ for (const item of preserve) {
49
+ const src = path.join(backup_dir, item);
50
+ const dest = path.join(bds_path, item);
51
+ if (!fs.existsSync(src)) {
52
+ log.warn(`[回滚] 跳过 (备份中不存在): ${item}`);
53
+ continue;
54
+ }
55
+ try {
56
+ // 先确保目标目录存在 (BDS 目录可能已被解压覆盖为空)
57
+ const destDir = path.dirname(dest);
58
+ if (!fs.existsSync(destDir))
59
+ fs.mkdirSync(destDir, { recursive: true });
60
+ if (fs.statSync(src).isDirectory()) {
61
+ // 先删除目标,再复制目录
62
+ if (fs.existsSync(dest))
63
+ emptyDirSync(dest);
64
+ copyDirSync(src, dest);
65
+ }
66
+ else {
67
+ fs.copyFileSync(src, dest);
68
+ }
69
+ log.info(`[回滚] 已恢复: ${item}`);
70
+ }
71
+ catch (e) {
72
+ log.warn(`[回滚] 恢复失败 ${item}: ${e.message}`);
73
+ }
74
+ }
75
+ return { ok: true };
76
+ }
77
+ /** 检查 BDS_PATH 中关键文件是否都还在 (更新后完整性 sanity check) */
78
+ export function verifyBdsInstall(bds_path, expected) {
79
+ const missing = [];
80
+ for (const f of expected) {
81
+ if (!fs.existsSync(path.join(bds_path, f)))
82
+ missing.push(f);
83
+ }
84
+ return { ok: missing.length === 0, missing };
85
+ }
86
+ export { getDirSize };
87
+ //# sourceMappingURL=rollback.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rollback.js","sourceRoot":"","sources":["../src/rollback.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * taskbar.ts — Windows Terminal 任务栏进度 (OSC 9;4)
3
+ *
4
+ * 通过 OSC 9;4 转义序列直接驱动 Windows Terminal 任务栏图标上的进度条。
5
+ * 不需要 native 绑定(ffi / ITaskbarList3),但**仅 Windows Terminal 支持**。
6
+ * cmd.exe / PowerShell ISE 等老终端会忽略该序列,本模块在不支持的终端
7
+ * 上静默 no-op。
8
+ *
9
+ * 兼容性:
10
+ * - Windows Terminal ✅
11
+ * - ConEmu / Cmder ⚠️ 部分
12
+ * - cmd.exe / ISE ❌(不解析 OSC)
13
+ *
14
+ * 检测方式:WT_SESSION 或 TERM_PROGRAM === "Windows Terminal"。
15
+ *
16
+ * 序列格式(Windows Terminal 私有):
17
+ * \x1b]9;4;0;\x07 清除(隐藏)
18
+ * \x1b]9;4;1;<pct>\x07 正常(绿,pct 0-100)
19
+ * \x1b]9;4;2;<pct>\x07 错误(红,pct 0-100)
20
+ * \x1b]9;4;3;\x07 不确定(动画条纹)
21
+ *
22
+ * 幂等:相同 state+pct 不重复输出,避免刷屏。
23
+ *
24
+ * 用法:
25
+ * setTaskbarProgress(50); // 50% 绿
26
+ * setTaskbarProgress(100, "error"); // 100% 红
27
+ * clearTaskbarProgress(); // 隐藏
28
+ */
29
+ type ProgressState = "normal" | "error" | "indeterminate";
30
+ /**
31
+ * 设置任务栏进度。
32
+ * - normal: 绿色 (pct 0-100)
33
+ * - error: 红色 (pct 0-100)
34
+ * - indeterminate: 动画条纹(pct 忽略)
35
+ */
36
+ export declare function setTaskbarProgress(pct: number, state?: ProgressState): void;
37
+ /** 清除任务栏进度(隐藏进度条)。幂等。 */
38
+ export declare function clearTaskbarProgress(): void;
39
+ /** 模块是否启用(Windows Terminal 探测结果)。供日志 / 调试。 */
40
+ export declare function isTaskbarSupported(): boolean;
41
+ export {};
42
+ //# sourceMappingURL=taskbar.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"taskbar.d.ts","sourceRoot":"","sources":["../src/taskbar.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,KAAK,aAAa,GAAG,QAAQ,GAAG,OAAO,GAAG,eAAe,CAAC;AA2B1D;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,GAAE,aAAwB,GAAG,IAAI,CAmBrF;AAED,yBAAyB;AACzB,wBAAgB,oBAAoB,IAAI,IAAI,CAM3C;AAED,8CAA8C;AAC9C,wBAAgB,kBAAkB,IAAI,OAAO,CAE5C"}
@@ -0,0 +1,94 @@
1
+ /**
2
+ * taskbar.ts — Windows Terminal 任务栏进度 (OSC 9;4)
3
+ *
4
+ * 通过 OSC 9;4 转义序列直接驱动 Windows Terminal 任务栏图标上的进度条。
5
+ * 不需要 native 绑定(ffi / ITaskbarList3),但**仅 Windows Terminal 支持**。
6
+ * cmd.exe / PowerShell ISE 等老终端会忽略该序列,本模块在不支持的终端
7
+ * 上静默 no-op。
8
+ *
9
+ * 兼容性:
10
+ * - Windows Terminal ✅
11
+ * - ConEmu / Cmder ⚠️ 部分
12
+ * - cmd.exe / ISE ❌(不解析 OSC)
13
+ *
14
+ * 检测方式:WT_SESSION 或 TERM_PROGRAM === "Windows Terminal"。
15
+ *
16
+ * 序列格式(Windows Terminal 私有):
17
+ * \x1b]9;4;0;\x07 清除(隐藏)
18
+ * \x1b]9;4;1;<pct>\x07 正常(绿,pct 0-100)
19
+ * \x1b]9;4;2;<pct>\x07 错误(红,pct 0-100)
20
+ * \x1b]9;4;3;\x07 不确定(动画条纹)
21
+ *
22
+ * 幂等:相同 state+pct 不重复输出,避免刷屏。
23
+ *
24
+ * 用法:
25
+ * setTaskbarProgress(50); // 50% 绿
26
+ * setTaskbarProgress(100, "error"); // 100% 红
27
+ * clearTaskbarProgress(); // 隐藏
28
+ */
29
+ function detect() {
30
+ if (process.platform !== "win32")
31
+ return false;
32
+ if (process.env["WT_SESSION"])
33
+ return true;
34
+ if (process.env["TERM_PROGRAM"] === "Windows Terminal")
35
+ return true;
36
+ return false;
37
+ }
38
+ let supported = detect();
39
+ let active = false;
40
+ let lastPct = -1;
41
+ let lastState = 0;
42
+ function stateCode(s) {
43
+ switch (s) {
44
+ case "clear":
45
+ return 0;
46
+ case "normal":
47
+ return 1;
48
+ case "error":
49
+ return 2;
50
+ case "indeterminate":
51
+ return 3;
52
+ }
53
+ }
54
+ /**
55
+ * 设置任务栏进度。
56
+ * - normal: 绿色 (pct 0-100)
57
+ * - error: 红色 (pct 0-100)
58
+ * - indeterminate: 动画条纹(pct 忽略)
59
+ */
60
+ export function setTaskbarProgress(pct, state = "normal") {
61
+ if (!supported)
62
+ return;
63
+ if (state === "indeterminate") {
64
+ if (lastState === 3)
65
+ return; // 已在 indeterminate,不再重发
66
+ process.stdout.write("\x1b]9;4;3\x07");
67
+ lastState = 3;
68
+ lastPct = -1;
69
+ active = true;
70
+ return;
71
+ }
72
+ const p = Math.max(0, Math.min(100, Math.round(pct)));
73
+ const sc = stateCode(state);
74
+ if (lastState === sc && lastPct === p)
75
+ return; // 无变化,跳过
76
+ process.stdout.write(`\x1b]9;4;${sc};${p}\x07`);
77
+ lastPct = p;
78
+ lastState = sc;
79
+ active = true;
80
+ }
81
+ /** 清除任务栏进度(隐藏进度条)。幂等。 */
82
+ export function clearTaskbarProgress() {
83
+ if (!supported || !active)
84
+ return;
85
+ process.stdout.write("\x1b]9;4;0\x07");
86
+ lastPct = -1;
87
+ lastState = 0;
88
+ active = false;
89
+ }
90
+ /** 模块是否启用(Windows Terminal 探测结果)。供日志 / 调试。 */
91
+ export function isTaskbarSupported() {
92
+ return supported;
93
+ }
94
+ //# sourceMappingURL=taskbar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"taskbar.js","sourceRoot":"","sources":["../src/taskbar.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAIH,SAAS,MAAM;IACb,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO;QAAE,OAAO,KAAK,CAAC;IAC/C,IAAI,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC;QAAE,OAAO,IAAI,CAAC;IAC3C,IAAI,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,KAAK,kBAAkB;QAAE,OAAO,IAAI,CAAC;IACpE,OAAO,KAAK,CAAC;AACf,CAAC;AAED,IAAI,SAAS,GAAG,MAAM,EAAE,CAAC;AACzB,IAAI,MAAM,GAAG,KAAK,CAAC;AACnB,IAAI,OAAO,GAAG,CAAC,CAAC,CAAC;AACjB,IAAI,SAAS,GAAkB,CAAC,CAAC;AAEjC,SAAS,SAAS,CAAC,CAA0B;IAC3C,QAAQ,CAAC,EAAE,CAAC;QACV,KAAK,OAAO;YACV,OAAO,CAAC,CAAC;QACX,KAAK,QAAQ;YACX,OAAO,CAAC,CAAC;QACX,KAAK,OAAO;YACV,OAAO,CAAC,CAAC;QACX,KAAK,eAAe;YAClB,OAAO,CAAC,CAAC;IACb,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB,CAAC,GAAW,EAAE,QAAuB,QAAQ;IAC7E,IAAI,CAAC,SAAS;QAAE,OAAO;IAEvB,IAAI,KAAK,KAAK,eAAe,EAAE,CAAC;QAC9B,IAAI,SAAS,KAAK,CAAC;YAAE,OAAO,CAAC,wBAAwB;QACrD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC;QACvC,SAAS,GAAG,CAAC,CAAC;QACd,OAAO,GAAG,CAAC,CAAC,CAAC;QACb,MAAM,GAAG,IAAI,CAAC;QACd,OAAO;IACT,CAAC;IAED,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IACtD,MAAM,EAAE,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC;IAC5B,IAAI,SAAS,KAAK,EAAE,IAAI,OAAO,KAAK,CAAC;QAAE,OAAO,CAAC,SAAS;IACxD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,YAAY,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;IAChD,OAAO,GAAG,CAAC,CAAC;IACZ,SAAS,GAAG,EAAE,CAAC;IACf,MAAM,GAAG,IAAI,CAAC;AAChB,CAAC;AAED,yBAAyB;AACzB,MAAM,UAAU,oBAAoB;IAClC,IAAI,CAAC,SAAS,IAAI,CAAC,MAAM;QAAE,OAAO;IAClC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC;IACvC,OAAO,GAAG,CAAC,CAAC,CAAC;IACb,SAAS,GAAG,CAAC,CAAC;IACd,MAAM,GAAG,KAAK,CAAC;AACjB,CAAC;AAED,8CAA8C;AAC9C,MAAM,UAAU,kBAAkB;IAChC,OAAO,SAAS,CAAC;AACnB,CAAC"}
@@ -0,0 +1,56 @@
1
+ /**
2
+ * types.ts — BDSTools 共享类型
3
+ */
4
+ export interface BdsUpdaterConfig {
5
+ bds_path?: string;
6
+ backup_dir?: string;
7
+ channel?: "release" | "preview" | string;
8
+ auto_restart?: boolean;
9
+ auto_check?: boolean;
10
+ crash_restart?: boolean;
11
+ crash_restart_delay?: number;
12
+ qq_notify?: boolean;
13
+ qq_config?: string;
14
+ preserve?: string[];
15
+ version_mode?: "bedrock-oss" | "endstone";
16
+ version_versions?: string;
17
+ version_versions_mirror?: string;
18
+ version_details?: string;
19
+ version_details_mirror?: string;
20
+ download_mirror?: string;
21
+ cdn_root?: string;
22
+ download_timeout?: number;
23
+ compatible_versions?: string[];
24
+ _hash?: {
25
+ sha1: string;
26
+ sha256: string;
27
+ };
28
+ }
29
+ export interface VersionInfo {
30
+ version: string;
31
+ cdnRoot: string;
32
+ }
33
+ export interface VersionDetails {
34
+ downloadUrl: string;
35
+ sha1: string;
36
+ sha256: string;
37
+ size: number;
38
+ }
39
+ export interface UpdateOutcome {
40
+ ok: boolean;
41
+ currentVer: string;
42
+ latestVer: string;
43
+ backupPath: string | null;
44
+ durationMs: number;
45
+ }
46
+ export interface ChangelogPayload {
47
+ text: string;
48
+ imageBase64: string | null;
49
+ }
50
+ export type LogLevel = "info" | "warn" | "error";
51
+ export interface Logger {
52
+ info(msg: string): void;
53
+ warn(msg: string): void;
54
+ error(msg: string): void;
55
+ }
56
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,SAAS,GAAG,SAAS,GAAG,MAAM,CAAC;IACzC,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IAGpB,YAAY,CAAC,EAAE,aAAa,GAAG,UAAU,CAAC;IAC1C,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAG1B,mBAAmB,CAAC,EAAE,MAAM,EAAE,CAAC;IAG/B,KAAK,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;CAC1C;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,OAAO,CAAC;IACZ,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;AAEjD,MAAM,WAAW,MAAM;IACrB,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B"}
package/dist/types.js ADDED
@@ -0,0 +1,5 @@
1
+ /**
2
+ * types.ts — BDSTools 共享类型
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * upstream.ts — 版本源 / 下载源 / 哈希校验
3
+ *
4
+ * 改进:
5
+ * - 3 次重试 + 指数退避
6
+ * - sha1 / sha256 同时校验
7
+ * - 流式校验 + 边下边校验
8
+ */
9
+ import type { BdsUpdaterConfig, VersionDetails, VersionInfo } from "./types.js";
10
+ /** 获取最新版本号 (含 cdn_root),3 次重试 */
11
+ export declare function getVersionInfo(cfg: BdsUpdaterConfig, channel: string): Promise<VersionInfo>;
12
+ /** 获取 per-version 的下载链接 + 哈希 (fallback GitHub → jsdelivr) */
13
+ export declare function fetchVersionDetails(cfg: BdsUpdaterConfig, channel: string, version: string): Promise<VersionDetails>;
14
+ /** 候选下载 URL (按优先级) */
15
+ export declare function buildDownloadUrls(cfg: BdsUpdaterConfig, channel: string, version: string, details: VersionDetails): string[];
16
+ /** 同步 / 异步校验文件哈希 */
17
+ export declare function verifyFileHash(filePath: string, expectedSha1: string, expectedSha256: string): Promise<boolean>;
18
+ /** 检查版本兼容性 (白名单) */
19
+ export declare function isVersionCompatible(cfg: BdsUpdaterConfig, version: string): boolean;
20
+ //# sourceMappingURL=upstream.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"upstream.d.ts","sourceRoot":"","sources":["../src/upstream.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAMH,OAAO,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAchF,iCAAiC;AACjC,wBAAsB,cAAc,CAAC,GAAG,EAAE,gBAAgB,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CA8BjG;AAED,6DAA6D;AAC7D,wBAAsB,mBAAmB,CACvC,GAAG,EAAE,gBAAgB,EACrB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,cAAc,CAAC,CA2BzB;AAED,sBAAsB;AACtB,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,gBAAgB,EACrB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,cAAc,GACtB,MAAM,EAAE,CAeV;AAED,oBAAoB;AACpB,wBAAsB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAiBrH;AAED,oBAAoB;AACpB,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,gBAAgB,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAInF"}
@@ -0,0 +1,126 @@
1
+ /**
2
+ * upstream.ts — 版本源 / 下载源 / 哈希校验
3
+ *
4
+ * 改进:
5
+ * - 3 次重试 + 指数退避
6
+ * - sha1 / sha256 同时校验
7
+ * - 流式校验 + 边下边校验
8
+ */
9
+ import crypto from "node:crypto";
10
+ import fs from "node:fs";
11
+ import { fetchJsonWithFallback } from "./http.js";
12
+ import { log } from "./log.js";
13
+ import { toVer3 } from "./version.js";
14
+ const DEFAULT_VERSIONS_API = "https://raw.githubusercontent.com/Bedrock-OSS/BDS-Versions/main/versions.json";
15
+ const DEFAULT_VERSIONS_MIRROR = "https://cdn.jsdelivr.net/gh/Bedrock-OSS/BDS-Versions@main/versions.json";
16
+ function resolveTemplate(tpl, vars) {
17
+ let s = tpl;
18
+ for (const [k, v] of Object.entries(vars)) {
19
+ s = s.replace(new RegExp(`\\{${k}\\}`, "g"), v);
20
+ }
21
+ return s;
22
+ }
23
+ /** 获取最新版本号 (含 cdn_root),3 次重试 */
24
+ export async function getVersionInfo(cfg, channel) {
25
+ const api = cfg.version_versions || process.env["BDS_VERSIONS_API"] || DEFAULT_VERSIONS_API;
26
+ const mirror = cfg.version_versions_mirror || process.env["BDS_VERSIONS_MIRROR"] || DEFAULT_VERSIONS_MIRROR;
27
+ const sources = [api, mirror].filter(Boolean);
28
+ const versionMode = cfg.version_mode || "bedrock-oss";
29
+ let lastErr;
30
+ for (let attempt = 1; attempt <= 3; attempt++) {
31
+ try {
32
+ const json = await fetchJsonWithFallback(sources);
33
+ let ver;
34
+ if (versionMode === "endstone") {
35
+ const entry = channel === "preview" ? json.preview : json.release;
36
+ ver = entry?.latest;
37
+ }
38
+ else {
39
+ const platform = json.windows || json.linux;
40
+ ver = channel === "preview" ? platform?.preview : platform?.stable;
41
+ }
42
+ if (!ver)
43
+ throw new Error("未找到最新版本号");
44
+ return { version: ver, cdnRoot: json.cdn_root ?? "" };
45
+ }
46
+ catch (e) {
47
+ lastErr = e;
48
+ if (attempt < 3) {
49
+ const wait = attempt * 3000;
50
+ log.warn(`版本号获取失败 (${attempt}/3): ${e.message},${wait / 1000}s 后重试...`);
51
+ await new Promise((r) => setTimeout(r, wait));
52
+ }
53
+ }
54
+ }
55
+ throw lastErr instanceof Error ? lastErr : new Error("版本号获取失败");
56
+ }
57
+ /** 获取 per-version 的下载链接 + 哈希 (fallback GitHub → jsdelivr) */
58
+ export async function fetchVersionDetails(cfg, channel, version) {
59
+ const platform = channel === "preview" ? "windows_preview" : "windows";
60
+ const ch = channel === "preview" ? "preview" : "release";
61
+ const vars = { version, ver3: toVer3(version), platform, channel: ch };
62
+ const detailsTpl = cfg.version_details || "https://raw.githubusercontent.com/Bedrock-OSS/BDS-Versions/main/{platform}/{version}.json";
63
+ const mirrorTpl = cfg.version_details_mirror || "https://cdn.jsdelivr.net/gh/Bedrock-OSS/BDS-Versions@main/{platform}/{version}.json";
64
+ const sources = [detailsTpl, mirrorTpl].filter(Boolean).map((t) => resolveTemplate(t, vars));
65
+ const json = await fetchJsonWithFallback(sources);
66
+ const mode = cfg.version_mode || "bedrock-oss";
67
+ if (mode === "endstone") {
68
+ const bw = json.binary?.windows;
69
+ return {
70
+ downloadUrl: bw?.url ?? "",
71
+ sha1: "",
72
+ sha256: bw?.sha256 ?? "",
73
+ size: bw?.size_in_bytes ?? 0,
74
+ };
75
+ }
76
+ return {
77
+ downloadUrl: json.download_url ?? "",
78
+ sha1: json.sha1 ?? "",
79
+ sha256: "",
80
+ size: json.size_in_bytes ?? 0,
81
+ };
82
+ }
83
+ /** 候选下载 URL (按优先级) */
84
+ export function buildDownloadUrls(cfg, channel, version, details) {
85
+ const urls = [];
86
+ if (cfg.download_mirror) {
87
+ const mirrorVer = channel === "preview" ? `${version}-preview` : version;
88
+ urls.push(resolveTemplate(cfg.download_mirror, { version: mirrorVer }));
89
+ }
90
+ if (details.downloadUrl)
91
+ urls.push(details.downloadUrl);
92
+ const cdnRoot = cfg.cdn_root || "https://www.minecraft.net/bedrockdedicatedserver";
93
+ const suffix = channel === "preview"
94
+ ? `/bin-win-preview/bedrock-server-${version}-preview.zip`
95
+ : `/bin-win/bedrock-server-${version}.zip`;
96
+ urls.push(cdnRoot + suffix);
97
+ urls.push(`https://minecraft.azureedge.net${suffix}`);
98
+ return [...new Set(urls)];
99
+ }
100
+ /** 同步 / 异步校验文件哈希 */
101
+ export async function verifyFileHash(filePath, expectedSha1, expectedSha256) {
102
+ const expected = expectedSha256 || expectedSha1;
103
+ if (!expected)
104
+ return true;
105
+ const algo = expectedSha256 ? "sha256" : "sha1";
106
+ return new Promise((resolve, reject) => {
107
+ const h = crypto.createHash(algo);
108
+ const stream = fs.createReadStream(filePath);
109
+ stream.on("data", (chunk) => {
110
+ h.update(typeof chunk === "string" ? Buffer.from(chunk) : chunk);
111
+ });
112
+ stream.on("end", () => {
113
+ const actual = h.digest("hex").toLowerCase();
114
+ resolve(actual === expected.toLowerCase());
115
+ });
116
+ stream.on("error", reject);
117
+ });
118
+ }
119
+ /** 检查版本兼容性 (白名单) */
120
+ export function isVersionCompatible(cfg, version) {
121
+ const allow = cfg.compatible_versions;
122
+ if (!allow || allow.length === 0)
123
+ return true;
124
+ return allow.includes(version) || allow.includes(toVer3(version));
125
+ }
126
+ //# sourceMappingURL=upstream.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"upstream.js","sourceRoot":"","sources":["../src/upstream.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * version.ts — 版本号工具 / 版本缓存
3
+ */
4
+ /** 4段 → 3段 (去尾) */
5
+ export declare function toVer3(v: string): string;
6
+ /** 3段 → 4段 (补 0) */
7
+ export declare function toVer4(v: string): string;
8
+ /** 版本比较 (按 4 段数字排序) */
9
+ export declare function compareVersions(a: string, b: string): number;
10
+ /** 简单的真值校验 (按版本号外形) */
11
+ export declare function isValidVersion(v: string): boolean;
12
+ export declare function saveVersionCache(version: string, sha256: string): void;
13
+ /**
14
+ * 异步识别当前 BDS 版本
15
+ * 优先通过 SHA256 反查缓存,失败则回退 `current_version.txt`(如果存在)
16
+ */
17
+ export declare function getCurrentVersionAsync(exePath: string): Promise<string>;
18
+ /** 同步版本 (兼容旧流程) */
19
+ export declare function getCurrentVersionSync(exePath: string): string;
20
+ //# sourceMappingURL=version.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA;;GAEG;AAQH,mBAAmB;AACnB,wBAAgB,MAAM,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAExC;AAED,oBAAoB;AACpB,wBAAgB,MAAM,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAIxC;AAED,uBAAuB;AACvB,wBAAgB,eAAe,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAc5D;AAED,uBAAuB;AACvB,wBAAgB,cAAc,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAEjD;AAoBD,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAQtE;AAED;;;GAGG;AACH,wBAAsB,sBAAsB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAW7E;AAED,mBAAmB;AACnB,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAU7D"}
@@ -0,0 +1,97 @@
1
+ /**
2
+ * version.ts — 版本号工具 / 版本缓存
3
+ */
4
+ import { readJson, writeJson } from "@sfmc-bds/sdk/node/config";
5
+ import fs from "node:fs";
6
+ import { VERSION_CACHE } from "./paths.js";
7
+ import { hashFileSync, hashFileAsync } from "./fsx.js";
8
+ import { log } from "./log.js";
9
+ /** 4段 → 3段 (去尾) */
10
+ export function toVer3(v) {
11
+ return v.split(".").slice(0, 3).join(".");
12
+ }
13
+ /** 3段 → 4段 (补 0) */
14
+ export function toVer4(v) {
15
+ const p = v.split(".");
16
+ while (p.length < 4)
17
+ p.push("0");
18
+ return p.join(".");
19
+ }
20
+ /** 版本比较 (按 4 段数字排序) */
21
+ export function compareVersions(a, b) {
22
+ const sa = a.replace(/-preview$/, "");
23
+ const sb = b.replace(/-preview$/, "");
24
+ const pa = sa.split(".").map(Number);
25
+ const pb = sb.split(".").map(Number);
26
+ for (let i = 0; i < 4; i++) {
27
+ const ai = pa[i] ?? 0;
28
+ const bi = pb[i] ?? 0;
29
+ if (ai !== bi)
30
+ return ai - bi;
31
+ }
32
+ // preview 低于不带 -preview 的同一数字
33
+ if (a.endsWith("-preview") && !b.endsWith("-preview"))
34
+ return -1;
35
+ if (!a.endsWith("-preview") && b.endsWith("-preview"))
36
+ return 1;
37
+ return 0;
38
+ }
39
+ /** 简单的真值校验 (按版本号外形) */
40
+ export function isValidVersion(v) {
41
+ return /^\d+\.\d+\.\d+(\.\d+)?(-preview)?$/.test(v);
42
+ }
43
+ function readCache() {
44
+ return readJson(VERSION_CACHE) ?? {};
45
+ }
46
+ /** 仅保留最近 3 条版本缓存 (避免无限增长) */
47
+ function trimCache(cache) {
48
+ const keys = Object.keys(cache).sort(compareVersions).slice(-3);
49
+ const trimmed = {};
50
+ for (const k of keys)
51
+ trimmed[k] = cache[k];
52
+ return trimmed;
53
+ }
54
+ export function saveVersionCache(version, sha256) {
55
+ const cache = readCache();
56
+ cache[version] = { sha256, verified_at: Date.now() };
57
+ try {
58
+ writeJson(VERSION_CACHE, trimCache(cache));
59
+ }
60
+ catch {
61
+ /* ignore */
62
+ }
63
+ }
64
+ /**
65
+ * 异步识别当前 BDS 版本
66
+ * 优先通过 SHA256 反查缓存,失败则回退 `current_version.txt`(如果存在)
67
+ */
68
+ export async function getCurrentVersionAsync(exePath) {
69
+ if (!fs.existsSync(exePath))
70
+ return "0.0.0.0";
71
+ const actual = await hashFileAsync(exePath, "sha256");
72
+ if (!actual)
73
+ return "0.0.0.0";
74
+ const cache = readCache();
75
+ for (const [ver, entry] of Object.entries(cache)) {
76
+ if (entry.sha256 === actual)
77
+ return ver;
78
+ }
79
+ log.warn("[BDSUpdater] bedrock_server.exe 哈希未匹配缓存,疑似被改动或首次启动");
80
+ return "0.0.0.0";
81
+ }
82
+ /** 同步版本 (兼容旧流程) */
83
+ export function getCurrentVersionSync(exePath) {
84
+ if (!fs.existsSync(exePath))
85
+ return "0.0.0.0";
86
+ const actual = hashFileSync(exePath, "sha256");
87
+ if (!actual)
88
+ return "0.0.0.0";
89
+ const cache = readCache();
90
+ for (const [ver, entry] of Object.entries(cache)) {
91
+ if (entry.sha256 === actual)
92
+ return ver;
93
+ }
94
+ log.warn("[BDSUpdater] bedrock_server.exe 哈希未匹配缓存");
95
+ return "0.0.0.0";
96
+ }
97
+ //# sourceMappingURL=version.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.js","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"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"}