@sfmc-bds/cli 0.2.0-beta.10 → 0.2.0-beta.12

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 (53) hide show
  1. package/LICENSE +663 -0
  2. package/dist/command-surface.test.js +92 -0
  3. package/dist/command-surface.test.js.map +7 -0
  4. package/dist/commands.d.ts +57 -4
  5. package/dist/commands.d.ts.map +1 -1
  6. package/dist/commands.js.map +2 -2
  7. package/dist/debug-command.test.js +76 -0
  8. package/dist/debug-command.test.js.map +7 -0
  9. package/dist/directory-picker.d.ts +27 -0
  10. package/dist/directory-picker.d.ts.map +1 -0
  11. package/dist/directory-picker.js +112 -0
  12. package/dist/directory-picker.js.map +7 -0
  13. package/dist/i18n/locales/en.d.ts +1 -0
  14. package/dist/i18n/locales/en.d.ts.map +1 -1
  15. package/dist/i18n/locales/en.js +1 -0
  16. package/dist/i18n/locales/en.js.map +2 -2
  17. package/dist/i18n/locales/zh-CN.d.ts.map +1 -1
  18. package/dist/i18n/locales/zh-CN.js +1 -0
  19. package/dist/i18n/locales/zh-CN.js.map +2 -2
  20. package/dist/interactive-prompts.d.ts +1 -2
  21. package/dist/interactive-prompts.d.ts.map +1 -1
  22. package/dist/interactive-prompts.js +12 -23
  23. package/dist/interactive-prompts.js.map +3 -3
  24. package/dist/log-filter.test.js +119 -0
  25. package/dist/log-filter.test.js.map +7 -0
  26. package/dist/module-commands.d.ts.map +1 -1
  27. package/dist/module-commands.js +6 -3
  28. package/dist/module-commands.js.map +2 -2
  29. package/dist/module-pack-build.js.map +1 -1
  30. package/dist/module-toggle.d.ts +1 -1
  31. package/dist/module-toggle.d.ts.map +1 -1
  32. package/dist/module-toggle.js.map +1 -1
  33. package/dist/module-toggle.test.js +37 -0
  34. package/dist/module-toggle.test.js.map +7 -0
  35. package/dist/pack-lifecycle.js +1 -1
  36. package/dist/pack-lifecycle.js.map +2 -2
  37. package/dist/services.d.ts +14 -0
  38. package/dist/services.d.ts.map +1 -1
  39. package/dist/services.js.map +2 -2
  40. package/dist/wizard.d.ts.map +1 -1
  41. package/dist/wizard.js +20 -22
  42. package/dist/wizard.js.map +2 -2
  43. package/dist/world-packs-uninstall.test.js +54 -0
  44. package/dist/world-packs-uninstall.test.js.map +7 -0
  45. package/package.json +14 -12
  46. package/scripts/module-install/check-modules.mjs +10 -76
  47. package/scripts/module-install/lib/catalog.mjs +1 -1
  48. package/scripts/module-install/lib/lock.mjs +2 -2
  49. package/scripts/module-install/lib/packages.mjs +16 -22
  50. package/scripts/module-install/{install-resolver.test.mjs → test/install-resolver.test.ts} +4 -5
  51. package/scripts/module-install/{link-local.test.mjs → test/link-local.test.ts} +4 -5
  52. package/scripts/module-install/{local-resolver.test.mjs → test/local-resolver.test.ts} +5 -12
  53. package/scripts/module-install/{registry-index.test.mjs → test/registry-index.test.ts} +5 -6
