@sfmc-bds/cli 0.2.0-beta.8 → 0.2.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.
- package/LICENSE +663 -0
- package/README.md +4 -5
- package/dist/bds-runtime-version.d.ts +3 -0
- package/dist/bds-runtime-version.d.ts.map +1 -0
- package/dist/bds-runtime-version.js +15 -0
- package/dist/bds-runtime-version.js.map +7 -0
- package/dist/command-surface.js +3 -3
- package/dist/command-surface.js.map +2 -2
- package/dist/commands.d.ts +57 -4
- package/dist/commands.d.ts.map +1 -1
- package/dist/commands.js +184 -68
- package/dist/commands.js.map +2 -2
- package/dist/directory-picker.d.ts +27 -0
- package/dist/directory-picker.d.ts.map +1 -0
- package/dist/directory-picker.js +112 -0
- package/dist/directory-picker.js.map +7 -0
- package/dist/help-text.d.ts.map +1 -1
- package/dist/help-text.js +1 -5
- package/dist/help-text.js.map +2 -2
- package/dist/i18n/locales/en.d.ts +49 -14
- package/dist/i18n/locales/en.d.ts.map +1 -1
- package/dist/i18n/locales/en.js +49 -15
- package/dist/i18n/locales/en.js.map +2 -2
- package/dist/i18n/locales/zh-CN.d.ts.map +1 -1
- package/dist/i18n/locales/zh-CN.js +50 -16
- package/dist/i18n/locales/zh-CN.js.map +2 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +2 -2
- package/dist/interactive-prompts.d.ts +1 -2
- package/dist/interactive-prompts.d.ts.map +1 -1
- package/dist/interactive-prompts.js +12 -23
- package/dist/interactive-prompts.js.map +3 -3
- package/dist/llbot-launch.d.ts +20 -0
- package/dist/llbot-launch.d.ts.map +1 -0
- package/dist/llbot-launch.js +40 -0
- package/dist/llbot-launch.js.map +7 -0
- package/dist/log-filter.d.ts +18 -2
- package/dist/log-filter.d.ts.map +1 -1
- package/dist/log-filter.js +54 -4
- package/dist/log-filter.js.map +2 -2
- package/dist/log-translator.d.ts +36 -0
- package/dist/log-translator.d.ts.map +1 -0
- package/dist/log-translator.js +279 -0
- package/dist/log-translator.js.map +7 -0
- package/dist/logs.d.ts +2 -0
- package/dist/logs.d.ts.map +1 -1
- package/dist/logs.js +24 -11
- package/dist/logs.js.map +2 -2
- package/dist/main.js +9 -6
- package/dist/main.js.map +2 -2
- package/dist/module-commands.d.ts.map +1 -1
- package/dist/module-commands.js +22 -8
- package/dist/module-commands.js.map +2 -2
- package/dist/module-fingerprint.d.ts.map +1 -1
- package/dist/module-fingerprint.js +1 -0
- package/dist/module-fingerprint.js.map +2 -2
- package/dist/module-pack-build.d.ts +14 -4
- package/dist/module-pack-build.d.ts.map +1 -1
- package/dist/module-pack-build.js +81 -108
- package/dist/module-pack-build.js.map +2 -2
- package/dist/module-toggle.d.ts +1 -1
- package/dist/module-toggle.d.ts.map +1 -1
- package/dist/module-toggle.js.map +1 -1
- package/dist/node-service-probe.d.ts +18 -0
- package/dist/node-service-probe.d.ts.map +1 -0
- package/dist/node-service-probe.js +97 -0
- package/dist/node-service-probe.js.map +7 -0
- package/dist/pack-lifecycle.d.ts +15 -1
- package/dist/pack-lifecycle.d.ts.map +1 -1
- package/dist/pack-lifecycle.js +249 -16
- package/dist/pack-lifecycle.js.map +2 -2
- package/dist/player-session.d.ts +13 -0
- package/dist/player-session.d.ts.map +1 -0
- package/dist/player-session.js +26 -0
- package/dist/player-session.js.map +7 -0
- package/dist/registry.d.ts +1 -1
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js +4 -1
- package/dist/registry.js.map +2 -2
- package/dist/repl-windows/format-display.d.ts.map +1 -1
- package/dist/repl-windows/format-display.js +5 -1
- package/dist/repl-windows/format-display.js.map +2 -2
- package/dist/repl-windows/host.d.ts +6 -3
- package/dist/repl-windows/host.d.ts.map +1 -1
- package/dist/repl-windows/host.js +12 -6
- package/dist/repl-windows/host.js.map +2 -2
- package/dist/repl-windows/index.d.ts +1 -0
- package/dist/repl-windows/index.d.ts.map +1 -1
- package/dist/repl-windows/index.js +3 -0
- package/dist/repl-windows/index.js.map +2 -2
- package/dist/repl-windows/service-window.d.ts +1 -1
- package/dist/repl-windows/service-window.d.ts.map +1 -1
- package/dist/repl-windows/service-window.js +9 -1
- package/dist/repl-windows/service-window.js.map +2 -2
- package/dist/repl-windows/sfmc-window.d.ts +7 -0
- package/dist/repl-windows/sfmc-window.d.ts.map +1 -0
- package/dist/repl-windows/sfmc-window.js +28 -0
- package/dist/repl-windows/sfmc-window.js.map +7 -0
- package/dist/repl.d.ts.map +1 -1
- package/dist/repl.js +37 -22
- package/dist/repl.js.map +2 -2
- package/dist/runtime.d.ts +2 -2
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +15 -2
- package/dist/runtime.js.map +2 -2
- package/dist/send-target.d.ts +2 -0
- package/dist/send-target.d.ts.map +1 -1
- package/dist/send-target.js +12 -2
- package/dist/send-target.js.map +2 -2
- package/dist/services.d.ts +58 -5
- package/dist/services.d.ts.map +1 -1
- package/dist/services.js +273 -50
- package/dist/services.js.map +2 -2
- package/dist/sfmc-modules-root.d.ts.map +1 -1
- package/dist/sfmc-modules-root.js +6 -2
- package/dist/sfmc-modules-root.js.map +2 -2
- package/dist/ui-command.d.ts +6 -0
- package/dist/ui-command.d.ts.map +1 -0
- package/dist/ui-command.js +68 -0
- package/dist/ui-command.js.map +7 -0
- package/dist/wizard.d.ts.map +1 -1
- package/dist/wizard.js +95 -32
- package/dist/wizard.js.map +2 -2
- package/dist/world-packs.d.ts +2 -0
- package/dist/world-packs.d.ts.map +1 -1
- package/dist/world-packs.js +161 -18
- package/dist/world-packs.js.map +2 -2
- package/package.json +21 -15
- package/scripts/module-install/check-modules.mjs +178 -0
- package/scripts/module-install/fetch-module.mjs +1083 -0
- package/scripts/module-install/lib/catalog.mjs +96 -0
- package/scripts/module-install/lib/config-seeding.mjs +128 -0
- package/scripts/module-install/lib/io.mjs +37 -0
- package/scripts/module-install/lib/link-from.mjs +80 -0
- package/scripts/module-install/lib/lock.mjs +78 -0
- package/scripts/module-install/lib/npm-resolver.mjs +55 -0
- package/scripts/module-install/lib/packages.mjs +136 -0
- package/scripts/module-install/lib/paths.mjs +48 -0
- package/scripts/module-install/lib/registry-index.mjs +50 -0
- package/dist/cmd-remote.d.ts +0 -13
- package/dist/cmd-remote.d.ts.map +0 -1
- package/dist/cmd-remote.js +0 -38
- package/dist/cmd-remote.js.map +0 -7
- package/dist/remote-agent.d.ts +0 -18
- package/dist/remote-agent.d.ts.map +0 -1
- package/dist/remote-agent.js +0 -198
- package/dist/remote-agent.js.map +0 -7
package/README.md
CHANGED
|
@@ -5,18 +5,17 @@ SFMC 管理 CLI:REPL、服务启停、模块安装、行为包 build/deploy。
|
|
|
5
5
|
## 安装
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
npx @sfmc-bds/cli status
|
|
8
|
+
pnpm add -g @sfmc-bds/cli
|
|
9
|
+
pnpm dlx @sfmc-bds/cli status
|
|
11
10
|
```
|
|
12
11
|
|
|
13
12
|
服主推荐:
|
|
14
13
|
|
|
15
14
|
```bash
|
|
16
|
-
|
|
15
|
+
pnpm add -g @sfmc-bds/sfmc
|
|
17
16
|
```
|
|
18
17
|
|
|
19
|
-
仅 CLI
|
|
18
|
+
仅 CLI(不含后端服务)可用 `pnpm add -g @sfmc-bds/cli`,完整平台请装聚合包。
|
|
20
19
|
|
|
21
20
|
## 依赖
|
|
22
21
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bds-runtime-version.d.ts","sourceRoot":"","sources":["../src/bds-runtime-version.ts"],"names":[],"mappings":"AAGA,sCAAsC;AACtC,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CASjG"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { stateDir, writeJson } from "@sfmc-bds/sdk/node/config";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
function recordBdsVersion(root, line, pid, startedAt) {
|
|
4
|
+
if (!pid || Date.now() - startedAt > 6e4) return;
|
|
5
|
+
const match = /^(?:\[(?!Scripting\b)[^\]\r\n]*\]\s*)?Version:\s*(\d+\.\d+\.\d+(?:\.\d+)?)(?:\s|$)/.exec(line.trim());
|
|
6
|
+
if (!match) return;
|
|
7
|
+
try {
|
|
8
|
+
writeJson(path.join(stateDir(root), "bds-runtime-version.json"), { pid, startedAt, version: match[1] });
|
|
9
|
+
} catch {
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
export {
|
|
13
|
+
recordBdsVersion
|
|
14
|
+
};
|
|
15
|
+
//# sourceMappingURL=bds-runtime-version.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/bds-runtime-version.ts"],
|
|
4
|
+
"sourcesContent": ["import { stateDir, writeJson } from \"@sfmc-bds/sdk/node/config\";\nimport path from \"node:path\";\n\n/** \u4EC5\u63A5\u53D7 BDS \u542F\u52A8\u9636\u6BB5\u7248\u672C\u884C\uFF0C\u907F\u514D\u666E\u901A\u6E38\u620F\u65E5\u5FD7\u88AB\u8BEF\u5F53\u4F5C\u7248\u672C\u3002 */\nexport function recordBdsVersion(root: string, line: string, pid: number, startedAt: number): void {\n if (!pid || Date.now() - startedAt > 60_000) return;\n const match = /^(?:\\[(?!Scripting\\b)[^\\]\\r\\n]*\\]\\s*)?Version:\\s*(\\d+\\.\\d+\\.\\d+(?:\\.\\d+)?)(?:\\s|$)/.exec(line.trim());\n if (!match) return;\n try {\n writeJson(path.join(stateDir(root), \"bds-runtime-version.json\"), { pid, startedAt, version: match[1] });\n } catch {\n /* \u7248\u672C\u91C7\u96C6\u5931\u8D25\u4E0D\u5F71\u54CD\u670D\u52A1\u8FDB\u7A0B\u3002 */\n }\n}\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,UAAU,iBAAiB;AACpC,OAAO,UAAU;AAGV,SAAS,iBAAiB,MAAc,MAAc,KAAa,WAAyB;AACjG,MAAI,CAAC,OAAO,KAAK,IAAI,IAAI,YAAY,IAAQ;AAC7C,QAAM,QAAQ,qFAAqF,KAAK,KAAK,KAAK,CAAC;AACnH,MAAI,CAAC,MAAO;AACZ,MAAI;AACF,cAAU,KAAK,KAAK,SAAS,IAAI,GAAG,0BAA0B,GAAG,EAAE,KAAK,WAAW,SAAS,MAAM,CAAC,EAAE,CAAC;AAAA,EACxG,QAAQ;AAAA,EAER;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
package/dist/command-surface.js
CHANGED
|
@@ -94,8 +94,8 @@ const TOP_DESC = {
|
|
|
94
94
|
init: "help.init",
|
|
95
95
|
update: "help.update",
|
|
96
96
|
locale: "help.locale",
|
|
97
|
-
remote: "help.remote.status",
|
|
98
97
|
debug: "help.debug.status",
|
|
98
|
+
ui: "help.ui",
|
|
99
99
|
install: "help.module.install",
|
|
100
100
|
uninstall: "help.module.uninstall",
|
|
101
101
|
search: "help.module.search",
|
|
@@ -151,7 +151,7 @@ function moduleChildNodes(mode) {
|
|
|
151
151
|
});
|
|
152
152
|
}
|
|
153
153
|
function packsChildNodes(mode) {
|
|
154
|
-
const noArg = /* @__PURE__ */ new Set(["list", "
|
|
154
|
+
const noArg = /* @__PURE__ */ new Set(["list", "path", "sources"]);
|
|
155
155
|
return listVisiblePacksSubs(mode).map((sub) => ({
|
|
156
156
|
label: sub,
|
|
157
157
|
token: sub,
|
|
@@ -230,8 +230,8 @@ const COMMAND_SPECS = [
|
|
|
230
230
|
{ id: "init", name: "init", channel: "both", needsTty: true },
|
|
231
231
|
{ id: "update", name: "update", channel: "both" },
|
|
232
232
|
{ id: "locale", name: "locale", channel: "both" },
|
|
233
|
-
{ id: "remote", name: "remote", channel: "both" },
|
|
234
233
|
{ id: "debug", name: "debug", channel: "both", accent: "dev" },
|
|
234
|
+
{ id: "ui", name: "ui", channel: "both", accent: "dev" },
|
|
235
235
|
/** 顶层扁平短命令 → module.*(少写一层 module) */
|
|
236
236
|
{ id: "install", name: "install", channel: "both" },
|
|
237
237
|
{ id: "uninstall", name: "uninstall", channel: "both", aliases: ["remove"] },
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/command-surface.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * command-surface.ts \u2014 sfmc CLI \u547D\u4EE4\u901A\u9053\u6CE8\u518C\u8868\uFF08\u5355\u4E00\u6743\u5A01\uFF09\n *\n * channel:\n * - both: argv\uFF08`sfmc <cmd>`\uFF09\u4E0E REPL \u5747\u53EF\u7528\uFF08\u9ED8\u8BA4\uFF09\n * - repl: \u4EC5 REPL\uFF1Bargv \u62D2\u7EDD\uFF08\u5982 send / quit\uFF09\n *\n * accent: \"dev\" \u4EC5\u5F71\u54CD\u5E2E\u52A9/\u8865\u5168\u84DD\u8272\u6837\u5F0F\uFF0C\u4E0D\u53C2\u4E0E canRun\uFF08OCP/DRY\uFF09\u3002\n * \u4E1A\u52A1\u5B9E\u73B0\u4E0D\u5728\u672C\u6587\u4EF6 / \u9762\u677F\u5185\uFF1A\u5206\u53D1\u5230 commands\u3001module-commands\u3001world-packs \u7B49\u3002\n */\nimport { stdin } from \"node:process\";\n\nexport type CommandChannel = \"repl\" | \"both\";\nexport type CommandMode = \"argv\" | \"repl\";\nexport type CommandAccent = \"dev\";\n\nexport type CommandSpec = {\n /** \u7A33\u5B9A id\uFF0C\u5982 \"module.install\" / \"send\" / \"debug\" */\n id: string;\n /** \u9876\u5C42\u547D\u4EE4\u540D\uFF08module \u5B50\u547D\u4EE4\u7528 \"module\"\uFF1B\u9876\u5C42\u522B\u540D\u89C1 TOP_LEVEL_ALIASES\uFF09 */\n name: string;\n /** \u5B50\u547D\u4EE4\uFF08\u4EC5 module/packs \u7B49\uFF09 */\n sub?: string;\n channel: CommandChannel;\n needsTty?: boolean;\n /** \u5E2E\u52A9\u67D3\u8272\uFF1B\u4E0D\u53C2\u4E0E canRun */\n accent?: CommandAccent;\n /** \u5B50\u547D\u4EE4\u540C\u4E49\u522B\u540D\uFF08\u5982 uninstall \u2192 remove\uFF09\uFF0C\u4E0D\u662F\u9876\u5C42\u522B\u540D */\n aliases?: string[];\n};\n\nexport type CanRunContext = {\n mode: CommandMode;\n isTty: boolean;\n};\n\nexport type CanRunFailReason = \"replOnly\" | \"needTty\";\n\nexport type CanRunResult = { ok: true } | { ok: false; reason: CanRunFailReason };\n\n/** \u9876\u5C42\u547D\u4EE4\u522B\u540D \u2192 \u89C4\u8303 name\uFF08DRY\uFF1A\u52FF\u5728\u5404 sub spec \u91CD\u590D\u5199 mod/addon\uFF09 */\nexport const TOP_LEVEL_ALIASES: Readonly<Record<string, string>> = {\n mod: \"module\",\n addon: \"packs\",\n log: \"logs\",\n lang: \"locale\",\n h: \"help\",\n \"?\": \"help\",\n exit: \"quit\",\n q: \"quit\",\n i: \"install\",\n remove: \"uninstall\",\n};\n\n/**\n * \u9876\u5C42\u6241\u5E73\u77ED\u547D\u4EE4 \u2192 module \u5B50\u547D\u4EE4\uFF08argv / REPL \u5171\u7528\uFF0C\u907F\u514D\u5728 switch \u91CC\u6563\u843D\u6620\u5C04\uFF09\n * \u4E0D\u542B enable/disable\uFF08\u4E0E packs \u51B2\u7A81\uFF0C\u4ECD\u8D70 /module \u6216 /packs\uFF09\n *\n * \u4E0E packs \u5B50\u547D\u4EE4\u5BF9\u9F50\uFF1A`packs i` \u2192 `packs install`\uFF08mapPacksSubAlias\uFF09\uFF1B\n * module \u9876\u5C42\u540C\u6837\u652F\u6301 `i` \u2192 `install`\uFF08\u89C1 TOP_LEVEL_ALIASES \u4E0E\u672C\u8868\uFF09\u3002\n */\nexport const MODULE_TOP_SHORTHAND: Readonly<Record<string, string>> = {\n i: \"install\",\n install: \"install\",\n uninstall: \"uninstall\",\n search: \"search\",\n verify: \"verify\",\n};\n\nexport function resolveModuleTopShorthand(cmd: string | undefined): string | undefined {\n if (!cmd) return undefined;\n const name = resolveTopLevelName(cmd);\n if (!name) return undefined;\n return MODULE_TOP_SHORTHAND[name];\n}\n\nexport function resolveTopLevelName(cmd: string | undefined): string | undefined {\n if (!cmd) return undefined;\n return TOP_LEVEL_ALIASES[cmd] ?? cmd;\n}\n\nfunction channelAllows(channel: CommandChannel, mode: CommandMode): boolean {\n if (channel === \"both\") return true;\n return mode === \"repl\";\n}\n\n/** \u5224\u5B9A\u5F53\u524D\u6A21\u5F0F\u4E0B\u80FD\u5426\u6267\u884C\u8BE5\u547D\u4EE4\uFF08accent \u4E0D\u53C2\u4E0E\uFF09\u3002 */\nexport function canRunCommand(spec: CommandSpec, ctx: CanRunContext): CanRunResult {\n if (!channelAllows(spec.channel, ctx.mode)) {\n return { ok: false, reason: \"replOnly\" };\n }\n if (spec.needsTty && !ctx.isTty) {\n return { ok: false, reason: \"needTty\" };\n }\n return { ok: true };\n}\n\n/** \u5F53\u524D\u6A21\u5F0F\u53EF\u89C1\u547D\u4EE4\uFF08help / Tab\uFF09\u3002 */\nexport function listVisibleCommands(mode: CommandMode): CommandSpec[] {\n return COMMAND_SPECS.filter((s) => channelAllows(s.channel, mode));\n}\n\n/** \u9876\u5C42\u547D\u4EE4\u540D\uFF08\u542B\u522B\u540D\uFF09\uFF0C\u4F9B REPL COMMANDS / \u8865\u5168\u3002 */\nexport function listVisibleTopLevelNames(mode: CommandMode): string[] {\n const canonical = new Set<string>();\n for (const s of listVisibleCommands(mode)) {\n canonical.add(s.name);\n }\n const out = new Set<string>(canonical);\n for (const [alias, name] of Object.entries(TOP_LEVEL_ALIASES)) {\n if (canonical.has(name)) out.add(alias);\n }\n return [...out];\n}\n\n/** \u67E5\u627E\u9876\u5C42\u547D\u4EE4\uFF08\u65E0 sub\uFF09\u7684\u4EFB\u610F\u4E00\u6761\u540C\u540D spec\uFF08\u7528\u4E8E channel \u95E8\u7981\uFF09\u3002 */\nexport function findTopLevelSpec(cmd: string | undefined): CommandSpec | undefined {\n const name = resolveTopLevelName(cmd);\n if (!name) return undefined;\n /* \u4F18\u5148\u65E0 sub \u7684\u9876\u5C42\u6761\u76EE\uFF1B\u5426\u5219\u53D6\u8BE5 name \u4E0B\u4EFB\u610F\u53EF\u89C1 spec \u4EE3\u8868\u901A\u9053\uFF08module/packs\uFF09 */\n const top = COMMAND_SPECS.find((s) => !s.sub && s.name === name);\n if (top) return top;\n return COMMAND_SPECS.find((s) => s.name === name);\n}\n\n/** \u67E5\u627E module \u5B50\u547D\u4EE4 spec\u3002 */\nexport function findModuleSubSpec(sub: string | undefined): CommandSpec | undefined {\n if (!sub) return undefined;\n return COMMAND_SPECS.find(\n (s) => s.name === \"module\" && (s.sub === sub || (s.aliases ?? []).includes(sub))\n );\n}\n\n/** \u67E5\u627E packs \u5B50\u547D\u4EE4 spec\u3002 */\nexport function findPacksSubSpec(sub: string | undefined): CommandSpec | undefined {\n if (!sub) return undefined;\n return COMMAND_SPECS.find(\n (s) => s.name === \"packs\" && (s.sub === sub || (s.aliases ?? []).includes(sub))\n );\n}\n\n/** \u5F53\u524D mode \u4E0B\u53EF\u89C1\u7684 module \u5B50\u547D\u4EE4\u540D\uFF08\u89C4\u8303\u540D\uFF0C\u4E0D\u542B remove \u522B\u540D\uFF09\u3002 */\nexport function listVisibleModuleSubs(mode: CommandMode): string[] {\n return listVisibleCommands(mode)\n .filter((s) => s.name === \"module\" && s.sub)\n .map((s) => s.sub!);\n}\n\n/** \u5F53\u524D mode \u4E0B\u53EF\u89C1\u7684 packs \u5B50\u547D\u4EE4\u540D\u3002 */\nexport function listVisiblePacksSubs(mode: CommandMode): string[] {\n return listVisibleCommands(mode)\n .filter((s) => s.name === \"packs\" && s.sub)\n .map((s) => s.sub!);\n}\n\n/** REPL \u5FEB\u901F\u8865\u5168\uFF1A\u5C42\u7EA7\u8282\u70B9\uFF08\u4E3B\u9762\u677F \u2192 \u53F3\u4FA7\u5B50\u9762\u677F\uFF09 */\nexport type PaletteNode = {\n /** \u9762\u677F\u5185\u663E\u793A\u7684\u6807\u7B7E */\n label: string;\n /** \u8FFD\u52A0\u5230\u547D\u4EE4\u884C\u7684 token\uFF08\u6839\u8282\u70B9\u542B\u6216\u4E0D\u542B\u524D\u5BFC\u903B\u8F91\u7531\u7EC4\u88C5\u8D1F\u8D23\uFF09 */\n token: string;\n /** i18n \u63CF\u8FF0\u952E */\n descKey?: string;\n accent?: CommandAccent;\n /** \u56FA\u5B9A\u4E0B\u4E00\u53C2\u9009\u9879\uFF1B\u56DE\u8F66\u540E\u5728\u53F3\u4FA7\u5C55\u5F00 */\n children?: PaletteNode[];\n /** \u65E0 children \u65F6\u4ECD\u9700\u81EA\u7531\u8F93\u5165\uFF08\u56DE\u8F66\u540E\u586B\u5165\u7A7A\u683C\u7EE7\u7EED\u6253\u5B57\uFF09 */\n freeArgs?: boolean;\n};\n\nconst NO_ARG_TOP = new Set([\"status\", \"help\", \"version\", \"quit\", \"init\", \"logs\"]);\n\nconst TOP_DESC: Record<string, string> = {\n status: \"help.status\",\n logs: \"help.logs\",\n start: \"help.start\",\n stop: \"help.stop\",\n restart: \"help.restart\",\n send: \"help.send\",\n help: \"help.help\",\n version: \"help.version\",\n quit: \"help.quit\",\n init: \"help.init\",\n update: \"help.update\",\n locale: \"help.locale\",\n remote: \"help.remote.status\",\n debug: \"help.debug.status\",\n install: \"help.module.install\",\n uninstall: \"help.module.uninstall\",\n search: \"help.module.search\",\n verify: \"help.module.verify\",\n};\n\nconst MODULE_DESC: Record<string, string> = {\n list: \"help.module.list\",\n info: \"help.module.info\",\n build: \"help.module.build\",\n reload: \"help.module.reload\",\n search: \"help.module.search\",\n install: \"help.module.install\",\n uninstall: \"help.module.uninstall\",\n verify: \"help.module.verify\",\n enable: \"help.module.toggle\",\n disable: \"help.module.toggle\",\n};\n\nconst PACKS_DESC: Record<string, string> = {\n list: \"help.packs.list\",\n search: \"help.packs.search\",\n enable: \"help.packs.enable\",\n disable: \"help.packs.disable\",\n doctor: \"help.packs.doctor\",\n path: \"help.packs.path\",\n install: \"help.addon\",\n scan: \"help.addon\",\n uninstall: \"help.addon\",\n bind: \"help.addon\",\n unbind: \"help.addon\",\n sources: \"help.addon\",\n check: \"help.addon\",\n update: \"help.addon\",\n bump: \"help.addon\",\n};\n\nfunction serviceArgNodes(): PaletteNode[] {\n return [\n { label: \"-all\", token: \"-all\" },\n ...([\"bds\", \"db\", \"qq\", \"llbot\"] as const).map((n) => ({ label: n, token: n })),\n ];\n}\n\nfunction moduleChildNodes(mode: CommandMode): PaletteNode[] {\n const noArg = new Set([\"list\", \"build\"]);\n return listVisibleModuleSubs(mode).map((sub) => {\n const spec = findModuleSubSpec(sub);\n const node: PaletteNode = {\n label: sub,\n token: sub,\n descKey: MODULE_DESC[sub] ?? \"help.module.list\",\n freeArgs: !noArg.has(sub),\n };\n if (spec?.accent) node.accent = spec.accent;\n return node;\n });\n}\n\nfunction packsChildNodes(mode: CommandMode): PaletteNode[] {\n const noArg = new Set([\"list\", \"doctor\", \"path\", \"sources\"]);\n return listVisiblePacksSubs(mode).map((sub) => ({\n label: sub,\n token: sub,\n descKey: PACKS_DESC[sub] ?? \"help.addon\",\n freeArgs: !noArg.has(sub),\n }));\n}\n\n/** \u5C42\u7EA7\u547D\u4EE4\u6811\uFF08REPL \u9762\u677F\u4E3B\u5217\uFF09 */\nexport function listPaletteRoots(mode: CommandMode = \"repl\"): PaletteNode[] {\n const specs = listVisibleCommands(mode);\n const out: PaletteNode[] = [];\n const seen = new Set<string>();\n /** \u9762\u677F\u4E0D\u5C55\u793A\u9876\u5C42\u77ED\u547D\u4EE4\uFF0C\u7EDF\u4E00\u8D70 /module <sub>\uFF08argv \u77ED\u547D\u4EE4\u4ECD\u53EF\u7528\uFF09 */\n const skipTopShorthand = new Set(Object.keys(MODULE_TOP_SHORTHAND));\n\n for (const s of specs) {\n if (s.sub) continue;\n if (s.name === \"module\" || s.name === \"packs\") continue;\n if (skipTopShorthand.has(s.name)) continue;\n if (seen.has(s.name)) continue;\n seen.add(s.name);\n\n const node: PaletteNode = {\n label: `/${s.name}`,\n token: s.name,\n descKey: TOP_DESC[s.name] ?? \"help.help\",\n };\n if (s.accent) node.accent = s.accent;\n\n if (s.name === \"start\" || s.name === \"stop\" || s.name === \"restart\") {\n node.children = serviceArgNodes();\n } else if (s.name === \"send\") {\n node.children = ([\"bds\", \"db\", \"qq\", \"llbot\"] as const).map((n) => ({\n label: n,\n token: n,\n freeArgs: true,\n }));\n } else if (!NO_ARG_TOP.has(s.name)) {\n node.freeArgs = true;\n }\n\n out.push(node);\n }\n\n const moduleSubs = moduleChildNodes(mode);\n if (moduleSubs.length > 0) {\n out.push({\n label: \"/module\",\n token: \"module\",\n descKey: \"help.module.list\",\n children: moduleSubs,\n });\n }\n\n const packsSubs = packsChildNodes(mode);\n if (packsSubs.length > 0) {\n out.push({\n label: \"/packs\",\n token: \"packs\",\n descKey: \"help.addon\",\n children: packsSubs,\n });\n }\n\n return out;\n}\n\nexport function isDevAccent(spec: CommandSpec | undefined): boolean {\n return spec?.accent === \"dev\";\n}\n\n/** sub \u662F\u5426\u4E3A\u5F00\u53D1\u8005\u6837\u5F0F\u547D\u4EE4\uFF08\u84DD\u6807\uFF09\u3002 */\nexport function isDevAccentModuleSub(sub: string | undefined): boolean {\n return isDevAccent(findModuleSubSpec(sub));\n}\n\n/** stdin TTY \u63A2\u6D4B\uFF08\u4F9B main/repl \u5171\u7528\uFF09\u3002 */\nexport function isCliTty(): boolean {\n return Boolean(stdin.isTTY);\n}\n\n/**\n * \u547D\u4EE4\u6CE8\u518C\u8868 \u2014\u2014 \u65B0\u589E\u547D\u4EE4\u53EA\u52A0\u6B64\u5904\uFF08OCP\uFF09\u3002\n * channel:\n * - both: argv + REPL\uFF08\u9ED8\u8BA4\uFF1B\u9762\u677F\u53EA\u8C03\u5EA6\u65E2\u6709 dispatcher\uFF09\n * - repl: \u4EC5 REPL\uFF08\u5982 send / quit\uFF09\n */\nexport const COMMAND_SPECS: readonly CommandSpec[] = [\n /* \u2500\u2500\u2500 both\uFF1A\u670D\u52A1 / \u6A21\u5757 / \u8D44\u6E90\u5305 / \u914D\u7F6E \u2500\u2500\u2500 */\n { id: \"status\", name: \"status\", channel: \"both\" },\n { id: \"start\", name: \"start\", channel: \"both\" },\n { id: \"stop\", name: \"stop\", channel: \"both\" },\n { id: \"restart\", name: \"restart\", channel: \"both\" },\n { id: \"logs\", name: \"logs\", channel: \"repl\" },\n { id: \"help\", name: \"help\", channel: \"both\" },\n { id: \"version\", name: \"version\", channel: \"both\" },\n { id: \"init\", name: \"init\", channel: \"both\", needsTty: true },\n { id: \"update\", name: \"update\", channel: \"both\" },\n { id: \"locale\", name: \"locale\", channel: \"both\" },\n { id: \"remote\", name: \"remote\", channel: \"both\" },\n { id: \"debug\", name: \"debug\", channel: \"both\", accent: \"dev\" },\n\n /** \u9876\u5C42\u6241\u5E73\u77ED\u547D\u4EE4 \u2192 module.*\uFF08\u5C11\u5199\u4E00\u5C42 module\uFF09 */\n { id: \"install\", name: \"install\", channel: \"both\" },\n { id: \"uninstall\", name: \"uninstall\", channel: \"both\", aliases: [\"remove\"] },\n { id: \"search\", name: \"search\", channel: \"both\" },\n { id: \"verify\", name: \"verify\", channel: \"both\" },\n\n { id: \"module.list\", name: \"module\", sub: \"list\", channel: \"both\" },\n { id: \"module.info\", name: \"module\", sub: \"info\", channel: \"both\" },\n { id: \"module.build\", name: \"module\", sub: \"build\", channel: \"both\", accent: \"dev\" },\n { id: \"module.reload\", name: \"module\", sub: \"reload\", channel: \"both\", accent: \"dev\" },\n { id: \"module.install\", name: \"module\", sub: \"install\", channel: \"both\" },\n {\n id: \"module.uninstall\",\n name: \"module\",\n sub: \"uninstall\",\n channel: \"both\",\n aliases: [\"remove\"],\n },\n { id: \"module.search\", name: \"module\", sub: \"search\", channel: \"both\" },\n { id: \"module.verify\", name: \"module\", sub: \"verify\", channel: \"both\" },\n { id: \"module.enable\", name: \"module\", sub: \"enable\", channel: \"both\" },\n { id: \"module.disable\", name: \"module\", sub: \"disable\", channel: \"both\" },\n\n { id: \"packs.list\", name: \"packs\", sub: \"list\", channel: \"both\" },\n { id: \"packs.search\", name: \"packs\", sub: \"search\", channel: \"both\" },\n { id: \"packs.enable\", name: \"packs\", sub: \"enable\", channel: \"both\" },\n { id: \"packs.disable\", name: \"packs\", sub: \"disable\", channel: \"both\" },\n { id: \"packs.doctor\", name: \"packs\", sub: \"doctor\", channel: \"both\" },\n { id: \"packs.path\", name: \"packs\", sub: \"path\", channel: \"both\" },\n { id: \"packs.install\", name: \"packs\", sub: \"install\", channel: \"both\" },\n { id: \"packs.scan\", name: \"packs\", sub: \"scan\", channel: \"both\" },\n { id: \"packs.uninstall\", name: \"packs\", sub: \"uninstall\", channel: \"both\" },\n { id: \"packs.bind\", name: \"packs\", sub: \"bind\", channel: \"both\" },\n { id: \"packs.unbind\", name: \"packs\", sub: \"unbind\", channel: \"both\" },\n { id: \"packs.sources\", name: \"packs\", sub: \"sources\", channel: \"both\" },\n { id: \"packs.check\", name: \"packs\", sub: \"check\", channel: \"both\" },\n { id: \"packs.update\", name: \"packs\", sub: \"update\", channel: \"both\" },\n { id: \"packs.bump\", name: \"packs\", sub: \"bump\", channel: \"both\" },\n\n /* \u2500\u2500\u2500 repl-only \u2500\u2500\u2500 */\n { id: \"send\", name: \"send\", channel: \"repl\" },\n { id: \"quit\", name: \"quit\", channel: \"repl\" },\n];\n"],
|
|
5
|
-
"mappings": "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
|
|
4
|
+
"sourcesContent": ["/**\n * command-surface.ts \u2014 sfmc CLI \u547D\u4EE4\u901A\u9053\u6CE8\u518C\u8868\uFF08\u5355\u4E00\u6743\u5A01\uFF09\n *\n * channel:\n * - both: argv\uFF08`sfmc <cmd>`\uFF09\u4E0E REPL \u5747\u53EF\u7528\uFF08\u9ED8\u8BA4\uFF09\n * - repl: \u4EC5 REPL\uFF1Bargv \u62D2\u7EDD\uFF08\u5982 send / quit\uFF09\n *\n * accent: \"dev\" \u4EC5\u5F71\u54CD\u5E2E\u52A9/\u8865\u5168\u84DD\u8272\u6837\u5F0F\uFF0C\u4E0D\u53C2\u4E0E canRun\uFF08OCP/DRY\uFF09\u3002\n * \u4E1A\u52A1\u5B9E\u73B0\u4E0D\u5728\u672C\u6587\u4EF6 / \u9762\u677F\u5185\uFF1A\u5206\u53D1\u5230 commands\u3001module-commands\u3001world-packs \u7B49\u3002\n */\nimport { stdin } from \"node:process\";\n\nexport type CommandChannel = \"repl\" | \"both\";\nexport type CommandMode = \"argv\" | \"repl\";\nexport type CommandAccent = \"dev\";\n\nexport type CommandSpec = {\n /** \u7A33\u5B9A id\uFF0C\u5982 \"module.install\" / \"send\" / \"debug\" */\n id: string;\n /** \u9876\u5C42\u547D\u4EE4\u540D\uFF08module \u5B50\u547D\u4EE4\u7528 \"module\"\uFF1B\u9876\u5C42\u522B\u540D\u89C1 TOP_LEVEL_ALIASES\uFF09 */\n name: string;\n /** \u5B50\u547D\u4EE4\uFF08\u4EC5 module/packs \u7B49\uFF09 */\n sub?: string;\n channel: CommandChannel;\n needsTty?: boolean;\n /** \u5E2E\u52A9\u67D3\u8272\uFF1B\u4E0D\u53C2\u4E0E canRun */\n accent?: CommandAccent;\n /** \u5B50\u547D\u4EE4\u540C\u4E49\u522B\u540D\uFF08\u5982 uninstall \u2192 remove\uFF09\uFF0C\u4E0D\u662F\u9876\u5C42\u522B\u540D */\n aliases?: string[];\n};\n\nexport type CanRunContext = {\n mode: CommandMode;\n isTty: boolean;\n};\n\nexport type CanRunFailReason = \"replOnly\" | \"needTty\";\n\nexport type CanRunResult = { ok: true } | { ok: false; reason: CanRunFailReason };\n\n/** \u9876\u5C42\u547D\u4EE4\u522B\u540D \u2192 \u89C4\u8303 name\uFF08DRY\uFF1A\u52FF\u5728\u5404 sub spec \u91CD\u590D\u5199 mod/addon\uFF09 */\nexport const TOP_LEVEL_ALIASES: Readonly<Record<string, string>> = {\n mod: \"module\",\n addon: \"packs\",\n log: \"logs\",\n lang: \"locale\",\n h: \"help\",\n \"?\": \"help\",\n exit: \"quit\",\n q: \"quit\",\n i: \"install\",\n remove: \"uninstall\",\n};\n\n/**\n * \u9876\u5C42\u6241\u5E73\u77ED\u547D\u4EE4 \u2192 module \u5B50\u547D\u4EE4\uFF08argv / REPL \u5171\u7528\uFF0C\u907F\u514D\u5728 switch \u91CC\u6563\u843D\u6620\u5C04\uFF09\n * \u4E0D\u542B enable/disable\uFF08\u4E0E packs \u51B2\u7A81\uFF0C\u4ECD\u8D70 /module \u6216 /packs\uFF09\n *\n * \u4E0E packs \u5B50\u547D\u4EE4\u5BF9\u9F50\uFF1A`packs i` \u2192 `packs install`\uFF08mapPacksSubAlias\uFF09\uFF1B\n * module \u9876\u5C42\u540C\u6837\u652F\u6301 `i` \u2192 `install`\uFF08\u89C1 TOP_LEVEL_ALIASES \u4E0E\u672C\u8868\uFF09\u3002\n */\nexport const MODULE_TOP_SHORTHAND: Readonly<Record<string, string>> = {\n i: \"install\",\n install: \"install\",\n uninstall: \"uninstall\",\n search: \"search\",\n verify: \"verify\",\n};\n\nexport function resolveModuleTopShorthand(cmd: string | undefined): string | undefined {\n if (!cmd) return undefined;\n const name = resolveTopLevelName(cmd);\n if (!name) return undefined;\n return MODULE_TOP_SHORTHAND[name];\n}\n\nexport function resolveTopLevelName(cmd: string | undefined): string | undefined {\n if (!cmd) return undefined;\n return TOP_LEVEL_ALIASES[cmd] ?? cmd;\n}\n\nfunction channelAllows(channel: CommandChannel, mode: CommandMode): boolean {\n if (channel === \"both\") return true;\n return mode === \"repl\";\n}\n\n/** \u5224\u5B9A\u5F53\u524D\u6A21\u5F0F\u4E0B\u80FD\u5426\u6267\u884C\u8BE5\u547D\u4EE4\uFF08accent \u4E0D\u53C2\u4E0E\uFF09\u3002 */\nexport function canRunCommand(spec: CommandSpec, ctx: CanRunContext): CanRunResult {\n if (!channelAllows(spec.channel, ctx.mode)) {\n return { ok: false, reason: \"replOnly\" };\n }\n if (spec.needsTty && !ctx.isTty) {\n return { ok: false, reason: \"needTty\" };\n }\n return { ok: true };\n}\n\n/** \u5F53\u524D\u6A21\u5F0F\u53EF\u89C1\u547D\u4EE4\uFF08help / Tab\uFF09\u3002 */\nexport function listVisibleCommands(mode: CommandMode): CommandSpec[] {\n return COMMAND_SPECS.filter((s) => channelAllows(s.channel, mode));\n}\n\n/** \u9876\u5C42\u547D\u4EE4\u540D\uFF08\u542B\u522B\u540D\uFF09\uFF0C\u4F9B REPL COMMANDS / \u8865\u5168\u3002 */\nexport function listVisibleTopLevelNames(mode: CommandMode): string[] {\n const canonical = new Set<string>();\n for (const s of listVisibleCommands(mode)) {\n canonical.add(s.name);\n }\n const out = new Set<string>(canonical);\n for (const [alias, name] of Object.entries(TOP_LEVEL_ALIASES)) {\n if (canonical.has(name)) out.add(alias);\n }\n return [...out];\n}\n\n/** \u67E5\u627E\u9876\u5C42\u547D\u4EE4\uFF08\u65E0 sub\uFF09\u7684\u4EFB\u610F\u4E00\u6761\u540C\u540D spec\uFF08\u7528\u4E8E channel \u95E8\u7981\uFF09\u3002 */\nexport function findTopLevelSpec(cmd: string | undefined): CommandSpec | undefined {\n const name = resolveTopLevelName(cmd);\n if (!name) return undefined;\n /* \u4F18\u5148\u65E0 sub \u7684\u9876\u5C42\u6761\u76EE\uFF1B\u5426\u5219\u53D6\u8BE5 name \u4E0B\u4EFB\u610F\u53EF\u89C1 spec \u4EE3\u8868\u901A\u9053\uFF08module/packs\uFF09 */\n const top = COMMAND_SPECS.find((s) => !s.sub && s.name === name);\n if (top) return top;\n return COMMAND_SPECS.find((s) => s.name === name);\n}\n\n/** \u67E5\u627E module \u5B50\u547D\u4EE4 spec\u3002 */\nexport function findModuleSubSpec(sub: string | undefined): CommandSpec | undefined {\n if (!sub) return undefined;\n return COMMAND_SPECS.find(\n (s) => s.name === \"module\" && (s.sub === sub || (s.aliases ?? []).includes(sub))\n );\n}\n\n/** \u67E5\u627E packs \u5B50\u547D\u4EE4 spec\u3002 */\nexport function findPacksSubSpec(sub: string | undefined): CommandSpec | undefined {\n if (!sub) return undefined;\n return COMMAND_SPECS.find(\n (s) => s.name === \"packs\" && (s.sub === sub || (s.aliases ?? []).includes(sub))\n );\n}\n\n/** \u5F53\u524D mode \u4E0B\u53EF\u89C1\u7684 module \u5B50\u547D\u4EE4\u540D\uFF08\u89C4\u8303\u540D\uFF0C\u4E0D\u542B remove \u522B\u540D\uFF09\u3002 */\nexport function listVisibleModuleSubs(mode: CommandMode): string[] {\n return listVisibleCommands(mode)\n .filter((s) => s.name === \"module\" && s.sub)\n .map((s) => s.sub!);\n}\n\n/** \u5F53\u524D mode \u4E0B\u53EF\u89C1\u7684 packs \u5B50\u547D\u4EE4\u540D\u3002 */\nexport function listVisiblePacksSubs(mode: CommandMode): string[] {\n return listVisibleCommands(mode)\n .filter((s) => s.name === \"packs\" && s.sub)\n .map((s) => s.sub!);\n}\n\n/** REPL \u5FEB\u901F\u8865\u5168\uFF1A\u5C42\u7EA7\u8282\u70B9\uFF08\u4E3B\u9762\u677F \u2192 \u53F3\u4FA7\u5B50\u9762\u677F\uFF09 */\nexport type PaletteNode = {\n /** \u9762\u677F\u5185\u663E\u793A\u7684\u6807\u7B7E */\n label: string;\n /** \u8FFD\u52A0\u5230\u547D\u4EE4\u884C\u7684 token\uFF08\u6839\u8282\u70B9\u542B\u6216\u4E0D\u542B\u524D\u5BFC\u903B\u8F91\u7531\u7EC4\u88C5\u8D1F\u8D23\uFF09 */\n token: string;\n /** i18n \u63CF\u8FF0\u952E */\n descKey?: string;\n accent?: CommandAccent;\n /** \u56FA\u5B9A\u4E0B\u4E00\u53C2\u9009\u9879\uFF1B\u56DE\u8F66\u540E\u5728\u53F3\u4FA7\u5C55\u5F00 */\n children?: PaletteNode[];\n /** \u65E0 children \u65F6\u4ECD\u9700\u81EA\u7531\u8F93\u5165\uFF08\u56DE\u8F66\u540E\u586B\u5165\u7A7A\u683C\u7EE7\u7EED\u6253\u5B57\uFF09 */\n freeArgs?: boolean;\n};\n\nconst NO_ARG_TOP = new Set([\"status\", \"help\", \"version\", \"quit\", \"init\", \"logs\"]);\n\nconst TOP_DESC: Record<string, string> = {\n status: \"help.status\",\n logs: \"help.logs\",\n start: \"help.start\",\n stop: \"help.stop\",\n restart: \"help.restart\",\n send: \"help.send\",\n help: \"help.help\",\n version: \"help.version\",\n quit: \"help.quit\",\n init: \"help.init\",\n update: \"help.update\",\n locale: \"help.locale\",\n debug: \"help.debug.status\",\n ui: \"help.ui\",\n install: \"help.module.install\",\n uninstall: \"help.module.uninstall\",\n search: \"help.module.search\",\n verify: \"help.module.verify\",\n};\n\nconst MODULE_DESC: Record<string, string> = {\n list: \"help.module.list\",\n info: \"help.module.info\",\n build: \"help.module.build\",\n reload: \"help.module.reload\",\n search: \"help.module.search\",\n install: \"help.module.install\",\n uninstall: \"help.module.uninstall\",\n verify: \"help.module.verify\",\n enable: \"help.module.toggle\",\n disable: \"help.module.toggle\",\n};\n\nconst PACKS_DESC: Record<string, string> = {\n list: \"help.packs.list\",\n search: \"help.packs.search\",\n enable: \"help.packs.enable\",\n disable: \"help.packs.disable\",\n doctor: \"help.packs.doctor\",\n path: \"help.packs.path\",\n install: \"help.addon\",\n scan: \"help.addon\",\n uninstall: \"help.addon\",\n bind: \"help.addon\",\n unbind: \"help.addon\",\n sources: \"help.addon\",\n check: \"help.addon\",\n update: \"help.addon\",\n bump: \"help.addon\",\n};\n\nfunction serviceArgNodes(): PaletteNode[] {\n return [\n { label: \"-all\", token: \"-all\" },\n ...([\"bds\", \"db\", \"qq\", \"llbot\"] as const).map((n) => ({ label: n, token: n })),\n ];\n}\n\nfunction moduleChildNodes(mode: CommandMode): PaletteNode[] {\n const noArg = new Set([\"list\", \"build\"]);\n return listVisibleModuleSubs(mode).map((sub) => {\n const spec = findModuleSubSpec(sub);\n const node: PaletteNode = {\n label: sub,\n token: sub,\n descKey: MODULE_DESC[sub] ?? \"help.module.list\",\n freeArgs: !noArg.has(sub),\n };\n if (spec?.accent) node.accent = spec.accent;\n return node;\n });\n}\n\nfunction packsChildNodes(mode: CommandMode): PaletteNode[] {\n const noArg = new Set([\"list\", \"path\", \"sources\"]);\n return listVisiblePacksSubs(mode).map((sub) => ({\n label: sub,\n token: sub,\n descKey: PACKS_DESC[sub] ?? \"help.addon\",\n freeArgs: !noArg.has(sub),\n }));\n}\n\n/** \u5C42\u7EA7\u547D\u4EE4\u6811\uFF08REPL \u9762\u677F\u4E3B\u5217\uFF09 */\nexport function listPaletteRoots(mode: CommandMode = \"repl\"): PaletteNode[] {\n const specs = listVisibleCommands(mode);\n const out: PaletteNode[] = [];\n const seen = new Set<string>();\n /** \u9762\u677F\u4E0D\u5C55\u793A\u9876\u5C42\u77ED\u547D\u4EE4\uFF0C\u7EDF\u4E00\u8D70 /module <sub>\uFF08argv \u77ED\u547D\u4EE4\u4ECD\u53EF\u7528\uFF09 */\n const skipTopShorthand = new Set(Object.keys(MODULE_TOP_SHORTHAND));\n\n for (const s of specs) {\n if (s.sub) continue;\n if (s.name === \"module\" || s.name === \"packs\") continue;\n if (skipTopShorthand.has(s.name)) continue;\n if (seen.has(s.name)) continue;\n seen.add(s.name);\n\n const node: PaletteNode = {\n label: `/${s.name}`,\n token: s.name,\n descKey: TOP_DESC[s.name] ?? \"help.help\",\n };\n if (s.accent) node.accent = s.accent;\n\n if (s.name === \"start\" || s.name === \"stop\" || s.name === \"restart\") {\n node.children = serviceArgNodes();\n } else if (s.name === \"send\") {\n node.children = ([\"bds\", \"db\", \"qq\", \"llbot\"] as const).map((n) => ({\n label: n,\n token: n,\n freeArgs: true,\n }));\n } else if (!NO_ARG_TOP.has(s.name)) {\n node.freeArgs = true;\n }\n\n out.push(node);\n }\n\n const moduleSubs = moduleChildNodes(mode);\n if (moduleSubs.length > 0) {\n out.push({\n label: \"/module\",\n token: \"module\",\n descKey: \"help.module.list\",\n children: moduleSubs,\n });\n }\n\n const packsSubs = packsChildNodes(mode);\n if (packsSubs.length > 0) {\n out.push({\n label: \"/packs\",\n token: \"packs\",\n descKey: \"help.addon\",\n children: packsSubs,\n });\n }\n\n return out;\n}\n\nexport function isDevAccent(spec: CommandSpec | undefined): boolean {\n return spec?.accent === \"dev\";\n}\n\n/** sub \u662F\u5426\u4E3A\u5F00\u53D1\u8005\u6837\u5F0F\u547D\u4EE4\uFF08\u84DD\u6807\uFF09\u3002 */\nexport function isDevAccentModuleSub(sub: string | undefined): boolean {\n return isDevAccent(findModuleSubSpec(sub));\n}\n\n/** stdin TTY \u63A2\u6D4B\uFF08\u4F9B main/repl \u5171\u7528\uFF09\u3002 */\nexport function isCliTty(): boolean {\n return Boolean(stdin.isTTY);\n}\n\n/**\n * \u547D\u4EE4\u6CE8\u518C\u8868 \u2014\u2014 \u65B0\u589E\u547D\u4EE4\u53EA\u52A0\u6B64\u5904\uFF08OCP\uFF09\u3002\n * channel:\n * - both: argv + REPL\uFF08\u9ED8\u8BA4\uFF1B\u9762\u677F\u53EA\u8C03\u5EA6\u65E2\u6709 dispatcher\uFF09\n * - repl: \u4EC5 REPL\uFF08\u5982 send / quit\uFF09\n */\nexport const COMMAND_SPECS: readonly CommandSpec[] = [\n /* \u2500\u2500\u2500 both\uFF1A\u670D\u52A1 / \u6A21\u5757 / \u8D44\u6E90\u5305 / \u914D\u7F6E \u2500\u2500\u2500 */\n { id: \"status\", name: \"status\", channel: \"both\" },\n { id: \"start\", name: \"start\", channel: \"both\" },\n { id: \"stop\", name: \"stop\", channel: \"both\" },\n { id: \"restart\", name: \"restart\", channel: \"both\" },\n { id: \"logs\", name: \"logs\", channel: \"repl\" },\n { id: \"help\", name: \"help\", channel: \"both\" },\n { id: \"version\", name: \"version\", channel: \"both\" },\n { id: \"init\", name: \"init\", channel: \"both\", needsTty: true },\n { id: \"update\", name: \"update\", channel: \"both\" },\n { id: \"locale\", name: \"locale\", channel: \"both\" },\n { id: \"debug\", name: \"debug\", channel: \"both\", accent: \"dev\" },\n { id: \"ui\", name: \"ui\", channel: \"both\", accent: \"dev\" },\n\n /** \u9876\u5C42\u6241\u5E73\u77ED\u547D\u4EE4 \u2192 module.*\uFF08\u5C11\u5199\u4E00\u5C42 module\uFF09 */\n { id: \"install\", name: \"install\", channel: \"both\" },\n { id: \"uninstall\", name: \"uninstall\", channel: \"both\", aliases: [\"remove\"] },\n { id: \"search\", name: \"search\", channel: \"both\" },\n { id: \"verify\", name: \"verify\", channel: \"both\" },\n\n { id: \"module.list\", name: \"module\", sub: \"list\", channel: \"both\" },\n { id: \"module.info\", name: \"module\", sub: \"info\", channel: \"both\" },\n { id: \"module.build\", name: \"module\", sub: \"build\", channel: \"both\", accent: \"dev\" },\n { id: \"module.reload\", name: \"module\", sub: \"reload\", channel: \"both\", accent: \"dev\" },\n { id: \"module.install\", name: \"module\", sub: \"install\", channel: \"both\" },\n {\n id: \"module.uninstall\",\n name: \"module\",\n sub: \"uninstall\",\n channel: \"both\",\n aliases: [\"remove\"],\n },\n { id: \"module.search\", name: \"module\", sub: \"search\", channel: \"both\" },\n { id: \"module.verify\", name: \"module\", sub: \"verify\", channel: \"both\" },\n { id: \"module.enable\", name: \"module\", sub: \"enable\", channel: \"both\" },\n { id: \"module.disable\", name: \"module\", sub: \"disable\", channel: \"both\" },\n\n { id: \"packs.list\", name: \"packs\", sub: \"list\", channel: \"both\" },\n { id: \"packs.search\", name: \"packs\", sub: \"search\", channel: \"both\" },\n { id: \"packs.enable\", name: \"packs\", sub: \"enable\", channel: \"both\" },\n { id: \"packs.disable\", name: \"packs\", sub: \"disable\", channel: \"both\" },\n { id: \"packs.doctor\", name: \"packs\", sub: \"doctor\", channel: \"both\" },\n { id: \"packs.path\", name: \"packs\", sub: \"path\", channel: \"both\" },\n { id: \"packs.install\", name: \"packs\", sub: \"install\", channel: \"both\" },\n { id: \"packs.scan\", name: \"packs\", sub: \"scan\", channel: \"both\" },\n { id: \"packs.uninstall\", name: \"packs\", sub: \"uninstall\", channel: \"both\" },\n { id: \"packs.bind\", name: \"packs\", sub: \"bind\", channel: \"both\" },\n { id: \"packs.unbind\", name: \"packs\", sub: \"unbind\", channel: \"both\" },\n { id: \"packs.sources\", name: \"packs\", sub: \"sources\", channel: \"both\" },\n { id: \"packs.check\", name: \"packs\", sub: \"check\", channel: \"both\" },\n { id: \"packs.update\", name: \"packs\", sub: \"update\", channel: \"both\" },\n { id: \"packs.bump\", name: \"packs\", sub: \"bump\", channel: \"both\" },\n\n /* \u2500\u2500\u2500 repl-only \u2500\u2500\u2500 */\n { id: \"send\", name: \"send\", channel: \"repl\" },\n { id: \"quit\", name: \"quit\", channel: \"repl\" },\n];\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/commands.d.ts
CHANGED
|
@@ -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
|
|
12
|
-
*
|
|
61
|
+
* 触发 BDS 核心版本更新检查与热升级流程。
|
|
62
|
+
*
|
|
63
|
+
* 进程管理与编排约束:
|
|
64
|
+
* - updater 子进程始终附加 `--no-start` 参数,避免由于进程脱离导致 REPL 丢失 PID 跟踪及标准输出
|
|
65
|
+
* - 若更新前 BDS 处于运行状态,且未显式指定 `--no-start`,在更新落盘部署完成后由监督器重新唤起 BDS
|
|
13
66
|
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
67
|
+
* @param args 传递给更新器的命令行参数。
|
|
68
|
+
* @returns 更新执行结果摘要文本。
|
|
16
69
|
*/
|
|
17
70
|
export declare function cmdUpdate(args?: string[]): Promise<string>;
|
|
18
71
|
//# sourceMappingURL=commands.d.ts.map
|
package/dist/commands.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../src/commands.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../src/commands.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAgBH,OAAO,EAAuD,KAAK,WAAW,EAAE,MAAM,eAAe,CAAC;AA+CtG;;;;GAIG;AACH,wBAAsB,SAAS,IAAI,OAAO,CAAC,MAAM,CAAC,CAYjD;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,CAuC3D;AAED;;;;;GAKG;AACH,wBAAsB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAgE1D;AAED,wBAAsB,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAyB3E;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,CAkFpE"}
|
package/dist/commands.js
CHANGED
|
@@ -1,11 +1,18 @@
|
|
|
1
|
-
import { killBedrockServerByImage, probeBdsStatus
|
|
2
|
-
import {
|
|
1
|
+
import { clearBdsPidFile, killBedrockServerByImage, probeBdsStatus } from "@sfmc-bds/bds-tools/process-probe";
|
|
2
|
+
import { stripTaskbarOsc } from "@sfmc-bds/bds-tools/taskbar";
|
|
3
|
+
import { didUpdateDeploy } from "@sfmc-bds/bds-tools/update-result";
|
|
4
|
+
import {
|
|
5
|
+
DEFAULT_QQ_CONFIG,
|
|
6
|
+
loadEnsuredConfig,
|
|
7
|
+
qqRuntimeStatusPath
|
|
8
|
+
} from "@sfmc-bds/sdk/node/config";
|
|
9
|
+
import fs from "node:fs";
|
|
3
10
|
import { t } from "./i18n/index.js";
|
|
11
|
+
import { pushLog as pushUnifiedLog } from "./logs.js";
|
|
12
|
+
import { findNodeServicePids, killNodeServiceByScript } from "./node-service-probe.js";
|
|
4
13
|
import { spawnService } from "./runtime.js";
|
|
5
|
-
import { ROOT, SERVICE_NAMES,
|
|
14
|
+
import { queryServicesRuntime, ROOT, SERVICE_NAMES, services } from "./services.js";
|
|
6
15
|
import { c, DIVIDER, highlightLogLine, padRight } from "./theme.js";
|
|
7
|
-
import { stripTaskbarOsc } from "@sfmc-bds/bds-tools/taskbar";
|
|
8
|
-
import { didUpdateDeploy } from "@sfmc-bds/bds-tools/update-result";
|
|
9
16
|
function parseService(raw) {
|
|
10
17
|
const s = raw.toLowerCase();
|
|
11
18
|
if (SERVICE_NAMES.includes(s)) return s;
|
|
@@ -19,7 +26,27 @@ function statusLine(name, running, pid, uptime, ownership) {
|
|
|
19
26
|
else if (running && ownership === "external") owner = c.yellow(t("svc.owner.external"));
|
|
20
27
|
const pidStr = pid ? c.dim(String(pid)) : c.dim("\u2014");
|
|
21
28
|
const upStr = uptime !== "\u2014" ? c.dim(uptime) : c.dim("\u2014");
|
|
22
|
-
return ` ${dot} ${c.bold(padRight(name,
|
|
29
|
+
return ` ${dot} ${c.bold(padRight(name, 14))} ${padRight(state, 8)} ${padRight(owner, 6)} ${padRight(pidStr, 8)} ${upStr}`;
|
|
30
|
+
}
|
|
31
|
+
function qqBridgeStatusFooter() {
|
|
32
|
+
const qqCfg = loadEnsuredConfig(ROOT, "qq_config.json", "qq_config", { ...DEFAULT_QQ_CONFIG });
|
|
33
|
+
const backend = qqCfg.qq_backend === "llbot" ? "llbot" : "official";
|
|
34
|
+
const enabled = qqCfg.qq_enabled !== false;
|
|
35
|
+
if (backend === "llbot") {
|
|
36
|
+
const group = qqCfg.llbot?.group_id || "\u2014";
|
|
37
|
+
const pathHint = qqCfg.llbot?.path ? String(qqCfg.llbot.path) : "\u2014";
|
|
38
|
+
return `
|
|
39
|
+
${c.dim(t("svc.qq.footer.llbot", { enabled: enabled ? "on" : "off", group, path: pathHint }))}
|
|
40
|
+
`;
|
|
41
|
+
}
|
|
42
|
+
const appId = String(qqCfg.official?.app_id ?? "").trim();
|
|
43
|
+
const appIdHint = appId ? appId.length > 8 ? `${appId.slice(0, 4)}\u2026${appId.slice(-4)}` : appId : "\u2014";
|
|
44
|
+
const openid = String(qqCfg.official?.group_openid ?? "").trim() || "\u2014";
|
|
45
|
+
const sandbox = qqCfg.official?.sandbox ? "sandbox" : "prod";
|
|
46
|
+
const creds = appId && String(qqCfg.official?.app_secret ?? "").trim() ? "ok" : "missing";
|
|
47
|
+
return `
|
|
48
|
+
${c.dim(t("svc.qq.footer.official", { enabled: enabled ? "on" : "off", appId: appIdHint, openid, sandbox, creds }))}
|
|
49
|
+
`;
|
|
23
50
|
}
|
|
24
51
|
async function cmdStatus() {
|
|
25
52
|
const rows = await queryServicesRuntime();
|
|
@@ -29,10 +56,10 @@ async function cmdStatus() {
|
|
|
29
56
|
const ownerH = t("svc.col.owner");
|
|
30
57
|
const pidH = t("svc.col.pid");
|
|
31
58
|
const upH = t("svc.col.uptime");
|
|
32
|
-
const header = ` ${padRight(nameH,
|
|
59
|
+
const header = ` ${padRight(nameH, 16)}${padRight(statusH, 8)}${padRight(ownerH, 6)}${padRight(pidH, 8)}${upH}`;
|
|
33
60
|
return `
|
|
34
61
|
${c.bold(t("svc.header"))}
|
|
35
|
-
` + c.dim(header) + "\n" + DIVIDER + "\n" + lines.join("\n") +
|
|
62
|
+
` + c.dim(header) + "\n" + DIVIDER + "\n" + lines.join("\n") + qqBridgeStatusFooter();
|
|
36
63
|
}
|
|
37
64
|
function cmdLogs(args, onFollow) {
|
|
38
65
|
let n = 20;
|
|
@@ -72,6 +99,16 @@ ${c.bold(t("svc.logs.header", { title: svcObj.title, count: lines.length }))}`;
|
|
|
72
99
|
}
|
|
73
100
|
const STARTING = /* @__PURE__ */ new Set();
|
|
74
101
|
const STOPPING = /* @__PURE__ */ new Set();
|
|
102
|
+
function isNodeSvc(name) {
|
|
103
|
+
return name === "db" || name === "qq";
|
|
104
|
+
}
|
|
105
|
+
function clearQqRuntimeFile() {
|
|
106
|
+
try {
|
|
107
|
+
const file = qqRuntimeStatusPath(ROOT);
|
|
108
|
+
if (fs.existsSync(file)) fs.unlinkSync(file);
|
|
109
|
+
} catch {
|
|
110
|
+
}
|
|
111
|
+
}
|
|
75
112
|
async function cmdStart(raw) {
|
|
76
113
|
const svc = parseService(raw);
|
|
77
114
|
if (!svc) return c.red(t("svc.unknown", { name: raw, list: SERVICE_NAMES.join(", ") }));
|
|
@@ -87,11 +124,23 @@ async function cmdStart(raw) {
|
|
|
87
124
|
);
|
|
88
125
|
}
|
|
89
126
|
}
|
|
127
|
+
if (isNodeSvc(svc)) {
|
|
128
|
+
const external = await findNodeServicePids(svc);
|
|
129
|
+
if (external.length > 0) {
|
|
130
|
+
return c.yellow(t("svc.alreadyRunning", { title: svcObj.title, pid: String(external.join(",")) }));
|
|
131
|
+
}
|
|
132
|
+
}
|
|
90
133
|
if (svcObj.running) return c.yellow(t("svc.alreadyRunning", { title: svcObj.title, pid: svcObj.pid }));
|
|
91
134
|
if (STARTING.has(svc)) return c.dim(t("svc.alreadyStarting", { title: svcObj.title }));
|
|
92
135
|
STARTING.add(svc);
|
|
93
136
|
try {
|
|
94
|
-
await svcObj.start();
|
|
137
|
+
const outcome = await svcObj.start();
|
|
138
|
+
if (outcome.status === "skipped") {
|
|
139
|
+
return c.yellow(t("svc.skipped", { title: svcObj.title, reason: outcome.reason }));
|
|
140
|
+
}
|
|
141
|
+
if (outcome.status === "already") {
|
|
142
|
+
return c.yellow(t("svc.alreadyRunning", { title: svcObj.title, pid: svcObj.pid }));
|
|
143
|
+
}
|
|
95
144
|
return c.green(t("svc.started", { title: svcObj.title }));
|
|
96
145
|
} catch (e) {
|
|
97
146
|
return c.red(t("svc.startFailed", { title: svcObj.title, message: e.message }));
|
|
@@ -123,7 +172,33 @@ async function cmdStop(raw) {
|
|
|
123
172
|
}
|
|
124
173
|
}
|
|
125
174
|
}
|
|
126
|
-
if (
|
|
175
|
+
if (isNodeSvc(svc)) {
|
|
176
|
+
if (STOPPING.has(svc)) return c.dim(t("svc.alreadyStopping", { title: svcObj.title }));
|
|
177
|
+
STOPPING.add(svc);
|
|
178
|
+
try {
|
|
179
|
+
const managed = svcObj.running;
|
|
180
|
+
if (managed) {
|
|
181
|
+
await svcObj.stop();
|
|
182
|
+
}
|
|
183
|
+
const killed = await killNodeServiceByScript(svc);
|
|
184
|
+
if (svc === "qq") clearQqRuntimeFile();
|
|
185
|
+
if (!managed && killed.length === 0) {
|
|
186
|
+
return c.yellow(t("svc.alreadyStopped", { title: svcObj.title }));
|
|
187
|
+
}
|
|
188
|
+
if (!managed && killed.length > 0) {
|
|
189
|
+
return c.dim(t("svc.stoppedExternal", { title: svcObj.title }));
|
|
190
|
+
}
|
|
191
|
+
return c.dim(t("svc.stoppedMsg", { title: svcObj.title }));
|
|
192
|
+
} catch (e) {
|
|
193
|
+
return c.red(t("svc.stopFailed", { title: svcObj.title, message: e.message }));
|
|
194
|
+
} finally {
|
|
195
|
+
STOPPING.delete(svc);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
if (!svcObj.running) {
|
|
199
|
+
if (svc === "tunnel") await svcObj.stop();
|
|
200
|
+
return c.yellow(t("svc.alreadyStopped", { title: svcObj.title }));
|
|
201
|
+
}
|
|
127
202
|
if (STOPPING.has(svc)) return c.dim(t("svc.alreadyStopping", { title: svcObj.title }));
|
|
128
203
|
STOPPING.add(svc);
|
|
129
204
|
try {
|
|
@@ -138,6 +213,7 @@ async function cmdStop(raw) {
|
|
|
138
213
|
async function cmdSend(raw, message) {
|
|
139
214
|
const svc = parseService(raw);
|
|
140
215
|
if (!svc) return c.red(t("svc.unknown", { name: raw, list: SERVICE_NAMES.join(", ") }));
|
|
216
|
+
if (svc === "tunnel") return c.yellow(t("svc.stdinUnavailable", { title: services[svc].title }));
|
|
141
217
|
if (!message) return c.yellow(t("svc.send.usage"));
|
|
142
218
|
const svcObj = services[svc];
|
|
143
219
|
await queryServicesRuntime();
|
|
@@ -162,13 +238,21 @@ async function cmdSend(raw, message) {
|
|
|
162
238
|
async function cmdRestart(raw) {
|
|
163
239
|
const svc = parseService(raw);
|
|
164
240
|
if (!svc) return c.red(t("svc.unknown", { name: raw, list: SERVICE_NAMES.join(", ") }));
|
|
165
|
-
if (svc === "bds") {
|
|
166
|
-
await cmdStop(
|
|
167
|
-
|
|
241
|
+
if (svc === "bds" || isNodeSvc(svc)) {
|
|
242
|
+
const stopMsg = await cmdStop(svc);
|
|
243
|
+
const startMsg = await cmdStart(svc);
|
|
244
|
+
if (/失败|failed/i.test(stopMsg) && !/已停止|stopped|already/i.test(stopMsg)) {
|
|
245
|
+
return stopMsg;
|
|
246
|
+
}
|
|
247
|
+
if (/失败|failed/i.test(startMsg)) return startMsg;
|
|
248
|
+
return c.green(t("svc.restarted", { title: services[svc].title }));
|
|
168
249
|
}
|
|
169
250
|
const svcObj = services[svc];
|
|
170
251
|
try {
|
|
171
|
-
await svcObj.restart();
|
|
252
|
+
const outcome = await svcObj.restart();
|
|
253
|
+
if (outcome.status === "skipped") {
|
|
254
|
+
return c.yellow(t("svc.skipped", { title: svcObj.title, reason: outcome.reason }));
|
|
255
|
+
}
|
|
172
256
|
return c.green(t("svc.restarted", { title: svcObj.title }));
|
|
173
257
|
} catch (e) {
|
|
174
258
|
return c.red(t("svc.restartFailed", { title: svcObj.title, message: e.message }));
|
|
@@ -176,8 +260,34 @@ async function cmdRestart(raw) {
|
|
|
176
260
|
}
|
|
177
261
|
async function cmdStartAll() {
|
|
178
262
|
const { startAll } = await import("./services.js");
|
|
179
|
-
await startAll();
|
|
180
|
-
|
|
263
|
+
const result = await startAll();
|
|
264
|
+
const parts = [];
|
|
265
|
+
if (result.started.length > 0) {
|
|
266
|
+
parts.push(c.green(t("svc.startAll.started", { list: result.started.join(", ") })));
|
|
267
|
+
}
|
|
268
|
+
if (result.skipped.length > 0) {
|
|
269
|
+
parts.push(
|
|
270
|
+
c.dim(
|
|
271
|
+
t("svc.startAll.skipped", {
|
|
272
|
+
list: result.skipped.map((s) => `${s.name}(${s.reason})`).join("; ")
|
|
273
|
+
})
|
|
274
|
+
)
|
|
275
|
+
);
|
|
276
|
+
}
|
|
277
|
+
if (result.failed.length > 0) {
|
|
278
|
+
parts.push(
|
|
279
|
+
c.red(
|
|
280
|
+
t("svc.startAll.failed", {
|
|
281
|
+
list: result.failed.map((s) => `${s.name}: ${s.reason}`).join("; ")
|
|
282
|
+
})
|
|
283
|
+
)
|
|
284
|
+
);
|
|
285
|
+
}
|
|
286
|
+
if (parts.length === 0) return c.dim(t("svc.startAll.empty"));
|
|
287
|
+
if (result.failed.length === 0 && result.skipped.length === 0) {
|
|
288
|
+
return c.green(t("svc.allStarted"));
|
|
289
|
+
}
|
|
290
|
+
return parts.join("\n");
|
|
181
291
|
}
|
|
182
292
|
async function cmdStopAll() {
|
|
183
293
|
const { stopAll } = await import("./services.js");
|
|
@@ -189,65 +299,71 @@ async function cmdUpdate(args = []) {
|
|
|
189
299
|
const checkOnly = args.includes("--check-only");
|
|
190
300
|
const spawnArgs = userNoStart ? [...args] : [...args, "--no-start"];
|
|
191
301
|
const bds = services.bds;
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
rootDir: ROOT
|
|
196
|
-
});
|
|
197
|
-
const bdsWasRunning = bdsProbe.state !== "stopped";
|
|
198
|
-
const result = await new Promise((resolve) => {
|
|
199
|
-
const proc = spawnService("update", spawnArgs, {
|
|
200
|
-
cwd: ROOT,
|
|
201
|
-
stdio: ["ignore", "pipe", "pipe"]
|
|
202
|
-
});
|
|
203
|
-
let out = "";
|
|
204
|
-
const pushChunk = (raw, level) => {
|
|
205
|
-
const s = stripTaskbarOsc(raw);
|
|
206
|
-
out += s;
|
|
207
|
-
for (const line of s.split(/\r?\n/).map((l) => l.trimEnd()).filter((l) => l.length > 0)) {
|
|
208
|
-
pushUnifiedLog(line, "update", level);
|
|
209
|
-
}
|
|
210
|
-
};
|
|
211
|
-
proc.stdout?.on("data", (d) => pushChunk(d.toString(), "info"));
|
|
212
|
-
proc.stderr?.on("data", (d) => pushChunk(d.toString(), "error"));
|
|
213
|
-
proc.on("exit", (code) => {
|
|
214
|
-
if (code === 0) {
|
|
215
|
-
pushUnifiedLog(t("svc.updateComplete"), "system", "success");
|
|
216
|
-
resolve({ code: 0, out: (out ? out + "\n" : "") + t("svc.updateComplete") });
|
|
217
|
-
} else {
|
|
218
|
-
resolve({ code, out: out || t("svc.updateExited", { code: String(code) }) });
|
|
219
|
-
}
|
|
220
|
-
});
|
|
221
|
-
proc.on("error", (e) => {
|
|
222
|
-
pushUnifiedLog(t("svc.updateError", { message: e.message }), "system", "error");
|
|
223
|
-
resolve({ code: 1, out: t("svc.updateError", { message: e.message }) });
|
|
224
|
-
});
|
|
225
|
-
});
|
|
226
|
-
const didDeploy = didUpdateDeploy(result.out);
|
|
227
|
-
if (result.code === 0 && didDeploy && !userNoStart && !checkOnly) {
|
|
228
|
-
const afterProbe = await probeBdsStatus({
|
|
302
|
+
bds.beginUpdate();
|
|
303
|
+
try {
|
|
304
|
+
const bdsProbe = await probeBdsStatus({
|
|
229
305
|
managedPid: bds.pid,
|
|
230
306
|
hasStdin: Boolean(bds.proc?.stdin),
|
|
231
307
|
rootDir: ROOT
|
|
232
308
|
});
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
309
|
+
const bdsWasRunning = bdsProbe.state !== "stopped";
|
|
310
|
+
const result = await new Promise((resolve) => {
|
|
311
|
+
const proc = spawnService("update", spawnArgs, {
|
|
312
|
+
cwd: ROOT,
|
|
313
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
314
|
+
});
|
|
315
|
+
let out = "";
|
|
316
|
+
const pushChunk = (raw, level) => {
|
|
317
|
+
const s = stripTaskbarOsc(raw);
|
|
318
|
+
out += s;
|
|
319
|
+
for (const line of s.split(/\r?\n/).map((l) => l.trimEnd()).filter((l) => l.length > 0)) {
|
|
320
|
+
pushUnifiedLog(line, "update", level);
|
|
321
|
+
}
|
|
322
|
+
};
|
|
323
|
+
proc.stdout?.on("data", (d) => pushChunk(d.toString(), "info"));
|
|
324
|
+
proc.stderr?.on("data", (d) => pushChunk(d.toString(), "error"));
|
|
325
|
+
proc.on("exit", (code) => {
|
|
326
|
+
if (code === 0) {
|
|
327
|
+
pushUnifiedLog(t("svc.updateComplete"), "system", "success");
|
|
328
|
+
resolve({ code: 0, out: (out ? out + "\n" : "") + t("svc.updateComplete") });
|
|
329
|
+
} else {
|
|
330
|
+
resolve({ code, out: out || t("svc.updateExited", { code: String(code) }) });
|
|
331
|
+
}
|
|
332
|
+
});
|
|
333
|
+
proc.on("error", (e) => {
|
|
334
|
+
pushUnifiedLog(t("svc.updateError", { message: e.message }), "system", "error");
|
|
335
|
+
resolve({ code: 1, out: t("svc.updateError", { message: e.message }) });
|
|
336
|
+
});
|
|
337
|
+
});
|
|
338
|
+
const didDeploy = didUpdateDeploy(result.out);
|
|
339
|
+
if (result.code === 0 && didDeploy && !userNoStart && !checkOnly) {
|
|
340
|
+
const afterProbe = await probeBdsStatus({
|
|
341
|
+
managedPid: bds.pid,
|
|
342
|
+
hasStdin: Boolean(bds.proc?.stdin),
|
|
343
|
+
rootDir: ROOT
|
|
344
|
+
});
|
|
345
|
+
if (afterProbe.state !== "stopped") {
|
|
346
|
+
return result.out;
|
|
347
|
+
}
|
|
348
|
+
try {
|
|
349
|
+
pushUnifiedLog(t("svc.updateStartBds"), "system", "info");
|
|
350
|
+
bds.endUpdate();
|
|
351
|
+
await bds.start();
|
|
352
|
+
return result.out + "\n" + c.green(t("svc.bdsStarted"));
|
|
353
|
+
} catch (e) {
|
|
354
|
+
return result.out + "\n" + c.red(t("svc.bdsStartFailed", { message: e.message }));
|
|
355
|
+
}
|
|
242
356
|
}
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
357
|
+
if (result.code === 0 && didDeploy && userNoStart && bdsWasRunning) {
|
|
358
|
+
const afterProbe = await probeBdsStatus({ rootDir: ROOT });
|
|
359
|
+
if (afterProbe.state === "stopped") {
|
|
360
|
+
return result.out + "\n" + c.yellow(t("svc.bdsStoppedForUpdate"));
|
|
361
|
+
}
|
|
248
362
|
}
|
|
363
|
+
return result.out;
|
|
364
|
+
} finally {
|
|
365
|
+
bds.endUpdate();
|
|
249
366
|
}
|
|
250
|
-
return result.out;
|
|
251
367
|
}
|
|
252
368
|
export {
|
|
253
369
|
cmdLogs,
|