@@ -0,0 +1,92 @@
1
+ import assert from "node:assert/strict";
2
+ import test from "node:test";
3
+ import { gateTopLevel } from "./cli-gate.js";
4
+ import {
5
+ canRunCommand,
6
+ findModuleSubSpec,
7
+ findTopLevelSpec,
8
+ listPaletteRoots,
9
+ listVisibleModuleSubs,
10
+ listVisibleTopLevelNames,
11
+ resolveModuleTopShorthand
12
+ } from "./command-surface.js";
13
+ const tty = { isTty: true };
14
+ const noTty = { isTty: false };
15
+ test("install \u4E24\u8FB9\u53EF\u7528\uFF08both\uFF09", () => {
16
+ const spec = findModuleSubSpec("install");
17
+ assert.ok(spec);
18
+ assert.equal(canRunCommand(spec, { mode: "argv", ...tty }).ok, true);
19
+ assert.equal(canRunCommand(spec, { mode: "repl", ...tty }).ok, true);
20
+ });
21
+ test("send \u4EC5 REPL\uFF1Aargv \u62D2\u7EDD", () => {
22
+ const spec = findTopLevelSpec("send");
23
+ assert.ok(spec);
24
+ const r = canRunCommand(spec, { mode: "argv", ...tty });
25
+ assert.equal(r.ok, false);
26
+ assert.equal(r.reason, "replOnly");
27
+ assert.equal(canRunCommand(spec, { mode: "repl", ...tty }).ok, true);
28
+ });
29
+ test("status \u4E24\u8FB9\u53EF\u7528", () => {
30
+ const spec = findTopLevelSpec("status");
31
+ assert.ok(spec);
32
+ assert.equal(canRunCommand(spec, { mode: "argv", ...tty }).ok, true);
33
+ assert.equal(canRunCommand(spec, { mode: "repl", ...tty }).ok, true);
34
+ });
35
+ test("build/reload/install \u5728 REPL \u53EF\u89C1", () => {
36
+ const build = findModuleSubSpec("build");
37
+ assert.equal(build?.accent, "dev");
38
+ assert.equal(canRunCommand(build, { mode: "repl", ...tty }).ok, true);
39
+ assert.ok(listVisibleModuleSubs("repl").includes("build"));
40
+ assert.ok(listVisibleModuleSubs("repl").includes("install"));
41
+ });
42
+ test("argv \u9876\u5C42\u5217\u8868\u4E0D\u542B send\uFF1B\u542B debug/install/uninstall", () => {
43
+ const names = listVisibleTopLevelNames("argv");
44
+ assert.ok(!names.includes("send"));
45
+ assert.ok(names.includes("debug"));
46
+ assert.ok(names.includes("install"));
47
+ assert.ok(names.includes("uninstall") || names.includes("remove"));
48
+ assert.ok(names.includes("module") || names.includes("mod"));
49
+ });
50
+ test("REPL \u9876\u5C42\u5217\u8868\u542B send \u4E0E debug", () => {
51
+ const names = listVisibleTopLevelNames("repl");
52
+ assert.ok(names.includes("send"));
53
+ assert.ok(names.includes("debug"));
54
+ assert.ok(names.includes("init"));
55
+ });
56
+ test("accent \u4E0D\u53C2\u4E0E canRun\uFF1Adebug \u4E24\u8FB9\u53EF\u8DD1", () => {
57
+ const spec = findTopLevelSpec("debug");
58
+ assert.equal(spec?.accent, "dev");
59
+ assert.equal(canRunCommand(spec, { mode: "argv", ...tty }).ok, true);
60
+ assert.equal(canRunCommand(spec, { mode: "repl", ...tty }).ok, true);
61
+ });
62
+ test("\u6A21\u5757\u9876\u5C42\u77ED\u547D\u4EE4\u6620\u5C04", () => {
63
+ assert.equal(resolveModuleTopShorthand("i"), "install");
64
+ assert.equal(resolveModuleTopShorthand("remove"), "uninstall");
65
+ assert.equal(resolveModuleTopShorthand("search"), "search");
66
+ assert.equal(resolveModuleTopShorthand("status"), void 0);
67
+ });
68
+ test("logs \u4EC5 REPL\uFF08\u65E0\u53C2\u53F6\u547D\u4EE4\uFF09", () => {
69
+ assert.ok(gateTopLevel("logs", "argv"), "argv \u5E94\u62D2\u7EDD logs");
70
+ assert.equal(gateTopLevel("logs", "repl"), null);
71
+ const logs = listPaletteRoots("repl").find((n) => n.token === "logs");
72
+ assert.ok(logs);
73
+ assert.equal(logs.children, void 0);
74
+ assert.notEqual(logs.freeArgs, true);
75
+ });
76
+ test("\u547D\u4EE4\u9762\u677F\u6839\u5217\u4E0D\u542B module \u77ED\u547D\u4EE4\uFF0C\u7EDF\u4E00\u6302\u5728 /module", () => {
77
+ const roots = listPaletteRoots("repl");
78
+ const tokens = roots.map((n) => n.token);
79
+ for (const shy of ["install", "uninstall", "search", "verify", "link", "create", "dev"]) {
80
+ assert.ok(!tokens.includes(shy), `\u9762\u677F\u6839\u5217\u4E0D\u5E94\u6709 /${shy}`);
81
+ }
82
+ const mod = roots.find((n) => n.token === "module");
83
+ assert.ok(mod?.children?.length);
84
+ const childTokens = mod.children.map((n) => n.token);
85
+ assert.ok(childTokens.includes("install"));
86
+ assert.ok(childTokens.includes("uninstall"));
87
+ assert.ok(!childTokens.includes("create"));
88
+ assert.ok(!childTokens.includes("link"));
89
+ assert.ok(!childTokens.includes("dev"));
90
+ assert.equal(mod.label, "/module");
91
+ });
92
+ //# sourceMappingURL=command-surface.test.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/command-surface.test.ts"],
4
+ "sourcesContent": ["/**\n * command-surface \u901A\u9053\u95E8\u7981\u7EAF\u51FD\u6570\u8868\u9A71\u52A8\n */\nimport assert from \"node:assert/strict\";\nimport test from \"node:test\";\nimport { gateTopLevel } from \"./cli-gate.js\";\nimport {\n canRunCommand,\n findModuleSubSpec,\n findTopLevelSpec,\n listPaletteRoots,\n listVisibleModuleSubs,\n listVisibleTopLevelNames,\n resolveModuleTopShorthand,\n} from \"./command-surface.js\";\n\nconst tty = { isTty: true };\nconst noTty = { isTty: false };\n\ntest(\"install \u4E24\u8FB9\u53EF\u7528\uFF08both\uFF09\", () => {\n const spec = findModuleSubSpec(\"install\");\n assert.ok(spec);\n assert.equal(canRunCommand(spec, { mode: \"argv\", ...tty }).ok, true);\n assert.equal(canRunCommand(spec, { mode: \"repl\", ...tty }).ok, true);\n});\n\ntest(\"send \u4EC5 REPL\uFF1Aargv \u62D2\u7EDD\", () => {\n const spec = findTopLevelSpec(\"send\");\n assert.ok(spec);\n const r = canRunCommand(spec, { mode: \"argv\", ...tty });\n assert.equal(r.ok, false);\n assert.equal(r.reason, \"replOnly\");\n assert.equal(canRunCommand(spec, { mode: \"repl\", ...tty }).ok, true);\n});\n\ntest(\"status \u4E24\u8FB9\u53EF\u7528\", () => {\n const spec = findTopLevelSpec(\"status\");\n assert.ok(spec);\n assert.equal(canRunCommand(spec, { mode: \"argv\", ...tty }).ok, true);\n assert.equal(canRunCommand(spec, { mode: \"repl\", ...tty }).ok, true);\n});\n\ntest(\"build/reload/install \u5728 REPL \u53EF\u89C1\", () => {\n const build = findModuleSubSpec(\"build\");\n assert.equal(build?.accent, \"dev\");\n assert.equal(canRunCommand(build, { mode: \"repl\", ...tty }).ok, true);\n assert.ok(listVisibleModuleSubs(\"repl\").includes(\"build\"));\n assert.ok(listVisibleModuleSubs(\"repl\").includes(\"install\"));\n});\n\ntest(\"argv \u9876\u5C42\u5217\u8868\u4E0D\u542B send\uFF1B\u542B debug/install/uninstall\", () => {\n const names = listVisibleTopLevelNames(\"argv\");\n assert.ok(!names.includes(\"send\"));\n assert.ok(names.includes(\"debug\"));\n assert.ok(names.includes(\"install\"));\n assert.ok(names.includes(\"uninstall\") || names.includes(\"remove\"));\n assert.ok(names.includes(\"module\") || names.includes(\"mod\"));\n});\n\ntest(\"REPL \u9876\u5C42\u5217\u8868\u542B send \u4E0E debug\", () => {\n const names = listVisibleTopLevelNames(\"repl\");\n assert.ok(names.includes(\"send\"));\n assert.ok(names.includes(\"debug\"));\n assert.ok(names.includes(\"init\"));\n});\n\ntest(\"accent \u4E0D\u53C2\u4E0E canRun\uFF1Adebug \u4E24\u8FB9\u53EF\u8DD1\", () => {\n const spec = findTopLevelSpec(\"debug\");\n assert.equal(spec?.accent, \"dev\");\n assert.equal(canRunCommand(spec, { mode: \"argv\", ...tty }).ok, true);\n assert.equal(canRunCommand(spec, { mode: \"repl\", ...tty }).ok, true);\n});\n\ntest(\"\u6A21\u5757\u9876\u5C42\u77ED\u547D\u4EE4\u6620\u5C04\", () => {\n assert.equal(resolveModuleTopShorthand(\"i\"), \"install\");\n assert.equal(resolveModuleTopShorthand(\"remove\"), \"uninstall\");\n assert.equal(resolveModuleTopShorthand(\"search\"), \"search\");\n assert.equal(resolveModuleTopShorthand(\"status\"), undefined);\n});\n\ntest(\"logs \u4EC5 REPL\uFF08\u65E0\u53C2\u53F6\u547D\u4EE4\uFF09\", () => {\n assert.ok(gateTopLevel(\"logs\", \"argv\"), \"argv \u5E94\u62D2\u7EDD logs\");\n assert.equal(gateTopLevel(\"logs\", \"repl\"), null);\n const logs = listPaletteRoots(\"repl\").find((n) => n.token === \"logs\");\n assert.ok(logs);\n assert.equal(logs.children, undefined);\n assert.notEqual(logs.freeArgs, true);\n});\n\ntest(\"\u547D\u4EE4\u9762\u677F\u6839\u5217\u4E0D\u542B module \u77ED\u547D\u4EE4\uFF0C\u7EDF\u4E00\u6302\u5728 /module\", () => {\n const roots = listPaletteRoots(\"repl\");\n const tokens = roots.map((n) => n.token);\n for (const shy of [\"install\", \"uninstall\", \"search\", \"verify\", \"link\", \"create\", \"dev\"]) {\n assert.ok(!tokens.includes(shy), `\u9762\u677F\u6839\u5217\u4E0D\u5E94\u6709 /${shy}`);\n }\n const mod = roots.find((n) => n.token === \"module\");\n assert.ok(mod?.children?.length);\n const childTokens = mod.children.map((n) => n.token);\n assert.ok(childTokens.includes(\"install\"));\n assert.ok(childTokens.includes(\"uninstall\"));\n assert.ok(!childTokens.includes(\"create\"));\n assert.ok(!childTokens.includes(\"link\"));\n assert.ok(!childTokens.includes(\"dev\"));\n assert.equal(mod.label, \"/module\");\n});\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -1,18 +1,71 @@
1
+ /**
2
+ * commands.ts — CLI 核心运维命令实现
3
+ *
4
+ * 提供命令行与 REPL 共享的系统级运维指令:
5
+ * - `status`:查询全部服务(BDS、db-server、qq-bridge、LLBot)运行状态、PID、运行时长与所有权
6
+ * - `start` / `stop` / `restart`:按依赖顺序或单个控制服务启停
7
+ * - `startAll` / `stopAll`:批量编排控制所有后台服务
8
+ * - `logs`:检索并实时追踪指定服务的最近日志流
9
+ * - `update`:触发 BDS 核心版本更新检查与热升级
10
+ */
1
11
  import { type ServiceName } from "./services.js";
12
+ /**
13
+ * 查询并格式化展示所有后台服务的当前运行状态矩阵。
14
+ *
15
+ * @returns 格式化后的状态摘要文本表格。
16
+ */
2
17
  export declare function cmdStatus(): Promise<string>;
18
+ /**
19
+ * 检索并格式化指定服务的最近历史日志行(支持 `-n <行数>` 及 `-f` 实时追踪)。
20
+ *
21
+ * @param args 参数列表。
22
+ * @param onFollow 可选的跟随模式回调。
23
+ * @returns 格式化后的日志输出文本。
24
+ */
3
25
  export declare function cmdLogs(args: string[], onFollow?: (serviceName: ServiceName) => void): string;
26
+ /**
27
+ * 启动指定的单项后台服务(bds / db / qq / llbot)。
28
+ *
29
+ * @param raw 目标服务名称字符串。
30
+ * @returns 启动结果描述文本。
31
+ */
4
32
  export declare function cmdStart(raw: string): Promise<string>;
33
+ /**
34
+ * 停止指定的单项后台服务(支持对外部非托管实例执行精准清理)。
35
+ *
36
+ * @param raw 目标服务名称字符串。
37
+ * @returns 停止操作结果文本。
38
+ */
5
39
  export declare function cmdStop(raw: string): Promise<string>;
6
40
  export declare function cmdSend(raw: string, message: string): Promise<string>;
41
+ /**
42
+ * 重启指定的单项后台服务(遵循 stop → start 严谨时序)。
43
+ *
44
+ * @param raw 目标服务名称字符串。
45
+ * @returns 重启操作结果文本。
46
+ */
7
47
  export declare function cmdRestart(raw: string): Promise<string>;
48
+ /**
49
+ * 按服务拓扑依赖次序批量启动所有已启用的后台服务。
50
+ *
51
+ * @returns 批量启动结果统计报告文本。
52
+ */
8
53
  export declare function cmdStartAll(): Promise<string>;
54
+ /**
55
+ * 批量停止所有当前处于运行态的后台服务。
56
+ *
57
+ * @returns 批量停止确认文本。
58
+ */
9
59
  export declare function cmdStopAll(): Promise<string>;
10
60
  /**
11
- * BDS 更新:子进程始终 --no-start,由 sfmc 监督器接管启停与日志。
12
- * (updater 内 detached 自启会导致 REPL 丢 PID / 无 stdout)
61
+ * 触发 BDS 核心版本更新检查与热升级流程。
62
+ *
63
+ * 进程管理与编排约束:
64
+ * - updater 子进程始终附加 `--no-start` 参数,避免由于进程脱离导致 REPL 丢失 PID 跟踪及标准输出
65
+ * - 若更新前 BDS 处于运行状态,且未显式指定 `--no-start`,在更新落盘部署完成后由监督器重新唤起 BDS
13
66
  *
14
- * 不停服预操作:真正需要更新时由 updater 停服;已是最新则不影响正在跑的 BDS。
15
- * 更新成功后若未指定 --no-start,再由监督器 `start bds`(接管 PID + 日志管道)。
67
+ * @param args 传递给更新器的命令行参数。
68
+ * @returns 更新执行结果摘要文本。
16
69
  */
17
70
  export declare function cmdUpdate(args?: string[]): Promise<string>;
18
71
  //# sourceMappingURL=commands.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../src/commands.ts"],"names":[],"mappings":"AAWA,OAAO,EAAuD,KAAK,WAAW,EAAE,MAAM,eAAe,CAAC;AAwDtG,wBAAsB,SAAS,IAAI,OAAO,CAAC,MAAM,CAAC,CAmBjD;AAED,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,QAAQ,CAAC,EAAE,CAAC,WAAW,EAAE,WAAW,KAAK,IAAI,GAAG,MAAM,CA+C7F;AAkBD,wBAAsB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAyC3D;AAED,wBAAsB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CA6D1D;AAED,wBAAsB,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAwB3E;AAED,wBAAsB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAwB7D;AAED,wBAAsB,WAAW,IAAI,OAAO,CAAC,MAAM,CAAC,CA8BnD;AAED,wBAAsB,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC,CAIlD;AAED;;;;;;GAMG;AACH,wBAAsB,SAAS,CAAC,IAAI,GAAE,MAAM,EAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CA2EpE"}
1
+ {"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../src/commands.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAaH,OAAO,EAAuD,KAAK,WAAW,EAAE,MAAM,eAAe,CAAC;AAyDtG;;;;GAIG;AACH,wBAAsB,SAAS,IAAI,OAAO,CAAC,MAAM,CAAC,CAmBjD;AAED;;;;;;GAMG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,QAAQ,CAAC,EAAE,CAAC,WAAW,EAAE,WAAW,KAAK,IAAI,GAAG,MAAM,CA+C7F;AAkBD;;;;;GAKG;AACH,wBAAsB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAyC3D;AAED;;;;;GAKG;AACH,wBAAsB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CA8D1D;AAED,wBAAsB,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAwB3E;AAED;;;;;GAKG;AACH,wBAAsB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAwB7D;AAED;;;;GAIG;AACH,wBAAsB,WAAW,IAAI,OAAO,CAAC,MAAM,CAAC,CA8BnD;AAED;;;;GAIG;AACH,wBAAsB,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC,CAIlD;AAED;;;;;;;;;GASG;AACH,wBAAsB,SAAS,CAAC,IAAI,GAAE,MAAM,EAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CA4EpE"}
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/commands.ts"],
4
- "sourcesContent": ["import { killBedrockServerByImage, probeBdsStatus, clearBdsPidFile } from \"@sfmc-bds/bds-tools/process-probe\";\nimport {\n DEFAULT_QQ_CONFIG,\n loadEnsuredConfig,\n qqRuntimeStatusPath,\n type QQBridgeConfig,\n} from \"@sfmc-bds/sdk/node/config\";\nimport { findNodeServicePids, killNodeServiceByScript, type NodeServiceName } from \"./node-service-probe.js\";\nimport { pushLog as pushUnifiedLog } from \"./logs.js\";\nimport { t } from \"./i18n/index.js\";\nimport { spawnService } from \"./runtime.js\";\nimport { ROOT, SERVICE_NAMES, queryServicesRuntime, services, type ServiceName } from \"./services.js\";\nimport { c, DIVIDER, highlightLogLine, padRight } from \"./theme.js\";\nimport { stripTaskbarOsc } from \"@sfmc-bds/bds-tools/taskbar\";\nimport { didUpdateDeploy } from \"@sfmc-bds/bds-tools/update-result\";\nimport fs from \"node:fs\";\n\nfunction parseService(raw: string): ServiceName | null {\n const s = raw.toLowerCase() as ServiceName;\n if (SERVICE_NAMES.includes(s)) return s;\n return null;\n}\n\nfunction statusLine(\n name: string,\n running: boolean,\n pid: number,\n uptime: string,\n ownership?: \"managed\" | \"external\"\n): string {\n const dot = running ? c.green(\"\u25CF\") : c.dim(\"\u25CB\");\n const state = running ? c.green(t(\"svc.state.running\")) : c.dim(t(\"svc.state.stopped\"));\n let owner = c.dim(t(\"svc.owner.none\"));\n if (running && ownership === \"managed\") owner = c.cyan(t(\"svc.owner.managed\"));\n else if (running && ownership === \"external\") owner = c.yellow(t(\"svc.owner.external\"));\n const pidStr = pid ? c.dim(String(pid)) : c.dim(\"\u2014\");\n const upStr = uptime !== \"\u2014\" ? c.dim(uptime) : c.dim(\"\u2014\");\n return ` ${dot} ${c.bold(padRight(name, 14))} ${padRight(state, 8)} ${padRight(owner, 6)} ${padRight(pidStr, 8)} ${upStr}`;\n}\n\n/** status \u9875\u811A\uFF1AQQ \u540E\u7AEF\u4E0E\u5173\u952E\u6458\u8981\uFF08\u5BC6\u94A5\u8131\u654F\uFF09 */\nfunction qqBridgeStatusFooter(): string {\n const qqCfg = loadEnsuredConfig(\n ROOT,\n \"qq_config.json\",\n \"qq_config\",\n { ...DEFAULT_QQ_CONFIG } as Record<string, unknown>\n ) as QQBridgeConfig;\n const backend = qqCfg.qq_backend === \"llbot\" ? \"llbot\" : \"official\";\n const enabled = qqCfg.qq_enabled !== false;\n if (backend === \"llbot\") {\n const group = qqCfg.qq_group_id || \"\u2014\";\n const pathHint = qqCfg.llbot_path ? String(qqCfg.llbot_path) : \"\u2014\";\n return (\n `\\n${c.dim(t(\"svc.qq.footer.llbot\", { enabled: enabled ? \"on\" : \"off\", group, path: pathHint }))}\\n`\n );\n }\n const appId = String(qqCfg.qq_app_id ?? \"\").trim();\n const appIdHint = appId ? (appId.length > 8 ? `${appId.slice(0, 4)}\u2026${appId.slice(-4)}` : appId) : \"\u2014\";\n const openid = String(qqCfg.qq_group_openid ?? \"\").trim() || \"\u2014\";\n const sandbox = qqCfg.qq_sandbox ? \"sandbox\" : \"prod\";\n const creds = appId && String(qqCfg.qq_app_secret ?? \"\").trim() ? \"ok\" : \"missing\";\n return (\n `\\n${c.dim(t(\"svc.qq.footer.official\", { enabled: enabled ? \"on\" : \"off\", appId: appIdHint, openid, sandbox, creds }))}\\n`\n );\n}\n\nexport async function cmdStatus(): Promise<string> {\n const rows = await queryServicesRuntime();\n const lines = rows.map((row) => statusLine(row.title, row.running, row.pid, row.uptime, row.ownership));\n const nameH = t(\"svc.col.name\");\n const statusH = t(\"svc.col.status\");\n const ownerH = t(\"svc.col.owner\");\n const pidH = t(\"svc.col.pid\");\n const upH = t(\"svc.col.uptime\");\n const header =\n ` ${padRight(nameH, 16)}${padRight(statusH, 8)}${padRight(ownerH, 6)}${padRight(pidH, 8)}${upH}`;\n return (\n `\\n${c.bold(t(\"svc.header\"))}\\n` +\n c.dim(header) +\n \"\\n\" +\n DIVIDER +\n \"\\n\" +\n lines.join(\"\\n\") +\n qqBridgeStatusFooter()\n );\n}\n\nexport function cmdLogs(args: string[], onFollow?: (serviceName: ServiceName) => void): string {\n let n = 20;\n let follow = false;\n const positional: string[] = [];\n\n for (const a of args) {\n if (a === \"-n\") continue; /* handled below */\n if (a === \"-f\") {\n follow = true;\n continue;\n }\n positional.push(a);\n }\n\n /* -n takes the next argument as value */\n const nIdx = args.indexOf(\"-n\");\n if (nIdx >= 0 && nIdx + 1 < args.length) n = parseInt(args[nIdx + 1] ?? \"0\", 10);\n\n const svcRaw = positional[0];\n if (!svcRaw) return c.yellow(t(\"svc.logs.usage\"));\n\n const svc = parseService(svcRaw);\n if (!svc) return c.red(t(\"svc.unknown\", { name: svcRaw, list: SERVICE_NAMES.join(\", \") }));\n\n const svcObj = services[svc];\n\n const lines = svcObj.getRecentLogs(n);\n if (lines.length === 0) return c.dim(t(\"svc.logs.empty\"));\n\n const header = `\\n${c.bold(t(\"svc.logs.header\", { title: svcObj.title, count: lines.length }))}`;\n const body = lines\n .map((l) => {\n const ts = c.dim(l.time.toLocaleTimeString());\n const text = highlightLogLine(l.text);\n const prefix = l.stream === \"stderr\" ? c.red(\"!\") : c.dim(\" \");\n return `${ts} ${prefix} ${text}`;\n })\n .join(\"\\n\");\n\n const result = header + \"\\n\" + DIVIDER + \"\\n\" + body + \"\\n\";\n\n if (follow && onFollow) {\n onFollow(svc);\n return \"\";\n }\n\n return result;\n}\n\nconst STARTING = new Set<ServiceName>();\nconst STOPPING = new Set<ServiceName>();\n\nfunction isNodeSvc(name: ServiceName): name is NodeServiceName {\n return name === \"db\" || name === \"qq\";\n}\n\nfunction clearQqRuntimeFile(): void {\n try {\n const file = qqRuntimeStatusPath(ROOT);\n if (fs.existsSync(file)) fs.unlinkSync(file);\n } catch {\n /* ignore */\n }\n}\n\nexport async function cmdStart(raw: string): Promise<string> {\n const svc = parseService(raw);\n if (!svc) return c.red(t(\"svc.unknown\", { name: raw, list: SERVICE_NAMES.join(\", \") }));\n const svcObj = services[svc];\n if (svc === \"bds\") {\n const probe = await probeBdsStatus({ rootDir: ROOT });\n if (probe.state !== \"stopped\") {\n return c.yellow(\n t(\"svc.bdsAlreadyRunning\", {\n pid: String(probe.pid),\n kind: probe.state === \"managed\" ? t(\"svc.running\") : t(\"svc.runningExternal\"),\n })\n );\n }\n }\n // \u5916\u90E8\u5DF2\u5728\u8DD1\uFF1A\u7981\u6B62\u518D spawn\uFF08\u907F\u514D\u53CC db / \u53CC qq\uFF09\n if (isNodeSvc(svc)) {\n const external = await findNodeServicePids(svc);\n if (external.length > 0) {\n return c.yellow(\n t(\"svc.alreadyRunning\", { title: svcObj.title, pid: String(external.join(\",\")) })\n );\n }\n }\n if (svcObj.running) return c.yellow(t(\"svc.alreadyRunning\", { title: svcObj.title, pid: svcObj.pid }));\n if (STARTING.has(svc)) return c.dim(t(\"svc.alreadyStarting\", { title: svcObj.title }));\n STARTING.add(svc);\n try {\n const outcome = await svcObj.start();\n if (outcome.status === \"skipped\") {\n return c.yellow(t(\"svc.skipped\", { title: svcObj.title, reason: outcome.reason }));\n }\n if (outcome.status === \"already\") {\n return c.yellow(t(\"svc.alreadyRunning\", { title: svcObj.title, pid: svcObj.pid }));\n }\n return c.green(t(\"svc.started\", { title: svcObj.title }));\n } catch (e) {\n return c.red(t(\"svc.startFailed\", { title: svcObj.title, message: (e as Error).message }));\n } finally {\n STARTING.delete(svc);\n }\n}\n\nexport async function cmdStop(raw: string): Promise<string> {\n const svc = parseService(raw);\n if (!svc) return c.red(t(\"svc.unknown\", { name: raw, list: SERVICE_NAMES.join(\", \") }));\n const svcObj = services[svc];\n if (svc === \"bds\") {\n const probe = await probeBdsStatus({\n managedPid: svcObj.pid,\n hasStdin: Boolean(svcObj.proc?.stdin),\n rootDir: ROOT,\n });\n if (probe.state === \"external\") {\n if (STOPPING.has(svc)) return c.dim(t(\"svc.alreadyStopping\", { title: svcObj.title }));\n STOPPING.add(svc);\n try {\n await killBedrockServerByImage();\n clearBdsPidFile(ROOT);\n return c.dim(t(\"svc.stoppedExternal\", { title: svcObj.title }));\n } catch (e) {\n return c.red(t(\"svc.stopFailed\", { title: svcObj.title, message: (e as Error).message }));\n } finally {\n STOPPING.delete(svc);\n }\n }\n }\n\n // db / qq\uFF1A\u6258\u7BA1\u6216\u5916\u90E8\u90FD\u8981\u80FD\u505C\u5E72\u51C0\n if (isNodeSvc(svc)) {\n if (STOPPING.has(svc)) return c.dim(t(\"svc.alreadyStopping\", { title: svcObj.title }));\n STOPPING.add(svc);\n try {\n const managed = svcObj.running;\n if (managed) {\n await svcObj.stop();\n }\n const killed = await killNodeServiceByScript(svc);\n if (svc === \"qq\") clearQqRuntimeFile();\n if (!managed && killed.length === 0) {\n return c.yellow(t(\"svc.alreadyStopped\", { title: svcObj.title }));\n }\n if (!managed && killed.length > 0) {\n return c.dim(t(\"svc.stoppedExternal\", { title: svcObj.title }));\n }\n return c.dim(t(\"svc.stoppedMsg\", { title: svcObj.title }));\n } catch (e) {\n return c.red(t(\"svc.stopFailed\", { title: svcObj.title, message: (e as Error).message }));\n } finally {\n STOPPING.delete(svc);\n }\n }\n\n if (!svcObj.running) return c.yellow(t(\"svc.alreadyStopped\", { title: svcObj.title }));\n if (STOPPING.has(svc)) return c.dim(t(\"svc.alreadyStopping\", { title: svcObj.title }));\n STOPPING.add(svc);\n try {\n await svcObj.stop();\n return c.dim(t(\"svc.stoppedMsg\", { title: svcObj.title }));\n } catch (e) {\n return c.red(t(\"svc.stopFailed\", { title: svcObj.title, message: (e as Error).message }));\n } finally {\n STOPPING.delete(svc);\n }\n}\n\nexport async function cmdSend(raw: string, message: string): Promise<string> {\n const svc = parseService(raw);\n if (!svc) return c.red(t(\"svc.unknown\", { name: raw, list: SERVICE_NAMES.join(\", \") }));\n if (!message) return c.yellow(t(\"svc.send.usage\"));\n const svcObj = services[svc];\n /* \u5148\u7EDF\u4E00\u63A2\u6D4B\uFF0C\u907F\u514D\u5185\u5B58 running \u4E0E\u771F\u5B9E\u8FDB\u7A0B\u8131\u8282 */\n await queryServicesRuntime();\n if (svc === \"bds\") {\n const probe = await probeBdsStatus({\n managedPid: svcObj.pid,\n hasStdin: Boolean(svcObj.proc?.stdin),\n rootDir: ROOT,\n });\n if (probe.state === \"external\") {\n return c.yellow(t(\"svc.stdinUnavailable\", { title: svcObj.title }));\n }\n }\n if (!svcObj.running || !svcObj.proc?.stdin) return c.yellow(t(\"svc.notRunning\", { title: svcObj.title }));\n try {\n svcObj.proc.stdin.write(message + \"\\n\");\n return \"\";\n } catch {\n return c.red(t(\"svc.writeFailed\"));\n }\n}\n\nexport async function cmdRestart(raw: string): Promise<string> {\n const svc = parseService(raw);\n if (!svc) return c.red(t(\"svc.unknown\", { name: raw, list: SERVICE_NAMES.join(\", \") }));\n // bds / db / qq\uFF1A\u7EDF\u4E00\u8D70 stop\u2192start\uFF0C\u786E\u4FDD\u5916\u90E8\u5B9E\u4F8B\u4E5F\u88AB\u6E05\u6389\n if (svc === \"bds\" || isNodeSvc(svc)) {\n const stopMsg = await cmdStop(svc);\n const startMsg = await cmdStart(svc);\n // \u82E5 stop \u5DF2\u62A5\u9519\u6587\u6848\u542B\u300C\u5931\u8D25\u300D\uFF0C\u539F\u6837\u5E26\u56DE\n if (/\u5931\u8D25|failed/i.test(stopMsg) && !/\u5DF2\u505C\u6B62|stopped|already/i.test(stopMsg)) {\n return stopMsg;\n }\n if (/\u5931\u8D25|failed/i.test(startMsg)) return startMsg;\n return c.green(t(\"svc.restarted\", { title: services[svc].title }));\n }\n const svcObj = services[svc];\n try {\n const outcome = await svcObj.restart();\n if (outcome.status === \"skipped\") {\n return c.yellow(t(\"svc.skipped\", { title: svcObj.title, reason: outcome.reason }));\n }\n return c.green(t(\"svc.restarted\", { title: svcObj.title }));\n } catch (e) {\n return c.red(t(\"svc.restartFailed\", { title: svcObj.title, message: (e as Error).message }));\n }\n}\n\nexport async function cmdStartAll(): Promise<string> {\n const { startAll } = await import(\"./services.js\");\n const result = await startAll();\n const parts: string[] = [];\n if (result.started.length > 0) {\n parts.push(c.green(t(\"svc.startAll.started\", { list: result.started.join(\", \") })));\n }\n if (result.skipped.length > 0) {\n parts.push(\n c.dim(\n t(\"svc.startAll.skipped\", {\n list: result.skipped.map((s) => `${s.name}(${s.reason})`).join(\"; \"),\n })\n )\n );\n }\n if (result.failed.length > 0) {\n parts.push(\n c.red(\n t(\"svc.startAll.failed\", {\n list: result.failed.map((s) => `${s.name}: ${s.reason}`).join(\"; \"),\n })\n )\n );\n }\n if (parts.length === 0) return c.dim(t(\"svc.startAll.empty\"));\n if (result.failed.length === 0 && result.skipped.length === 0) {\n return c.green(t(\"svc.allStarted\"));\n }\n return parts.join(\"\\n\");\n}\n\nexport async function cmdStopAll(): Promise<string> {\n const { stopAll } = await import(\"./services.js\");\n await stopAll();\n return c.dim(t(\"svc.allStopped\"));\n}\n\n/**\n * BDS \u66F4\u65B0\uFF1A\u5B50\u8FDB\u7A0B\u59CB\u7EC8 --no-start\uFF0C\u7531 sfmc \u76D1\u7763\u5668\u63A5\u7BA1\u542F\u505C\u4E0E\u65E5\u5FD7\u3002\n * \uFF08updater \u5185 detached \u81EA\u542F\u4F1A\u5BFC\u81F4 REPL \u4E22 PID / \u65E0 stdout\uFF09\n *\n * \u4E0D\u505C\u670D\u9884\u64CD\u4F5C\uFF1A\u771F\u6B63\u9700\u8981\u66F4\u65B0\u65F6\u7531 updater \u505C\u670D\uFF1B\u5DF2\u662F\u6700\u65B0\u5219\u4E0D\u5F71\u54CD\u6B63\u5728\u8DD1\u7684 BDS\u3002\n * \u66F4\u65B0\u6210\u529F\u540E\u82E5\u672A\u6307\u5B9A --no-start\uFF0C\u518D\u7531\u76D1\u7763\u5668 `start bds`\uFF08\u63A5\u7BA1 PID + \u65E5\u5FD7\u7BA1\u9053\uFF09\u3002\n */\nexport async function cmdUpdate(args: string[] = []): Promise<string> {\n const userNoStart = args.includes(\"--no-start\");\n const checkOnly = args.includes(\"--check-only\");\n const spawnArgs = userNoStart ? [...args] : [...args, \"--no-start\"];\n\n const bds = services.bds;\n const bdsProbe = await probeBdsStatus({\n managedPid: bds.pid,\n hasStdin: Boolean(bds.proc?.stdin),\n rootDir: ROOT,\n });\n const bdsWasRunning = bdsProbe.state !== \"stopped\";\n\n const result = await new Promise<{ code: number | null; out: string }>((resolve) => {\n const proc = spawnService(\"update\", spawnArgs, {\n cwd: ROOT,\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n });\n let out = \"\";\n const pushChunk = (raw: string, level: \"info\" | \"error\"): void => {\n // \u5265\u79BB Windows Terminal \u4EFB\u52A1\u680F OSC\uFF0C\u907F\u514D pipe \u65E5\u5FD7\u7A7A\u767D\u884C\uFF08\u6743\u5A01\uFF1Abds-tools/taskbar\uFF09\n const s = stripTaskbarOsc(raw);\n out += s;\n for (const line of s\n .split(/\\r?\\n/)\n .map((l) => l.trimEnd())\n .filter((l) => l.length > 0)) {\n pushUnifiedLog(line, \"update\", level);\n }\n };\n proc.stdout?.on(\"data\", (d: Buffer) => pushChunk(d.toString(), \"info\"));\n proc.stderr?.on(\"data\", (d: Buffer) => pushChunk(d.toString(), \"error\"));\n proc.on(\"exit\", (code) => {\n if (code === 0) {\n pushUnifiedLog(t(\"svc.updateComplete\"), \"system\", \"success\");\n resolve({ code: 0, out: (out ? out + \"\\n\" : \"\") + t(\"svc.updateComplete\") });\n } else {\n resolve({ code, out: out || t(\"svc.updateExited\", { code: String(code) }) });\n }\n });\n proc.on(\"error\", (e) => {\n pushUnifiedLog(t(\"svc.updateError\", { message: e.message }), \"system\", \"error\");\n resolve({ code: 1, out: t(\"svc.updateError\", { message: e.message }) });\n });\n });\n\n /* \u4EC5\u5728\u771F\u6B63\u5B8C\u6210\u90E8\u7F72\u540E\u62C9\u8D77 BDS\uFF1B\u300C\u5DF2\u662F\u6700\u65B0\u300D\u4E0D\u6253\u6270\u5F53\u524D\u72B6\u6001\u3002\n * \u4EE5 updater \u8F93\u51FA\u7684 SFMC_UPDATE_RESULT=deployed \u673A\u5668\u6807\u8BB0\u4E3A\u51C6\uFF08\u52FF\u5339\u914D\u672C\u5730\u5316\u65E5\u5FD7\uFF09\u3002 */\n const didDeploy = didUpdateDeploy(result.out);\n if (result.code === 0 && didDeploy && !userNoStart && !checkOnly) {\n const afterProbe = await probeBdsStatus({\n managedPid: bds.pid,\n hasStdin: Boolean(bds.proc?.stdin),\n rootDir: ROOT,\n });\n if (afterProbe.state !== \"stopped\") {\n return result.out;\n }\n try {\n pushUnifiedLog(t(\"svc.updateStartBds\"), \"system\", \"info\");\n await bds.start();\n return result.out + \"\\n\" + c.green(t(\"svc.bdsStarted\"));\n } catch (e) {\n return result.out + \"\\n\" + c.red(t(\"svc.bdsStartFailed\", { message: (e as Error).message }));\n }\n }\n\n if (result.code === 0 && didDeploy && userNoStart && bdsWasRunning) {\n const afterProbe = await probeBdsStatus({ rootDir: ROOT });\n if (afterProbe.state === \"stopped\") {\n return result.out + \"\\n\" + c.yellow(t(\"svc.bdsStoppedForUpdate\"));\n }\n }\n\n return result.out;\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * commands.ts \u2014 CLI \u6838\u5FC3\u8FD0\u7EF4\u547D\u4EE4\u5B9E\u73B0\n *\n * \u63D0\u4F9B\u547D\u4EE4\u884C\u4E0E REPL \u5171\u4EAB\u7684\u7CFB\u7EDF\u7EA7\u8FD0\u7EF4\u6307\u4EE4\uFF1A\n * - `status`\uFF1A\u67E5\u8BE2\u5168\u90E8\u670D\u52A1\uFF08BDS\u3001db-server\u3001qq-bridge\u3001LLBot\uFF09\u8FD0\u884C\u72B6\u6001\u3001PID\u3001\u8FD0\u884C\u65F6\u957F\u4E0E\u6240\u6709\u6743\n * - `start` / `stop` / `restart`\uFF1A\u6309\u4F9D\u8D56\u987A\u5E8F\u6216\u5355\u4E2A\u63A7\u5236\u670D\u52A1\u542F\u505C\n * - `startAll` / `stopAll`\uFF1A\u6279\u91CF\u7F16\u6392\u63A7\u5236\u6240\u6709\u540E\u53F0\u670D\u52A1\n * - `logs`\uFF1A\u68C0\u7D22\u5E76\u5B9E\u65F6\u8FFD\u8E2A\u6307\u5B9A\u670D\u52A1\u7684\u6700\u8FD1\u65E5\u5FD7\u6D41\n * - `update`\uFF1A\u89E6\u53D1 BDS \u6838\u5FC3\u7248\u672C\u66F4\u65B0\u68C0\u67E5\u4E0E\u70ED\u5347\u7EA7\n */\n\nimport { killBedrockServerByImage, probeBdsStatus, clearBdsPidFile } from \"@sfmc-bds/bds-tools/process-probe\";\nimport {\n DEFAULT_QQ_CONFIG,\n loadEnsuredConfig,\n qqRuntimeStatusPath,\n type QQBridgeConfig,\n} from \"@sfmc-bds/sdk/node/config\";\nimport { findNodeServicePids, killNodeServiceByScript, type NodeServiceName } from \"./node-service-probe.js\";\nimport { pushLog as pushUnifiedLog } from \"./logs.js\";\nimport { t } from \"./i18n/index.js\";\nimport { spawnService } from \"./runtime.js\";\nimport { ROOT, SERVICE_NAMES, queryServicesRuntime, services, type ServiceName } from \"./services.js\";\nimport { c, DIVIDER, highlightLogLine, padRight } from \"./theme.js\";\nimport { stripTaskbarOsc } from \"@sfmc-bds/bds-tools/taskbar\";\nimport { didUpdateDeploy } from \"@sfmc-bds/bds-tools/update-result\";\nimport fs from \"node:fs\";\n\n\nfunction parseService(raw: string): ServiceName | null {\n const s = raw.toLowerCase() as ServiceName;\n if (SERVICE_NAMES.includes(s)) return s;\n return null;\n}\n\nfunction statusLine(\n name: string,\n running: boolean,\n pid: number,\n uptime: string,\n ownership?: \"managed\" | \"external\"\n): string {\n const dot = running ? c.green(\"\u25CF\") : c.dim(\"\u25CB\");\n const state = running ? c.green(t(\"svc.state.running\")) : c.dim(t(\"svc.state.stopped\"));\n let owner = c.dim(t(\"svc.owner.none\"));\n if (running && ownership === \"managed\") owner = c.cyan(t(\"svc.owner.managed\"));\n else if (running && ownership === \"external\") owner = c.yellow(t(\"svc.owner.external\"));\n const pidStr = pid ? c.dim(String(pid)) : c.dim(\"\u2014\");\n const upStr = uptime !== \"\u2014\" ? c.dim(uptime) : c.dim(\"\u2014\");\n return ` ${dot} ${c.bold(padRight(name, 14))} ${padRight(state, 8)} ${padRight(owner, 6)} ${padRight(pidStr, 8)} ${upStr}`;\n}\n\n/** status \u9875\u811A\uFF1AQQ \u540E\u7AEF\u4E0E\u5173\u952E\u6458\u8981\uFF08\u5BC6\u94A5\u8131\u654F\uFF09 */\nfunction qqBridgeStatusFooter(): string {\n const qqCfg = loadEnsuredConfig(\n ROOT,\n \"qq_config.json\",\n \"qq_config\",\n { ...DEFAULT_QQ_CONFIG } as Record<string, unknown>\n ) as QQBridgeConfig;\n const backend = qqCfg.qq_backend === \"llbot\" ? \"llbot\" : \"official\";\n const enabled = qqCfg.qq_enabled !== false;\n if (backend === \"llbot\") {\n const group = qqCfg.qq_group_id || \"\u2014\";\n const pathHint = qqCfg.llbot_path ? String(qqCfg.llbot_path) : \"\u2014\";\n return (\n `\\n${c.dim(t(\"svc.qq.footer.llbot\", { enabled: enabled ? \"on\" : \"off\", group, path: pathHint }))}\\n`\n );\n }\n const appId = String(qqCfg.qq_app_id ?? \"\").trim();\n const appIdHint = appId ? (appId.length > 8 ? `${appId.slice(0, 4)}\u2026${appId.slice(-4)}` : appId) : \"\u2014\";\n const openid = String(qqCfg.qq_group_openid ?? \"\").trim() || \"\u2014\";\n const sandbox = qqCfg.qq_sandbox ? \"sandbox\" : \"prod\";\n const creds = appId && String(qqCfg.qq_app_secret ?? \"\").trim() ? \"ok\" : \"missing\";\n return (\n `\\n${c.dim(t(\"svc.qq.footer.official\", { enabled: enabled ? \"on\" : \"off\", appId: appIdHint, openid, sandbox, creds }))}\\n`\n );\n}\n\n/**\n * \u67E5\u8BE2\u5E76\u683C\u5F0F\u5316\u5C55\u793A\u6240\u6709\u540E\u53F0\u670D\u52A1\u7684\u5F53\u524D\u8FD0\u884C\u72B6\u6001\u77E9\u9635\u3002\n *\n * @returns \u683C\u5F0F\u5316\u540E\u7684\u72B6\u6001\u6458\u8981\u6587\u672C\u8868\u683C\u3002\n */\nexport async function cmdStatus(): Promise<string> {\n const rows = await queryServicesRuntime();\n const lines = rows.map((row) => statusLine(row.title, row.running, row.pid, row.uptime, row.ownership));\n const nameH = t(\"svc.col.name\");\n const statusH = t(\"svc.col.status\");\n const ownerH = t(\"svc.col.owner\");\n const pidH = t(\"svc.col.pid\");\n const upH = t(\"svc.col.uptime\");\n const header =\n ` ${padRight(nameH, 16)}${padRight(statusH, 8)}${padRight(ownerH, 6)}${padRight(pidH, 8)}${upH}`;\n return (\n `\\n${c.bold(t(\"svc.header\"))}\\n` +\n c.dim(header) +\n \"\\n\" +\n DIVIDER +\n \"\\n\" +\n lines.join(\"\\n\") +\n qqBridgeStatusFooter()\n );\n}\n\n/**\n * \u68C0\u7D22\u5E76\u683C\u5F0F\u5316\u6307\u5B9A\u670D\u52A1\u7684\u6700\u8FD1\u5386\u53F2\u65E5\u5FD7\u884C\uFF08\u652F\u6301 `-n <\u884C\u6570>` \u53CA `-f` \u5B9E\u65F6\u8FFD\u8E2A\uFF09\u3002\n *\n * @param args \u53C2\u6570\u5217\u8868\u3002\n * @param onFollow \u53EF\u9009\u7684\u8DDF\u968F\u6A21\u5F0F\u56DE\u8C03\u3002\n * @returns \u683C\u5F0F\u5316\u540E\u7684\u65E5\u5FD7\u8F93\u51FA\u6587\u672C\u3002\n */\nexport function cmdLogs(args: string[], onFollow?: (serviceName: ServiceName) => void): string {\n let n = 20;\n let follow = false;\n const positional: string[] = [];\n\n for (const a of args) {\n if (a === \"-n\") continue; /* handled below */\n if (a === \"-f\") {\n follow = true;\n continue;\n }\n positional.push(a);\n }\n\n /* -n takes the next argument as value */\n const nIdx = args.indexOf(\"-n\");\n if (nIdx >= 0 && nIdx + 1 < args.length) n = parseInt(args[nIdx + 1] ?? \"0\", 10);\n\n const svcRaw = positional[0];\n if (!svcRaw) return c.yellow(t(\"svc.logs.usage\"));\n\n const svc = parseService(svcRaw);\n if (!svc) return c.red(t(\"svc.unknown\", { name: svcRaw, list: SERVICE_NAMES.join(\", \") }));\n\n const svcObj = services[svc];\n\n const lines = svcObj.getRecentLogs(n);\n if (lines.length === 0) return c.dim(t(\"svc.logs.empty\"));\n\n const header = `\\n${c.bold(t(\"svc.logs.header\", { title: svcObj.title, count: lines.length }))}`;\n const body = lines\n .map((l) => {\n const ts = c.dim(l.time.toLocaleTimeString());\n const text = highlightLogLine(l.text);\n const prefix = l.stream === \"stderr\" ? c.red(\"!\") : c.dim(\" \");\n return `${ts} ${prefix} ${text}`;\n })\n .join(\"\\n\");\n\n const result = header + \"\\n\" + DIVIDER + \"\\n\" + body + \"\\n\";\n\n if (follow && onFollow) {\n onFollow(svc);\n return \"\";\n }\n\n return result;\n}\n\nconst STARTING = new Set<ServiceName>();\nconst STOPPING = new Set<ServiceName>();\n\nfunction isNodeSvc(name: ServiceName): name is NodeServiceName {\n return name === \"db\" || name === \"qq\";\n}\n\nfunction clearQqRuntimeFile(): void {\n try {\n const file = qqRuntimeStatusPath(ROOT);\n if (fs.existsSync(file)) fs.unlinkSync(file);\n } catch {\n /* ignore */\n }\n}\n\n/**\n * \u542F\u52A8\u6307\u5B9A\u7684\u5355\u9879\u540E\u53F0\u670D\u52A1\uFF08bds / db / qq / llbot\uFF09\u3002\n *\n * @param raw \u76EE\u6807\u670D\u52A1\u540D\u79F0\u5B57\u7B26\u4E32\u3002\n * @returns \u542F\u52A8\u7ED3\u679C\u63CF\u8FF0\u6587\u672C\u3002\n */\nexport async function cmdStart(raw: string): Promise<string> {\n const svc = parseService(raw);\n if (!svc) return c.red(t(\"svc.unknown\", { name: raw, list: SERVICE_NAMES.join(\", \") }));\n const svcObj = services[svc];\n if (svc === \"bds\") {\n const probe = await probeBdsStatus({ rootDir: ROOT });\n if (probe.state !== \"stopped\") {\n return c.yellow(\n t(\"svc.bdsAlreadyRunning\", {\n pid: String(probe.pid),\n kind: probe.state === \"managed\" ? t(\"svc.running\") : t(\"svc.runningExternal\"),\n })\n );\n }\n }\n // \u5916\u90E8\u5DF2\u5728\u8DD1\uFF1A\u7981\u6B62\u518D spawn\uFF08\u907F\u514D\u53CC db / \u53CC qq\uFF09\n if (isNodeSvc(svc)) {\n const external = await findNodeServicePids(svc);\n if (external.length > 0) {\n return c.yellow(\n t(\"svc.alreadyRunning\", { title: svcObj.title, pid: String(external.join(\",\")) })\n );\n }\n }\n if (svcObj.running) return c.yellow(t(\"svc.alreadyRunning\", { title: svcObj.title, pid: svcObj.pid }));\n if (STARTING.has(svc)) return c.dim(t(\"svc.alreadyStarting\", { title: svcObj.title }));\n STARTING.add(svc);\n try {\n const outcome = await svcObj.start();\n if (outcome.status === \"skipped\") {\n return c.yellow(t(\"svc.skipped\", { title: svcObj.title, reason: outcome.reason }));\n }\n if (outcome.status === \"already\") {\n return c.yellow(t(\"svc.alreadyRunning\", { title: svcObj.title, pid: svcObj.pid }));\n }\n return c.green(t(\"svc.started\", { title: svcObj.title }));\n } catch (e) {\n return c.red(t(\"svc.startFailed\", { title: svcObj.title, message: (e as Error).message }));\n } finally {\n STARTING.delete(svc);\n }\n}\n\n/**\n * \u505C\u6B62\u6307\u5B9A\u7684\u5355\u9879\u540E\u53F0\u670D\u52A1\uFF08\u652F\u6301\u5BF9\u5916\u90E8\u975E\u6258\u7BA1\u5B9E\u4F8B\u6267\u884C\u7CBE\u51C6\u6E05\u7406\uFF09\u3002\n *\n * @param raw \u76EE\u6807\u670D\u52A1\u540D\u79F0\u5B57\u7B26\u4E32\u3002\n * @returns \u505C\u6B62\u64CD\u4F5C\u7ED3\u679C\u6587\u672C\u3002\n */\nexport async function cmdStop(raw: string): Promise<string> {\n\n const svc = parseService(raw);\n if (!svc) return c.red(t(\"svc.unknown\", { name: raw, list: SERVICE_NAMES.join(\", \") }));\n const svcObj = services[svc];\n if (svc === \"bds\") {\n const probe = await probeBdsStatus({\n managedPid: svcObj.pid,\n hasStdin: Boolean(svcObj.proc?.stdin),\n rootDir: ROOT,\n });\n if (probe.state === \"external\") {\n if (STOPPING.has(svc)) return c.dim(t(\"svc.alreadyStopping\", { title: svcObj.title }));\n STOPPING.add(svc);\n try {\n await killBedrockServerByImage();\n clearBdsPidFile(ROOT);\n return c.dim(t(\"svc.stoppedExternal\", { title: svcObj.title }));\n } catch (e) {\n return c.red(t(\"svc.stopFailed\", { title: svcObj.title, message: (e as Error).message }));\n } finally {\n STOPPING.delete(svc);\n }\n }\n }\n\n // db / qq\uFF1A\u6258\u7BA1\u6216\u5916\u90E8\u90FD\u8981\u80FD\u505C\u5E72\u51C0\n if (isNodeSvc(svc)) {\n if (STOPPING.has(svc)) return c.dim(t(\"svc.alreadyStopping\", { title: svcObj.title }));\n STOPPING.add(svc);\n try {\n const managed = svcObj.running;\n if (managed) {\n await svcObj.stop();\n }\n const killed = await killNodeServiceByScript(svc);\n if (svc === \"qq\") clearQqRuntimeFile();\n if (!managed && killed.length === 0) {\n return c.yellow(t(\"svc.alreadyStopped\", { title: svcObj.title }));\n }\n if (!managed && killed.length > 0) {\n return c.dim(t(\"svc.stoppedExternal\", { title: svcObj.title }));\n }\n return c.dim(t(\"svc.stoppedMsg\", { title: svcObj.title }));\n } catch (e) {\n return c.red(t(\"svc.stopFailed\", { title: svcObj.title, message: (e as Error).message }));\n } finally {\n STOPPING.delete(svc);\n }\n }\n\n if (!svcObj.running) return c.yellow(t(\"svc.alreadyStopped\", { title: svcObj.title }));\n if (STOPPING.has(svc)) return c.dim(t(\"svc.alreadyStopping\", { title: svcObj.title }));\n STOPPING.add(svc);\n try {\n await svcObj.stop();\n return c.dim(t(\"svc.stoppedMsg\", { title: svcObj.title }));\n } catch (e) {\n return c.red(t(\"svc.stopFailed\", { title: svcObj.title, message: (e as Error).message }));\n } finally {\n STOPPING.delete(svc);\n }\n}\n\nexport async function cmdSend(raw: string, message: string): Promise<string> {\n const svc = parseService(raw);\n if (!svc) return c.red(t(\"svc.unknown\", { name: raw, list: SERVICE_NAMES.join(\", \") }));\n if (!message) return c.yellow(t(\"svc.send.usage\"));\n const svcObj = services[svc];\n /* \u5148\u7EDF\u4E00\u63A2\u6D4B\uFF0C\u907F\u514D\u5185\u5B58 running \u4E0E\u771F\u5B9E\u8FDB\u7A0B\u8131\u8282 */\n await queryServicesRuntime();\n if (svc === \"bds\") {\n const probe = await probeBdsStatus({\n managedPid: svcObj.pid,\n hasStdin: Boolean(svcObj.proc?.stdin),\n rootDir: ROOT,\n });\n if (probe.state === \"external\") {\n return c.yellow(t(\"svc.stdinUnavailable\", { title: svcObj.title }));\n }\n }\n if (!svcObj.running || !svcObj.proc?.stdin) return c.yellow(t(\"svc.notRunning\", { title: svcObj.title }));\n try {\n svcObj.proc.stdin.write(message + \"\\n\");\n return \"\";\n } catch {\n return c.red(t(\"svc.writeFailed\"));\n }\n}\n\n/**\n * \u91CD\u542F\u6307\u5B9A\u7684\u5355\u9879\u540E\u53F0\u670D\u52A1\uFF08\u9075\u5FAA stop \u2192 start \u4E25\u8C28\u65F6\u5E8F\uFF09\u3002\n *\n * @param raw \u76EE\u6807\u670D\u52A1\u540D\u79F0\u5B57\u7B26\u4E32\u3002\n * @returns \u91CD\u542F\u64CD\u4F5C\u7ED3\u679C\u6587\u672C\u3002\n */\nexport async function cmdRestart(raw: string): Promise<string> {\n const svc = parseService(raw);\n if (!svc) return c.red(t(\"svc.unknown\", { name: raw, list: SERVICE_NAMES.join(\", \") }));\n // bds / db / qq\uFF1A\u7EDF\u4E00\u8D70 stop\u2192start\uFF0C\u786E\u4FDD\u5916\u90E8\u5B9E\u4F8B\u4E5F\u88AB\u6E05\u6389\n if (svc === \"bds\" || isNodeSvc(svc)) {\n const stopMsg = await cmdStop(svc);\n const startMsg = await cmdStart(svc);\n // \u82E5 stop \u5DF2\u62A5\u9519\u6587\u6848\u542B\u300C\u5931\u8D25\u300D\uFF0C\u539F\u6837\u5E26\u56DE\n if (/\u5931\u8D25|failed/i.test(stopMsg) && !/\u5DF2\u505C\u6B62|stopped|already/i.test(stopMsg)) {\n return stopMsg;\n }\n if (/\u5931\u8D25|failed/i.test(startMsg)) return startMsg;\n return c.green(t(\"svc.restarted\", { title: services[svc].title }));\n }\n const svcObj = services[svc];\n try {\n const outcome = await svcObj.restart();\n if (outcome.status === \"skipped\") {\n return c.yellow(t(\"svc.skipped\", { title: svcObj.title, reason: outcome.reason }));\n }\n return c.green(t(\"svc.restarted\", { title: svcObj.title }));\n } catch (e) {\n return c.red(t(\"svc.restartFailed\", { title: svcObj.title, message: (e as Error).message }));\n }\n}\n\n/**\n * \u6309\u670D\u52A1\u62D3\u6251\u4F9D\u8D56\u6B21\u5E8F\u6279\u91CF\u542F\u52A8\u6240\u6709\u5DF2\u542F\u7528\u7684\u540E\u53F0\u670D\u52A1\u3002\n *\n * @returns \u6279\u91CF\u542F\u52A8\u7ED3\u679C\u7EDF\u8BA1\u62A5\u544A\u6587\u672C\u3002\n */\nexport async function cmdStartAll(): Promise<string> {\n const { startAll } = await import(\"./services.js\");\n const result = await startAll();\n const parts: string[] = [];\n if (result.started.length > 0) {\n parts.push(c.green(t(\"svc.startAll.started\", { list: result.started.join(\", \") })));\n }\n if (result.skipped.length > 0) {\n parts.push(\n c.dim(\n t(\"svc.startAll.skipped\", {\n list: result.skipped.map((s) => `${s.name}(${s.reason})`).join(\"; \"),\n })\n )\n );\n }\n if (result.failed.length > 0) {\n parts.push(\n c.red(\n t(\"svc.startAll.failed\", {\n list: result.failed.map((s) => `${s.name}: ${s.reason}`).join(\"; \"),\n })\n )\n );\n }\n if (parts.length === 0) return c.dim(t(\"svc.startAll.empty\"));\n if (result.failed.length === 0 && result.skipped.length === 0) {\n return c.green(t(\"svc.allStarted\"));\n }\n return parts.join(\"\\n\");\n}\n\n/**\n * \u6279\u91CF\u505C\u6B62\u6240\u6709\u5F53\u524D\u5904\u4E8E\u8FD0\u884C\u6001\u7684\u540E\u53F0\u670D\u52A1\u3002\n *\n * @returns \u6279\u91CF\u505C\u6B62\u786E\u8BA4\u6587\u672C\u3002\n */\nexport async function cmdStopAll(): Promise<string> {\n const { stopAll } = await import(\"./services.js\");\n await stopAll();\n return c.dim(t(\"svc.allStopped\"));\n}\n\n/**\n * \u89E6\u53D1 BDS \u6838\u5FC3\u7248\u672C\u66F4\u65B0\u68C0\u67E5\u4E0E\u70ED\u5347\u7EA7\u6D41\u7A0B\u3002\n *\n * \u8FDB\u7A0B\u7BA1\u7406\u4E0E\u7F16\u6392\u7EA6\u675F\uFF1A\n * - updater \u5B50\u8FDB\u7A0B\u59CB\u7EC8\u9644\u52A0 `--no-start` \u53C2\u6570\uFF0C\u907F\u514D\u7531\u4E8E\u8FDB\u7A0B\u8131\u79BB\u5BFC\u81F4 REPL \u4E22\u5931 PID \u8DDF\u8E2A\u53CA\u6807\u51C6\u8F93\u51FA\n * - \u82E5\u66F4\u65B0\u524D BDS \u5904\u4E8E\u8FD0\u884C\u72B6\u6001\uFF0C\u4E14\u672A\u663E\u5F0F\u6307\u5B9A `--no-start`\uFF0C\u5728\u66F4\u65B0\u843D\u76D8\u90E8\u7F72\u5B8C\u6210\u540E\u7531\u76D1\u7763\u5668\u91CD\u65B0\u5524\u8D77 BDS\n *\n * @param args \u4F20\u9012\u7ED9\u66F4\u65B0\u5668\u7684\u547D\u4EE4\u884C\u53C2\u6570\u3002\n * @returns \u66F4\u65B0\u6267\u884C\u7ED3\u679C\u6458\u8981\u6587\u672C\u3002\n */\nexport async function cmdUpdate(args: string[] = []): Promise<string> {\n\n const userNoStart = args.includes(\"--no-start\");\n const checkOnly = args.includes(\"--check-only\");\n const spawnArgs = userNoStart ? [...args] : [...args, \"--no-start\"];\n\n const bds = services.bds;\n const bdsProbe = await probeBdsStatus({\n managedPid: bds.pid,\n hasStdin: Boolean(bds.proc?.stdin),\n rootDir: ROOT,\n });\n const bdsWasRunning = bdsProbe.state !== \"stopped\";\n\n const result = await new Promise<{ code: number | null; out: string }>((resolve) => {\n const proc = spawnService(\"update\", spawnArgs, {\n cwd: ROOT,\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n });\n let out = \"\";\n const pushChunk = (raw: string, level: \"info\" | \"error\"): void => {\n // \u5265\u79BB Windows Terminal \u4EFB\u52A1\u680F OSC\uFF0C\u907F\u514D pipe \u65E5\u5FD7\u7A7A\u767D\u884C\uFF08\u6743\u5A01\uFF1Abds-tools/taskbar\uFF09\n const s = stripTaskbarOsc(raw);\n out += s;\n for (const line of s\n .split(/\\r?\\n/)\n .map((l) => l.trimEnd())\n .filter((l) => l.length > 0)) {\n pushUnifiedLog(line, \"update\", level);\n }\n };\n proc.stdout?.on(\"data\", (d: Buffer) => pushChunk(d.toString(), \"info\"));\n proc.stderr?.on(\"data\", (d: Buffer) => pushChunk(d.toString(), \"error\"));\n proc.on(\"exit\", (code) => {\n if (code === 0) {\n pushUnifiedLog(t(\"svc.updateComplete\"), \"system\", \"success\");\n resolve({ code: 0, out: (out ? out + \"\\n\" : \"\") + t(\"svc.updateComplete\") });\n } else {\n resolve({ code, out: out || t(\"svc.updateExited\", { code: String(code) }) });\n }\n });\n proc.on(\"error\", (e) => {\n pushUnifiedLog(t(\"svc.updateError\", { message: e.message }), \"system\", \"error\");\n resolve({ code: 1, out: t(\"svc.updateError\", { message: e.message }) });\n });\n });\n\n /* \u4EC5\u5728\u771F\u6B63\u5B8C\u6210\u90E8\u7F72\u540E\u62C9\u8D77 BDS\uFF1B\u300C\u5DF2\u662F\u6700\u65B0\u300D\u4E0D\u6253\u6270\u5F53\u524D\u72B6\u6001\u3002\n * \u4EE5 updater \u8F93\u51FA\u7684 SFMC_UPDATE_RESULT=deployed \u673A\u5668\u6807\u8BB0\u4E3A\u51C6\uFF08\u52FF\u5339\u914D\u672C\u5730\u5316\u65E5\u5FD7\uFF09\u3002 */\n const didDeploy = didUpdateDeploy(result.out);\n if (result.code === 0 && didDeploy && !userNoStart && !checkOnly) {\n const afterProbe = await probeBdsStatus({\n managedPid: bds.pid,\n hasStdin: Boolean(bds.proc?.stdin),\n rootDir: ROOT,\n });\n if (afterProbe.state !== \"stopped\") {\n return result.out;\n }\n try {\n pushUnifiedLog(t(\"svc.updateStartBds\"), \"system\", \"info\");\n await bds.start();\n return result.out + \"\\n\" + c.green(t(\"svc.bdsStarted\"));\n } catch (e) {\n return result.out + \"\\n\" + c.red(t(\"svc.bdsStartFailed\", { message: (e as Error).message }));\n }\n }\n\n if (result.code === 0 && didDeploy && userNoStart && bdsWasRunning) {\n const afterProbe = await probeBdsStatus({ rootDir: ROOT });\n if (afterProbe.state === \"stopped\") {\n return result.out + \"\\n\" + c.yellow(t(\"svc.bdsStoppedForUpdate\"));\n }\n }\n\n return result.out;\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,76 @@
1
+ import assert from "node:assert/strict";
2
+ import fs from "node:fs";
3
+ import os from "node:os";
4
+ import path from "node:path";
5
+ import test from "node:test";
6
+ import { cmdDebug, isDebugTruthy } from "./debug-command.js";
7
+ function setupSfmcRoot(bdsRoot) {
8
+ const root = fs.mkdtempSync(path.join(os.tmpdir(), "sfmc-debug-"));
9
+ fs.mkdirSync(path.join(root, "configs"), { recursive: true });
10
+ fs.writeFileSync(
11
+ path.join(root, "configs", "bds_updater.json"),
12
+ JSON.stringify({ bds_path: bdsRoot.replace(/\\/g, "/") }, null, 2)
13
+ );
14
+ return root;
15
+ }
16
+ test("isDebugTruthy \u4E0E SDK \u5951\u7EA6\u4E00\u81F4", () => {
17
+ assert.equal(isDebugTruthy(true), true);
18
+ assert.equal(isDebugTruthy(1), true);
19
+ assert.equal(isDebugTruthy("yes"), true);
20
+ assert.equal(isDebugTruthy("on"), true);
21
+ assert.equal(isDebugTruthy(false), false);
22
+ assert.equal(isDebugTruthy("no"), false);
23
+ });
24
+ test("debug enable/disable/status \u5199 BDS variables.json", async () => {
25
+ const bdsRoot = fs.mkdtempSync(path.join(os.tmpdir(), "sfmc-bds-"));
26
+ const sfmcRoot = setupSfmcRoot(bdsRoot);
27
+ const prev = process.env.SFMC_ROOT;
28
+ process.env.SFMC_ROOT = sfmcRoot;
29
+ try {
30
+ const variablesPath = path.join(bdsRoot, "config", "default", "variables.json");
31
+ await cmdDebug(["enable"]);
32
+ const afterEnable = JSON.parse(fs.readFileSync(variablesPath, "utf8"));
33
+ assert.equal(afterEnable.sfmc_debug, true);
34
+ const statusOn = await cmdDebug(["status"]);
35
+ assert.match(statusOn, /sfmc_debug/i);
36
+ await cmdDebug(["disable"]);
37
+ const afterDisable = JSON.parse(fs.readFileSync(variablesPath, "utf8"));
38
+ assert.equal(afterDisable.sfmc_debug, false);
39
+ } finally {
40
+ if (prev === void 0) delete process.env.SFMC_ROOT;
41
+ else process.env.SFMC_ROOT = prev;
42
+ }
43
+ });
44
+ test("debug sentry on/off \u5199 BDS secrets.json", async () => {
45
+ const bdsRoot = fs.mkdtempSync(path.join(os.tmpdir(), "sfmc-bds-"));
46
+ const sfmcRoot = setupSfmcRoot(bdsRoot);
47
+ const prev = process.env.SFMC_ROOT;
48
+ process.env.SFMC_ROOT = sfmcRoot;
49
+ try {
50
+ const secretsPath = path.join(bdsRoot, "config", "default", "secrets.json");
51
+ const dsn = "https://example@o123.ingest.sentry.io/456";
52
+ await cmdDebug(["sentry", "on", "--dsn", dsn]);
53
+ const afterOn = JSON.parse(fs.readFileSync(secretsPath, "utf8"));
54
+ assert.equal(afterOn.SENTRY_DSN, dsn);
55
+ await cmdDebug(["sentry", "off"]);
56
+ const afterOff = JSON.parse(fs.readFileSync(secretsPath, "utf8"));
57
+ assert.equal("SENTRY_DSN" in afterOff, false);
58
+ } finally {
59
+ if (prev === void 0) delete process.env.SFMC_ROOT;
60
+ else process.env.SFMC_ROOT = prev;
61
+ }
62
+ });
63
+ test("debug sentry on \u7F3A --dsn \u62A5\u9519", async () => {
64
+ const bdsRoot = fs.mkdtempSync(path.join(os.tmpdir(), "sfmc-bds-"));
65
+ const sfmcRoot = setupSfmcRoot(bdsRoot);
66
+ const prev = process.env.SFMC_ROOT;
67
+ process.env.SFMC_ROOT = sfmcRoot;
68
+ try {
69
+ const out = await cmdDebug(["sentry", "on"]);
70
+ assert.match(out, /--dsn|required|需要/i);
71
+ } finally {
72
+ if (prev === void 0) delete process.env.SFMC_ROOT;
73
+ else process.env.SFMC_ROOT = prev;
74
+ }
75
+ });
76
+ //# sourceMappingURL=debug-command.test.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/debug-command.test.ts"],
4
+ "sourcesContent": ["/**\n * debug-command BDS variables.json / secrets.json \u8BFB\u5199\n */\nimport assert from \"node:assert/strict\";\nimport fs from \"node:fs\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport test from \"node:test\";\nimport { cmdDebug, isDebugTruthy } from \"./debug-command.js\";\n\nfunction setupSfmcRoot(bdsRoot: string): string {\n const root = fs.mkdtempSync(path.join(os.tmpdir(), \"sfmc-debug-\"));\n fs.mkdirSync(path.join(root, \"configs\"), { recursive: true });\n fs.writeFileSync(\n path.join(root, \"configs\", \"bds_updater.json\"),\n JSON.stringify({ bds_path: bdsRoot.replace(/\\\\/g, \"/\") }, null, 2)\n );\n return root;\n}\n\ntest(\"isDebugTruthy \u4E0E SDK \u5951\u7EA6\u4E00\u81F4\", () => {\n assert.equal(isDebugTruthy(true), true);\n assert.equal(isDebugTruthy(1), true);\n assert.equal(isDebugTruthy(\"yes\"), true);\n assert.equal(isDebugTruthy(\"on\"), true);\n assert.equal(isDebugTruthy(false), false);\n assert.equal(isDebugTruthy(\"no\"), false);\n});\n\ntest(\"debug enable/disable/status \u5199 BDS variables.json\", async () => {\n const bdsRoot = fs.mkdtempSync(path.join(os.tmpdir(), \"sfmc-bds-\"));\n const sfmcRoot = setupSfmcRoot(bdsRoot);\n const prev = process.env.SFMC_ROOT;\n process.env.SFMC_ROOT = sfmcRoot;\n\n try {\n const variablesPath = path.join(bdsRoot, \"config\", \"default\", \"variables.json\");\n\n await cmdDebug([\"enable\"]);\n const afterEnable = JSON.parse(fs.readFileSync(variablesPath, \"utf8\")) as { sfmc_debug?: boolean };\n assert.equal(afterEnable.sfmc_debug, true);\n\n const statusOn = await cmdDebug([\"status\"]);\n assert.match(statusOn, /sfmc_debug/i);\n\n await cmdDebug([\"disable\"]);\n const afterDisable = JSON.parse(fs.readFileSync(variablesPath, \"utf8\")) as { sfmc_debug?: boolean };\n assert.equal(afterDisable.sfmc_debug, false);\n } finally {\n if (prev === undefined) delete process.env.SFMC_ROOT;\n else process.env.SFMC_ROOT = prev;\n }\n});\n\ntest(\"debug sentry on/off \u5199 BDS secrets.json\", async () => {\n const bdsRoot = fs.mkdtempSync(path.join(os.tmpdir(), \"sfmc-bds-\"));\n const sfmcRoot = setupSfmcRoot(bdsRoot);\n const prev = process.env.SFMC_ROOT;\n process.env.SFMC_ROOT = sfmcRoot;\n\n try {\n const secretsPath = path.join(bdsRoot, \"config\", \"default\", \"secrets.json\");\n const dsn = \"https://example@o123.ingest.sentry.io/456\";\n\n await cmdDebug([\"sentry\", \"on\", \"--dsn\", dsn]);\n const afterOn = JSON.parse(fs.readFileSync(secretsPath, \"utf8\")) as { SENTRY_DSN?: string };\n assert.equal(afterOn.SENTRY_DSN, dsn);\n\n await cmdDebug([\"sentry\", \"off\"]);\n const afterOff = JSON.parse(fs.readFileSync(secretsPath, \"utf8\")) as Record<string, unknown>;\n assert.equal(\"SENTRY_DSN\" in afterOff, false);\n } finally {\n if (prev === undefined) delete process.env.SFMC_ROOT;\n else process.env.SFMC_ROOT = prev;\n }\n});\n\ntest(\"debug sentry on \u7F3A --dsn \u62A5\u9519\", async () => {\n const bdsRoot = fs.mkdtempSync(path.join(os.tmpdir(), \"sfmc-bds-\"));\n const sfmcRoot = setupSfmcRoot(bdsRoot);\n const prev = process.env.SFMC_ROOT;\n process.env.SFMC_ROOT = sfmcRoot;\n\n try {\n const out = await cmdDebug([\"sentry\", \"on\"]);\n assert.match(out, /--dsn|required|\u9700\u8981/i);\n } finally {\n if (prev === undefined) delete process.env.SFMC_ROOT;\n else process.env.SFMC_ROOT = prev;\n }\n});\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,27 @@
1
+ export type DirectoryPickerResult = {
2
+ status: "selected";
3
+ path: string;
4
+ } | {
5
+ status: "cancelled";
6
+ } | {
7
+ status: "unavailable";
8
+ };
9
+ export type PickerCommand = {
10
+ command: string;
11
+ args: string[];
12
+ };
13
+ /** PowerShell 单引号字符串转义。 */
14
+ export declare function escapePowerShellSingleQuoted(value: string): string;
15
+ /** AppleScript 双引号字符串转义。 */
16
+ export declare function escapeAppleScriptString(value: string): string;
17
+ /** 选择器起始目录:默认路径不存在时回退到父目录或 cwd。 */
18
+ export declare function resolvePickerStartDir(defaultDirectory: string): string;
19
+ export declare function buildWindowsPickerScript(title: string, defaultDirectory: string): string;
20
+ export declare function buildMacOsPickerScript(title: string, defaultDirectory: string): string;
21
+ /** 按平台生成原生目录选择器命令候选(先试桌面默认,再试通用工具)。 */
22
+ export declare function buildDirectoryPickerCandidates(platform: NodeJS.Platform, title: string, defaultDirectory: string): PickerCommand[];
23
+ /** 执行单次原生目录选择;命令不存在时返回 unavailable。 */
24
+ export declare function runDirectoryPickerCommand(candidate: PickerCommand): DirectoryPickerResult;
25
+ /** 跨平台系统文件夹选择器(zenity / kdialog / osascript / PowerShell)。 */
26
+ export declare function pickDirectoryDialog(title: string, defaultDirectory: string): DirectoryPickerResult;
27
+ //# sourceMappingURL=directory-picker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"directory-picker.d.ts","sourceRoot":"","sources":["../src/directory-picker.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,qBAAqB,GAC7B;IAAE,MAAM,EAAE,UAAU,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACpC;IAAE,MAAM,EAAE,WAAW,CAAA;CAAE,GACvB;IAAE,MAAM,EAAE,aAAa,CAAA;CAAE,CAAC;AAE9B,MAAM,MAAM,aAAa,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC;AAEhE,2BAA2B;AAC3B,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAElE;AAED,4BAA4B;AAC5B,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE7D;AAED,mCAAmC;AACnC,wBAAgB,qBAAqB,CAAC,gBAAgB,EAAE,MAAM,GAAG,MAAM,CAMtE;AAED,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,GAAG,MAAM,CASxF;AAED,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,GAAG,MAAM,CAWtF;AAED,uCAAuC;AACvC,wBAAgB,8BAA8B,CAC5C,QAAQ,EAAE,MAAM,CAAC,QAAQ,EACzB,KAAK,EAAE,MAAM,EACb,gBAAgB,EAAE,MAAM,GACvB,aAAa,EAAE,CA8BjB;AAYD,uCAAuC;AACvC,wBAAgB,yBAAyB,CAAC,SAAS,EAAE,aAAa,GAAG,qBAAqB,CAgBzF;AAED,8DAA8D;AAC9D,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,GAAG,qBAAqB,CAUlG"}
@@ -0,0 +1,112 @@
1
+ import { execFileSync } from "node:child_process";
2
+ import fs from "node:fs";
3
+ import path from "node:path";
4
+ function escapePowerShellSingleQuoted(value) {
5
+ return value.replace(/'/g, "''");
6
+ }
7
+ function escapeAppleScriptString(value) {
8
+ return value.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
9
+ }
10
+ function resolvePickerStartDir(defaultDirectory) {
11
+ const resolved = path.resolve(defaultDirectory);
12
+ if (fs.existsSync(resolved) && fs.statSync(resolved).isDirectory()) return resolved;
13
+ const parent = path.dirname(resolved);
14
+ if (fs.existsSync(parent) && fs.statSync(parent).isDirectory()) return parent;
15
+ return process.cwd();
16
+ }
17
+ function buildWindowsPickerScript(title, defaultDirectory) {
18
+ const escape = escapePowerShellSingleQuoted;
19
+ return [
20
+ "Add-Type -AssemblyName System.Windows.Forms",
21
+ "$dialog = New-Object System.Windows.Forms.FolderBrowserDialog",
22
+ `$dialog.Description = '${escape(title)}'`,
23
+ `$dialog.SelectedPath = '${escape(defaultDirectory)}'`,
24
+ "if ($dialog.ShowDialog() -eq [System.Windows.Forms.DialogResult]::OK) { Write-Output $dialog.SelectedPath }"
25
+ ].join("; ");
26
+ }
27
+ function buildMacOsPickerScript(title, defaultDirectory) {
28
+ const escTitle = escapeAppleScriptString(title);
29
+ const escPath = escapeAppleScriptString(defaultDirectory.replace(/\\/g, "/"));
30
+ return [
31
+ `set defaultFolder to POSIX file "${escPath}"`,
32
+ "try",
33
+ ` POSIX path of (choose folder with prompt "${escTitle}" default location defaultFolder)`,
34
+ "on error number -128",
35
+ ' error "User cancelled"',
36
+ "end try"
37
+ ].join("\n");
38
+ }
39
+ function buildDirectoryPickerCandidates(platform, title, defaultDirectory) {
40
+ const startDir = resolvePickerStartDir(defaultDirectory);
41
+ if (platform === "win32") {
42
+ const script = buildWindowsPickerScript(title, startDir);
43
+ return [
44
+ { command: "powershell.exe", args: ["-NoProfile", "-STA", "-Command", script] },
45
+ { command: "pwsh", args: ["-NoProfile", "-STA", "-Command", script] }
46
+ ];
47
+ }
48
+ if (platform === "darwin") {
49
+ return [{ command: "osascript", args: ["-e", buildMacOsPickerScript(title, startDir)] }];
50
+ }
51
+ if (platform === "linux") {
52
+ const desktop = process.env.XDG_CURRENT_DESKTOP ?? "";
53
+ const kdeFirst = /KDE/i.test(desktop);
54
+ const zenity = {
55
+ command: "zenity",
56
+ args: ["--file-selection", "--directory", `--title=${title}`, `--filename=${startDir}/`]
57
+ };
58
+ const kdialog = {
59
+ command: "kdialog",
60
+ args: ["--getexistingdirectory", startDir, "--title", title]
61
+ };
62
+ return kdeFirst ? [kdialog, zenity] : [zenity, kdialog];
63
+ }
64
+ return [];
65
+ }
66
+ function isPickerCancelled(error) {
67
+ if (!error || typeof error !== "object") return false;
68
+ const err = error;
69
+ if (err.status === 1) return true;
70
+ const stderr = typeof err.stderr === "string" ? err.stderr : err.stderr?.toString("utf-8") ?? "";
71
+ if (/cancelled|-128|User cancelled/i.test(stderr)) return true;
72
+ const message = err.message ?? "";
73
+ return /cancelled|-128/i.test(message);
74
+ }
75
+ function runDirectoryPickerCommand(candidate) {
76
+ try {
77
+ const output = execFileSync(candidate.command, candidate.args, {
78
+ encoding: "utf-8",
79
+ windowsHide: true,
80
+ stdio: ["ignore", "pipe", "pipe"]
81
+ });
82
+ const trimmed = output.trim();
83
+ if (!trimmed) return { status: "cancelled" };
84
+ return { status: "selected", path: trimmed };
85
+ } catch (error) {
86
+ const err = error;
87
+ if (err.code === "ENOENT") return { status: "unavailable" };
88
+ if (isPickerCancelled(error)) return { status: "cancelled" };
89
+ return { status: "unavailable" };
90
+ }
91
+ }
92
+ function pickDirectoryDialog(title, defaultDirectory) {
93
+ const candidates = buildDirectoryPickerCandidates(process.platform, title, defaultDirectory);
94
+ if (candidates.length === 0) return { status: "unavailable" };
95
+ for (const candidate of candidates) {
96
+ const result = runDirectoryPickerCommand(candidate);
97
+ if (result.status === "unavailable") continue;
98
+ return result;
99
+ }
100
+ return { status: "unavailable" };
101
+ }
102
+ export {
103
+ buildDirectoryPickerCandidates,
104
+ buildMacOsPickerScript,
105
+ buildWindowsPickerScript,
106
+ escapeAppleScriptString,
107
+ escapePowerShellSingleQuoted,
108
+ pickDirectoryDialog,
109
+ resolvePickerStartDir,
110
+ runDirectoryPickerCommand
111
+ };
112
+ //# sourceMappingURL=directory-picker.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/directory-picker.ts"],
4
+ "sourcesContent": ["import { execFileSync } from \"node:child_process\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\n\nexport type DirectoryPickerResult =\n | { status: \"selected\"; path: string }\n | { status: \"cancelled\" }\n | { status: \"unavailable\" };\n\nexport type PickerCommand = { command: string; args: string[] };\n\n/** PowerShell \u5355\u5F15\u53F7\u5B57\u7B26\u4E32\u8F6C\u4E49\u3002 */\nexport function escapePowerShellSingleQuoted(value: string): string {\n return value.replace(/'/g, \"''\");\n}\n\n/** AppleScript \u53CC\u5F15\u53F7\u5B57\u7B26\u4E32\u8F6C\u4E49\u3002 */\nexport function escapeAppleScriptString(value: string): string {\n return value.replace(/\\\\/g, \"\\\\\\\\\").replace(/\"/g, '\\\\\"');\n}\n\n/** \u9009\u62E9\u5668\u8D77\u59CB\u76EE\u5F55\uFF1A\u9ED8\u8BA4\u8DEF\u5F84\u4E0D\u5B58\u5728\u65F6\u56DE\u9000\u5230\u7236\u76EE\u5F55\u6216 cwd\u3002 */\nexport function resolvePickerStartDir(defaultDirectory: string): string {\n const resolved = path.resolve(defaultDirectory);\n if (fs.existsSync(resolved) && fs.statSync(resolved).isDirectory()) return resolved;\n const parent = path.dirname(resolved);\n if (fs.existsSync(parent) && fs.statSync(parent).isDirectory()) return parent;\n return process.cwd();\n}\n\nexport function buildWindowsPickerScript(title: string, defaultDirectory: string): string {\n const escape = escapePowerShellSingleQuoted;\n return [\n \"Add-Type -AssemblyName System.Windows.Forms\",\n \"$dialog = New-Object System.Windows.Forms.FolderBrowserDialog\",\n `$dialog.Description = '${escape(title)}'`,\n `$dialog.SelectedPath = '${escape(defaultDirectory)}'`,\n \"if ($dialog.ShowDialog() -eq [System.Windows.Forms.DialogResult]::OK) { Write-Output $dialog.SelectedPath }\",\n ].join(\"; \");\n}\n\nexport function buildMacOsPickerScript(title: string, defaultDirectory: string): string {\n const escTitle = escapeAppleScriptString(title);\n const escPath = escapeAppleScriptString(defaultDirectory.replace(/\\\\/g, \"/\"));\n return [\n `set defaultFolder to POSIX file \"${escPath}\"`,\n \"try\",\n ` POSIX path of (choose folder with prompt \"${escTitle}\" default location defaultFolder)`,\n \"on error number -128\",\n ' error \"User cancelled\"',\n \"end try\",\n ].join(\"\\n\");\n}\n\n/** \u6309\u5E73\u53F0\u751F\u6210\u539F\u751F\u76EE\u5F55\u9009\u62E9\u5668\u547D\u4EE4\u5019\u9009\uFF08\u5148\u8BD5\u684C\u9762\u9ED8\u8BA4\uFF0C\u518D\u8BD5\u901A\u7528\u5DE5\u5177\uFF09\u3002 */\nexport function buildDirectoryPickerCandidates(\n platform: NodeJS.Platform,\n title: string,\n defaultDirectory: string\n): PickerCommand[] {\n const startDir = resolvePickerStartDir(defaultDirectory);\n\n if (platform === \"win32\") {\n const script = buildWindowsPickerScript(title, startDir);\n return [\n { command: \"powershell.exe\", args: [\"-NoProfile\", \"-STA\", \"-Command\", script] },\n { command: \"pwsh\", args: [\"-NoProfile\", \"-STA\", \"-Command\", script] },\n ];\n }\n\n if (platform === \"darwin\") {\n return [{ command: \"osascript\", args: [\"-e\", buildMacOsPickerScript(title, startDir)] }];\n }\n\n if (platform === \"linux\") {\n const desktop = process.env.XDG_CURRENT_DESKTOP ?? \"\";\n const kdeFirst = /KDE/i.test(desktop);\n const zenity: PickerCommand = {\n command: \"zenity\",\n args: [\"--file-selection\", \"--directory\", `--title=${title}`, `--filename=${startDir}/`],\n };\n const kdialog: PickerCommand = {\n command: \"kdialog\",\n args: [\"--getexistingdirectory\", startDir, \"--title\", title],\n };\n return kdeFirst ? [kdialog, zenity] : [zenity, kdialog];\n }\n\n return [];\n}\n\nfunction isPickerCancelled(error: unknown): boolean {\n if (!error || typeof error !== \"object\") return false;\n const err = error as NodeJS.ErrnoException & { status?: number | null; stderr?: Buffer | string };\n if (err.status === 1) return true;\n const stderr = typeof err.stderr === \"string\" ? err.stderr : err.stderr?.toString(\"utf-8\") ?? \"\";\n if (/cancelled|-128|User cancelled/i.test(stderr)) return true;\n const message = err.message ?? \"\";\n return /cancelled|-128/i.test(message);\n}\n\n/** \u6267\u884C\u5355\u6B21\u539F\u751F\u76EE\u5F55\u9009\u62E9\uFF1B\u547D\u4EE4\u4E0D\u5B58\u5728\u65F6\u8FD4\u56DE unavailable\u3002 */\nexport function runDirectoryPickerCommand(candidate: PickerCommand): DirectoryPickerResult {\n try {\n const output = execFileSync(candidate.command, candidate.args, {\n encoding: \"utf-8\",\n windowsHide: true,\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n });\n const trimmed = output.trim();\n if (!trimmed) return { status: \"cancelled\" };\n return { status: \"selected\", path: trimmed };\n } catch (error) {\n const err = error as NodeJS.ErrnoException;\n if (err.code === \"ENOENT\") return { status: \"unavailable\" };\n if (isPickerCancelled(error)) return { status: \"cancelled\" };\n return { status: \"unavailable\" };\n }\n}\n\n/** \u8DE8\u5E73\u53F0\u7CFB\u7EDF\u6587\u4EF6\u5939\u9009\u62E9\u5668\uFF08zenity / kdialog / osascript / PowerShell\uFF09\u3002 */\nexport function pickDirectoryDialog(title: string, defaultDirectory: string): DirectoryPickerResult {\n const candidates = buildDirectoryPickerCandidates(process.platform, title, defaultDirectory);\n if (candidates.length === 0) return { status: \"unavailable\" };\n\n for (const candidate of candidates) {\n const result = runDirectoryPickerCommand(candidate);\n if (result.status === \"unavailable\") continue;\n return result;\n }\n return { status: \"unavailable\" };\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }