@sfmc-bds/cli 0.8.0 → 0.10.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.
@@ -0,0 +1,17 @@
1
+ /**
2
+ * local-methods.ts — 管理通道在 stdio 进程内直接作答的只读方法
3
+ *
4
+ * 使用场景:stdio.ts 收到这些方法时不转发给常驻守护进程,而是用磁盘上的新代码读取数据库,
5
+ * 平台升级后不必重启仍在托管服务的守护进程即可使用;server.ts 握手时声明对应能力。
6
+ * 守护进程握手结果由旧代码生成时,stdio.ts 也会补上 LOCAL_CAPABILITIES。
7
+ * 新增此类只读方法时在这里登记(OCP)。
8
+ */
9
+ import type { ManagementCapability } from "@sfmc-bds/management";
10
+ /** 在 stdio 进程内直接分派给 dispatchManagement 的方法 */
11
+ export declare const LOCAL_METHODS: ReadonlySet<string>;
12
+ /**
13
+ * 由本地方法提供、需要在握手中声明的能力。
14
+ * scoreboard 的两个方法由 stdio.ts 单独分派(写入要转交守护进程),不在 LOCAL_METHODS 中,但同样不依赖守护进程版本。
15
+ */
16
+ export declare const LOCAL_CAPABILITIES: readonly ManagementCapability[];
17
+ //# sourceMappingURL=local-methods.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local-methods.d.ts","sourceRoot":"","sources":["../../src/management/local-methods.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EAAE,oBAAoB,EAAoB,MAAM,sBAAsB,CAAC;AAEnF,8CAA8C;AAC9C,eAAO,MAAM,aAAa,EAAE,WAAW,CAAC,MAAM,CAAmF,CAAC;AAElI;;;GAGG;AACH,eAAO,MAAM,kBAAkB,EAAE,SAAS,oBAAoB,EAA+B,CAAC"}
@@ -0,0 +1,7 @@
1
+ const LOCAL_METHODS = /* @__PURE__ */ new Set(["players.list", "activity.query", "activity.stats"]);
2
+ const LOCAL_CAPABILITIES = ["activity", "scoreboard"];
3
+ export {
4
+ LOCAL_CAPABILITIES,
5
+ LOCAL_METHODS
6
+ };
7
+ //# sourceMappingURL=local-methods.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/management/local-methods.ts"],
4
+ "sourcesContent": ["/**\n * local-methods.ts \u2014 \u7BA1\u7406\u901A\u9053\u5728 stdio \u8FDB\u7A0B\u5185\u76F4\u63A5\u4F5C\u7B54\u7684\u53EA\u8BFB\u65B9\u6CD5\n *\n * \u4F7F\u7528\u573A\u666F\uFF1Astdio.ts \u6536\u5230\u8FD9\u4E9B\u65B9\u6CD5\u65F6\u4E0D\u8F6C\u53D1\u7ED9\u5E38\u9A7B\u5B88\u62A4\u8FDB\u7A0B\uFF0C\u800C\u662F\u7528\u78C1\u76D8\u4E0A\u7684\u65B0\u4EE3\u7801\u8BFB\u53D6\u6570\u636E\u5E93\uFF0C\n * \u5E73\u53F0\u5347\u7EA7\u540E\u4E0D\u5FC5\u91CD\u542F\u4ECD\u5728\u6258\u7BA1\u670D\u52A1\u7684\u5B88\u62A4\u8FDB\u7A0B\u5373\u53EF\u4F7F\u7528\uFF1Bserver.ts \u63E1\u624B\u65F6\u58F0\u660E\u5BF9\u5E94\u80FD\u529B\u3002\n * \u5B88\u62A4\u8FDB\u7A0B\u63E1\u624B\u7ED3\u679C\u7531\u65E7\u4EE3\u7801\u751F\u6210\u65F6\uFF0Cstdio.ts \u4E5F\u4F1A\u8865\u4E0A LOCAL_CAPABILITIES\u3002\n * \u65B0\u589E\u6B64\u7C7B\u53EA\u8BFB\u65B9\u6CD5\u65F6\u5728\u8FD9\u91CC\u767B\u8BB0\uFF08OCP\uFF09\u3002\n */\nimport type { ManagementCapability, ManagementMethod } from \"@sfmc-bds/management\";\n\n/** \u5728 stdio \u8FDB\u7A0B\u5185\u76F4\u63A5\u5206\u6D3E\u7ED9 dispatchManagement \u7684\u65B9\u6CD5 */\nexport const LOCAL_METHODS: ReadonlySet<string> = new Set<ManagementMethod>([\"players.list\", \"activity.query\", \"activity.stats\"]);\n\n/**\n * \u7531\u672C\u5730\u65B9\u6CD5\u63D0\u4F9B\u3001\u9700\u8981\u5728\u63E1\u624B\u4E2D\u58F0\u660E\u7684\u80FD\u529B\u3002\n * scoreboard \u7684\u4E24\u4E2A\u65B9\u6CD5\u7531 stdio.ts \u5355\u72EC\u5206\u6D3E\uFF08\u5199\u5165\u8981\u8F6C\u4EA4\u5B88\u62A4\u8FDB\u7A0B\uFF09\uFF0C\u4E0D\u5728 LOCAL_METHODS \u4E2D\uFF0C\u4F46\u540C\u6837\u4E0D\u4F9D\u8D56\u5B88\u62A4\u8FDB\u7A0B\u7248\u672C\u3002\n */\nexport const LOCAL_CAPABILITIES: readonly ManagementCapability[] = [\"activity\", \"scoreboard\"];\n"],
5
+ "mappings": "AAWO,MAAM,gBAAqC,oBAAI,IAAsB,CAAC,gBAAgB,kBAAkB,gBAAgB,CAAC;AAMzH,MAAM,qBAAsD,CAAC,YAAY,YAAY;",
6
+ "names": []
7
+ }
@@ -1,4 +1,15 @@
1
1
  import type { MetricsResult } from "@sfmc-bds/management";
2
+ /**
3
+ * 与数据服务相同的配置读取:文件缺失时用默认端口和默认数据库相对路径。
4
+ * 使用场景:本文件读取运行指标;scoreboard.ts 读取计分板快照。
5
+ */
6
+ export declare function dbConfig(root: string): {
7
+ db_port?: number;
8
+ http_auth?: string;
9
+ dbDir?: string;
10
+ };
11
+ /** 请求数据服务失败是否因为服务未运行(连接被拒、超时等),而不是返回了错误。使用场景同 dbConfig。 */
12
+ export declare function offline(error: unknown): boolean;
2
13
  /**
3
14
  * 管理协议 metrics.read。
4
15
  * 落盘读取失败时保留数据服务返回的历史;两边都没有时沿用原来的空结果说明。
@@ -1 +1 @@
1
- {"version":3,"file":"metrics-read.d.ts","sourceRoot":"","sources":["../../src/management/metrics-read.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAiC1D;;;GAGG;AACH,wBAAsB,kBAAkB,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC,aAAa,CAAC,CA2ChF"}
1
+ {"version":3,"file":"metrics-read.d.ts","sourceRoot":"","sources":["../../src/management/metrics-read.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAG1D;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAW/F;AAaD,2DAA2D;AAC3D,wBAAgB,OAAO,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAG/C;AAED;;;GAGG;AACH,wBAAsB,kBAAkB,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC,aAAa,CAAC,CA2ChF"}
@@ -75,6 +75,8 @@ async function readRuntimeMetrics(params) {
75
75
  };
76
76
  }
77
77
  export {
78
+ dbConfig,
79
+ offline,
78
80
  readRuntimeMetrics
79
81
  };
80
82
  //# sourceMappingURL=metrics-read.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/management/metrics-read.ts"],
4
- "sourcesContent": ["/**\n * \u8BFB\u53D6\u8FD0\u884C\u6307\u6807\uFF1A\u5B9E\u65F6\u6570\u503C\u8D70\u6570\u636E\u670D\u52A1\uFF0C\u66F2\u7EBF\u8D70\u5DF2\u843D\u76D8\u7684 sqlite\u3002\n * \u4F7F\u7528\u573A\u666F\uFF1A\u684C\u9762\u7AEF\u300C\u8FD0\u884C\u6307\u6807\u300D\u3002\u6570\u636E\u670D\u52A1\u505C\u7740\u65F6\u4ECD\u8FD4\u56DE\u505C\u670D\u524D\u7684\u5386\u53F2\uFF0C\u4E0D\u628A\u6574\u9875\u53D8\u6210\u5931\u8D25\u3002\n */\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { clampMetricsSpan, readPersistedMetrics } from \"@sfmc-bds/db-server/metrics-store\";\nimport type { MetricsResult } from \"@sfmc-bds/management\";\nimport { getRoot } from \"../runtime.js\";\n\n/** \u4E0E\u6570\u636E\u670D\u52A1\u76F8\u540C\u7684\u914D\u7F6E\u8BFB\u53D6\uFF1A\u6587\u4EF6\u7F3A\u5931\u65F6\u7528\u9ED8\u8BA4\u7AEF\u53E3\u548C\u9ED8\u8BA4\u6570\u636E\u5E93\u76F8\u5BF9\u8DEF\u5F84\u3002 */\nfunction dbConfig(root: string): { db_port?: number; http_auth?: string; dbDir?: string } {\n try {\n const parsed = JSON.parse(fs.readFileSync(path.join(root, \"configs\", \"db_config.json\"), \"utf8\")) as { db_port?: unknown; http_auth?: unknown; dbDir?: unknown };\n return {\n ...(typeof parsed.db_port === \"number\" ? { db_port: parsed.db_port } : {}),\n ...(typeof parsed.http_auth === \"string\" ? { http_auth: parsed.http_auth } : {}),\n ...(typeof parsed.dbDir === \"string\" && parsed.dbDir.trim() ? { dbDir: parsed.dbDir } : {}),\n };\n } catch {\n return {};\n }\n}\n\n/** \u6307\u6807\u5E93\u4E0E\u4E1A\u52A1\u5E93\u540C\u76EE\u5F55\uFF0C\u6587\u4EF6\u540D\u4E0E\u6570\u636E\u670D\u52A1\u6253\u5F00\u7684 runtime-metrics.sqlite \u4E00\u81F4\u3002 */\nfunction metricsDatabasePath(root: string, dbDir: string | undefined): string {\n return path.join(path.dirname(path.resolve(root, dbDir ?? \"data/sfmc_data.db\")), \"runtime-metrics.sqlite\");\n}\n\nfunction spanOf(params: unknown): number {\n if (params === undefined) return clampMetricsSpan(undefined);\n if (!params || typeof params !== \"object\" || Array.isArray(params)) throw new Error(\"\u53C2\u6570\u5FC5\u987B\u4E3A\u5BF9\u8C61\");\n return clampMetricsSpan((params as { spanMs?: unknown }).spanMs);\n}\n\nfunction offline(error: unknown): boolean {\n const detail = error instanceof Error ? `${error.message} ${String(error.cause ?? \"\")}` : String(error);\n return /fetch failed|ECONNREFUSED|ENOTFOUND|AbortError|TimeoutError|timed out/i.test(detail);\n}\n\n/**\n * \u7BA1\u7406\u534F\u8BAE metrics.read\u3002\n * \u843D\u76D8\u8BFB\u53D6\u5931\u8D25\u65F6\u4FDD\u7559\u6570\u636E\u670D\u52A1\u8FD4\u56DE\u7684\u5386\u53F2\uFF1B\u4E24\u8FB9\u90FD\u6CA1\u6709\u65F6\u6CBF\u7528\u539F\u6765\u7684\u7A7A\u7ED3\u679C\u8BF4\u660E\u3002\n */\nexport async function readRuntimeMetrics(params: unknown): Promise<MetricsResult> {\n const spanMs = spanOf(params);\n const root = getRoot();\n const cfg = dbConfig(root);\n let live: MetricsResult | undefined;\n try {\n const response = await fetch(`http://127.0.0.1:${cfg.db_port ?? 3001}/api/sfmc/metrics?spanMs=${spanMs}`, {\n headers: cfg.http_auth ? { authorization: `Bearer ${cfg.http_auth}` } : {},\n signal: AbortSignal.timeout(10_000),\n });\n if (!response.ok) throw new Error(`\u8FD0\u884C\u6307\u6807\u8BFB\u53D6\u5931\u8D25 (${response.status})`);\n const body = await response.json() as MetricsResult;\n if (!body || typeof body !== \"object\" || !Array.isArray(body.history)) throw new Error(\"\u8FD0\u884C\u6307\u6807\u8BFB\u53D6\u5931\u8D25\");\n live = body;\n } catch (error) {\n if (!offline(error)) throw error;\n }\n let stored: ReturnType<typeof readPersistedMetrics> = null;\n try { stored = readPersistedMetrics(metricsDatabasePath(root, cfg.dbDir), Date.now(), spanMs); } catch { stored = null; }\n if (!live) {\n const history = stored?.history ?? [];\n const resourceHistory = stored?.resourceHistory ?? [];\n return {\n fresh: false,\n updatedAt: history.at(-1)?.recordedAt ?? null,\n current: null,\n history,\n host: null,\n processes: null,\n resourcesUpdatedAt: resourceHistory.at(-1)?.recordedAt ?? null,\n resourceHistory,\n note: history.length || resourceHistory.length ? \"\u6570\u636E\u670D\u52A1\u672A\u8FD0\u884C\uFF0C\u5B9E\u65F6\u6570\u503C\u4E0D\u53EF\u7528\" : \"\u6570\u636E\u670D\u52A1\u672A\u8FD0\u884C\uFF0C\u6682\u65F6\u6CA1\u6709\u8FD0\u884C\u6307\u6807\",\n };\n }\n const history = stored?.history ?? live.history;\n const resourceHistory = stored?.resourceHistory ?? live.resourceHistory;\n return {\n ...live,\n history,\n ...(resourceHistory ? { resourceHistory } : {}),\n updatedAt: live.updatedAt ?? history.at(-1)?.recordedAt ?? null,\n resourcesUpdatedAt: live.resourcesUpdatedAt ?? resourceHistory?.at(-1)?.recordedAt ?? null,\n };\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * \u8BFB\u53D6\u8FD0\u884C\u6307\u6807\uFF1A\u5B9E\u65F6\u6570\u503C\u8D70\u6570\u636E\u670D\u52A1\uFF0C\u66F2\u7EBF\u8D70\u5DF2\u843D\u76D8\u7684 sqlite\u3002\n * \u4F7F\u7528\u573A\u666F\uFF1A\u684C\u9762\u7AEF\u300C\u8FD0\u884C\u6307\u6807\u300D\u3002\u6570\u636E\u670D\u52A1\u505C\u7740\u65F6\u4ECD\u8FD4\u56DE\u505C\u670D\u524D\u7684\u5386\u53F2\uFF0C\u4E0D\u628A\u6574\u9875\u53D8\u6210\u5931\u8D25\u3002\n */\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { clampMetricsSpan, readPersistedMetrics } from \"@sfmc-bds/db-server/metrics-store\";\nimport type { MetricsResult } from \"@sfmc-bds/management\";\nimport { getRoot } from \"../runtime.js\";\n\n/**\n * \u4E0E\u6570\u636E\u670D\u52A1\u76F8\u540C\u7684\u914D\u7F6E\u8BFB\u53D6\uFF1A\u6587\u4EF6\u7F3A\u5931\u65F6\u7528\u9ED8\u8BA4\u7AEF\u53E3\u548C\u9ED8\u8BA4\u6570\u636E\u5E93\u76F8\u5BF9\u8DEF\u5F84\u3002\n * \u4F7F\u7528\u573A\u666F\uFF1A\u672C\u6587\u4EF6\u8BFB\u53D6\u8FD0\u884C\u6307\u6807\uFF1Bscoreboard.ts \u8BFB\u53D6\u8BA1\u5206\u677F\u5FEB\u7167\u3002\n */\nexport function dbConfig(root: string): { db_port?: number; http_auth?: string; dbDir?: string } {\n try {\n const parsed = JSON.parse(fs.readFileSync(path.join(root, \"configs\", \"db_config.json\"), \"utf8\")) as { db_port?: unknown; http_auth?: unknown; dbDir?: unknown };\n return {\n ...(typeof parsed.db_port === \"number\" ? { db_port: parsed.db_port } : {}),\n ...(typeof parsed.http_auth === \"string\" ? { http_auth: parsed.http_auth } : {}),\n ...(typeof parsed.dbDir === \"string\" && parsed.dbDir.trim() ? { dbDir: parsed.dbDir } : {}),\n };\n } catch {\n return {};\n }\n}\n\n/** \u6307\u6807\u5E93\u4E0E\u4E1A\u52A1\u5E93\u540C\u76EE\u5F55\uFF0C\u6587\u4EF6\u540D\u4E0E\u6570\u636E\u670D\u52A1\u6253\u5F00\u7684 runtime-metrics.sqlite \u4E00\u81F4\u3002 */\nfunction metricsDatabasePath(root: string, dbDir: string | undefined): string {\n return path.join(path.dirname(path.resolve(root, dbDir ?? \"data/sfmc_data.db\")), \"runtime-metrics.sqlite\");\n}\n\nfunction spanOf(params: unknown): number {\n if (params === undefined) return clampMetricsSpan(undefined);\n if (!params || typeof params !== \"object\" || Array.isArray(params)) throw new Error(\"\u53C2\u6570\u5FC5\u987B\u4E3A\u5BF9\u8C61\");\n return clampMetricsSpan((params as { spanMs?: unknown }).spanMs);\n}\n\n/** \u8BF7\u6C42\u6570\u636E\u670D\u52A1\u5931\u8D25\u662F\u5426\u56E0\u4E3A\u670D\u52A1\u672A\u8FD0\u884C\uFF08\u8FDE\u63A5\u88AB\u62D2\u3001\u8D85\u65F6\u7B49\uFF09\uFF0C\u800C\u4E0D\u662F\u8FD4\u56DE\u4E86\u9519\u8BEF\u3002\u4F7F\u7528\u573A\u666F\u540C dbConfig\u3002 */\nexport function offline(error: unknown): boolean {\n const detail = error instanceof Error ? `${error.message} ${String(error.cause ?? \"\")}` : String(error);\n return /fetch failed|ECONNREFUSED|ENOTFOUND|AbortError|TimeoutError|timed out/i.test(detail);\n}\n\n/**\n * \u7BA1\u7406\u534F\u8BAE metrics.read\u3002\n * \u843D\u76D8\u8BFB\u53D6\u5931\u8D25\u65F6\u4FDD\u7559\u6570\u636E\u670D\u52A1\u8FD4\u56DE\u7684\u5386\u53F2\uFF1B\u4E24\u8FB9\u90FD\u6CA1\u6709\u65F6\u6CBF\u7528\u539F\u6765\u7684\u7A7A\u7ED3\u679C\u8BF4\u660E\u3002\n */\nexport async function readRuntimeMetrics(params: unknown): Promise<MetricsResult> {\n const spanMs = spanOf(params);\n const root = getRoot();\n const cfg = dbConfig(root);\n let live: MetricsResult | undefined;\n try {\n const response = await fetch(`http://127.0.0.1:${cfg.db_port ?? 3001}/api/sfmc/metrics?spanMs=${spanMs}`, {\n headers: cfg.http_auth ? { authorization: `Bearer ${cfg.http_auth}` } : {},\n signal: AbortSignal.timeout(10_000),\n });\n if (!response.ok) throw new Error(`\u8FD0\u884C\u6307\u6807\u8BFB\u53D6\u5931\u8D25 (${response.status})`);\n const body = await response.json() as MetricsResult;\n if (!body || typeof body !== \"object\" || !Array.isArray(body.history)) throw new Error(\"\u8FD0\u884C\u6307\u6807\u8BFB\u53D6\u5931\u8D25\");\n live = body;\n } catch (error) {\n if (!offline(error)) throw error;\n }\n let stored: ReturnType<typeof readPersistedMetrics> = null;\n try { stored = readPersistedMetrics(metricsDatabasePath(root, cfg.dbDir), Date.now(), spanMs); } catch { stored = null; }\n if (!live) {\n const history = stored?.history ?? [];\n const resourceHistory = stored?.resourceHistory ?? [];\n return {\n fresh: false,\n updatedAt: history.at(-1)?.recordedAt ?? null,\n current: null,\n history,\n host: null,\n processes: null,\n resourcesUpdatedAt: resourceHistory.at(-1)?.recordedAt ?? null,\n resourceHistory,\n note: history.length || resourceHistory.length ? \"\u6570\u636E\u670D\u52A1\u672A\u8FD0\u884C\uFF0C\u5B9E\u65F6\u6570\u503C\u4E0D\u53EF\u7528\" : \"\u6570\u636E\u670D\u52A1\u672A\u8FD0\u884C\uFF0C\u6682\u65F6\u6CA1\u6709\u8FD0\u884C\u6307\u6807\",\n };\n }\n const history = stored?.history ?? live.history;\n const resourceHistory = stored?.resourceHistory ?? live.resourceHistory;\n return {\n ...live,\n history,\n ...(resourceHistory ? { resourceHistory } : {}),\n updatedAt: live.updatedAt ?? history.at(-1)?.recordedAt ?? null,\n resourcesUpdatedAt: live.resourcesUpdatedAt ?? resourceHistory?.at(-1)?.recordedAt ?? null,\n };\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["history", "resourceHistory"]
7
7
  }
@@ -0,0 +1,23 @@
1
+ /**
2
+ * scoreboard.ts — 管理协议 scoreboard.read / scoreboard.apply
3
+ *
4
+ * 使用场景:桌面端与小程序的「计分板」页。
5
+ * - 读取:从数据服务 GET /api/sfmc/scoreboard 取游戏内同步的快照。数据服务只在有人查看时才让游戏内脚本计算快照,
6
+ * 所以首次读取或带 after 参数时会短暂等待新快照(脚本未连接时不等待)。
7
+ * - 写入:按 @sfmc-bds/management 的规则逐条校验,转成 `scoreboard` 控制台命令,经注入的 send 写入 BDS 标准输入。
8
+ * stdio 会话把命令转发给守护进程的 services.send,守护进程内则直接写入托管 BDS 的标准输入(DIP)。
9
+ */
10
+ import { type ScoreboardApplyResult, type ScoreboardReadResult } from "@sfmc-bds/management";
11
+ /** 把一行命令发送到 BDS 控制台 */
12
+ export type ConsoleSender = (line: string) => Promise<void>;
13
+ /**
14
+ * 管理协议 scoreboard.read。
15
+ * 快照不新鲜、或早于 after 时,在脚本仍连接的前提下最多等待 READ_WAIT_MS;超时返回当时的快照(fresh 如实标注)。
16
+ */
17
+ export declare function readScoreboard(params: unknown): Promise<ScoreboardReadResult>;
18
+ /**
19
+ * 管理协议 scoreboard.apply:校验 → 按快照复核目标 → 逐条发送命令。
20
+ * 命令执行结果出现在控制台日志里,最新分数由之后的 scoreboard.read(after = sentAt)体现。
21
+ */
22
+ export declare function applyScoreboard(params: unknown, send: ConsoleSender): Promise<ScoreboardApplyResult>;
23
+ //# sourceMappingURL=scoreboard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scoreboard.d.ts","sourceRoot":"","sources":["../../src/management/scoreboard.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAKL,KAAK,qBAAqB,EAG1B,KAAK,oBAAoB,EAC1B,MAAM,sBAAsB,CAAC;AAU9B,uBAAuB;AACvB,MAAM,MAAM,aAAa,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AAuD5D;;;GAGG;AACH,wBAAsB,cAAc,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAUnF;AAuCD;;;GAGG;AACH,wBAAsB,eAAe,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAM1G"}
@@ -0,0 +1,107 @@
1
+ import {
2
+ SCOREBOARD_APPLY_MAX,
3
+ scoreboardCommand,
4
+ scoreboardOperationError,
5
+ scoreboardTargetBlock
6
+ } from "@sfmc-bds/management";
7
+ import { getRoot } from "../runtime.js";
8
+ import { dbConfig, offline } from "./metrics-read.js";
9
+ const READ_WAIT_MS = 6e3;
10
+ const READ_POLL_MS = 400;
11
+ async function fetchView() {
12
+ const cfg = dbConfig(getRoot());
13
+ try {
14
+ const response = await fetch(`http://127.0.0.1:${cfg.db_port ?? 3001}/api/sfmc/scoreboard`, {
15
+ headers: cfg.http_auth ? { authorization: `Bearer ${cfg.http_auth}` } : {},
16
+ signal: AbortSignal.timeout(5e3)
17
+ });
18
+ if (!response.ok) throw new Error(`\u8BA1\u5206\u677F\u8BFB\u53D6\u5931\u8D25 (${response.status})`);
19
+ const body = await response.json();
20
+ if (!body || typeof body !== "object" || !Array.isArray(body.objectives)) throw new Error("\u8BA1\u5206\u677F\u8BFB\u53D6\u5931\u8D25");
21
+ return body;
22
+ } catch (error) {
23
+ if (offline(error)) return null;
24
+ throw error;
25
+ }
26
+ }
27
+ function toResult(view) {
28
+ const result = {
29
+ available: view.available,
30
+ fresh: view.fresh,
31
+ updatedAt: view.updatedAt,
32
+ objectives: view.objectives,
33
+ displaySlots: view.displaySlots,
34
+ truncated: view.truncated
35
+ };
36
+ if (view.note) result.note = view.note;
37
+ return result;
38
+ }
39
+ const OFFLINE_RESULT = {
40
+ available: false,
41
+ fresh: false,
42
+ updatedAt: null,
43
+ objectives: [],
44
+ displaySlots: [],
45
+ truncated: false,
46
+ note: "\u6570\u636E\u670D\u52A1\u672A\u8FD0\u884C\uFF0C\u65E0\u6CD5\u8BFB\u53D6\u8BA1\u5206\u677F"
47
+ };
48
+ function afterOf(params) {
49
+ if (params === void 0 || params === null) return void 0;
50
+ if (typeof params !== "object" || Array.isArray(params)) throw new Error("\u53C2\u6570\u5FC5\u987B\u4E3A\u5BF9\u8C61");
51
+ const after = params.after;
52
+ if (after === void 0) return void 0;
53
+ if (typeof after !== "number" || !Number.isFinite(after) || after < 0) throw new Error("after \u5FC5\u987B\u4E3A\u6BEB\u79D2\u65F6\u95F4\u6233");
54
+ return after;
55
+ }
56
+ async function readScoreboard(params) {
57
+ const after = afterOf(params);
58
+ const deadline = Date.now() + READ_WAIT_MS;
59
+ for (; ; ) {
60
+ const view = await fetchView();
61
+ if (!view) return OFFLINE_RESULT;
62
+ const current = view.fresh && (after === void 0 || (view.updatedAt ?? 0) > after);
63
+ if (current || !view.scriptConnected || Date.now() + READ_POLL_MS > deadline) return toResult(view);
64
+ await new Promise((resolve) => setTimeout(resolve, READ_POLL_MS));
65
+ }
66
+ }
67
+ function operationsOf(params) {
68
+ if (!params || typeof params !== "object" || Array.isArray(params)) throw new Error("\u53C2\u6570\u5FC5\u987B\u4E3A\u5BF9\u8C61");
69
+ const operations = params.operations;
70
+ if (!Array.isArray(operations) || !operations.length) throw new Error("\u8BF7\u63D0\u4F9B\u81F3\u5C11\u4E00\u6761\u8BA1\u5206\u677F\u64CD\u4F5C");
71
+ if (operations.length > SCOREBOARD_APPLY_MAX) throw new Error(`\u4E00\u6B21\u6700\u591A\u63D0\u4EA4 ${SCOREBOARD_APPLY_MAX} \u6761\u8BA1\u5206\u677F\u64CD\u4F5C`);
72
+ operations.forEach((operation, index) => {
73
+ const error = scoreboardOperationError(operation);
74
+ if (error) throw new Error(operations.length > 1 ? `\u7B2C ${index + 1} \u6761\u64CD\u4F5C\uFF1A${error}` : error);
75
+ });
76
+ return operations;
77
+ }
78
+ function checkTargets(operations, view) {
79
+ const scoreOps = operations.filter((operation) => operation.op.startsWith("score."));
80
+ if (!scoreOps.length) return;
81
+ if (!view?.available) throw new Error("\u6682\u65F6\u8BFB\u4E0D\u5230\u8BA1\u5206\u677F\u5FEB\u7167\uFF0C\u65E0\u6CD5\u786E\u8BA4\u53C2\u4E0E\u8005\u72B6\u6001\uFF0C\u8BF7\u786E\u8BA4 BDS \u6B63\u5728\u8FD0\u884C\u540E\u91CD\u8BD5");
82
+ const participants = /* @__PURE__ */ new Map();
83
+ for (const objective of view.objectives) for (const row of objective.participants) participants.set(row.id, row);
84
+ for (const operation of scoreOps) {
85
+ if (!("target" in operation)) continue;
86
+ const known = operation.participantId !== void 0 ? participants.get(operation.participantId) : void 0;
87
+ if (known) {
88
+ const block = scoreboardTargetBlock(known);
89
+ if (block) throw new Error(`${known.name}\uFF1A${block}`);
90
+ continue;
91
+ }
92
+ const offlineSameName = [...participants.values()].find((row) => row.type === "player" && !row.online && row.name === operation.target);
93
+ if (offlineSameName) throw new Error(`${operation.target} \u662F\u79BB\u7EBF\u73A9\u5BB6\uFF0C\u547D\u4EE4\u4F1A\u521B\u5EFA\u540C\u540D\u865A\u62DF\u73A9\u5BB6\u800C\u4E0D\u662F\u4FEE\u6539\u8BE5\u73A9\u5BB6\uFF0C\u8BF7\u7B49\u73A9\u5BB6\u4E0A\u7EBF\u540E\u518D\u4FEE\u6539`);
94
+ }
95
+ }
96
+ async function applyScoreboard(params, send) {
97
+ const operations = operationsOf(params);
98
+ checkTargets(operations, operations.some((operation) => operation.op.startsWith("score.")) ? await fetchView() : null);
99
+ const commands = operations.map(scoreboardCommand);
100
+ for (const command of commands) await send(command);
101
+ return { commands, sentAt: Date.now() };
102
+ }
103
+ export {
104
+ applyScoreboard,
105
+ readScoreboard
106
+ };
107
+ //# sourceMappingURL=scoreboard.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/management/scoreboard.ts"],
4
+ "sourcesContent": ["/**\n * scoreboard.ts \u2014 \u7BA1\u7406\u534F\u8BAE scoreboard.read / scoreboard.apply\n *\n * \u4F7F\u7528\u573A\u666F\uFF1A\u684C\u9762\u7AEF\u4E0E\u5C0F\u7A0B\u5E8F\u7684\u300C\u8BA1\u5206\u677F\u300D\u9875\u3002\n * - \u8BFB\u53D6\uFF1A\u4ECE\u6570\u636E\u670D\u52A1 GET /api/sfmc/scoreboard \u53D6\u6E38\u620F\u5185\u540C\u6B65\u7684\u5FEB\u7167\u3002\u6570\u636E\u670D\u52A1\u53EA\u5728\u6709\u4EBA\u67E5\u770B\u65F6\u624D\u8BA9\u6E38\u620F\u5185\u811A\u672C\u8BA1\u7B97\u5FEB\u7167\uFF0C\n * \u6240\u4EE5\u9996\u6B21\u8BFB\u53D6\u6216\u5E26 after \u53C2\u6570\u65F6\u4F1A\u77ED\u6682\u7B49\u5F85\u65B0\u5FEB\u7167\uFF08\u811A\u672C\u672A\u8FDE\u63A5\u65F6\u4E0D\u7B49\u5F85\uFF09\u3002\n * - \u5199\u5165\uFF1A\u6309 @sfmc-bds/management \u7684\u89C4\u5219\u9010\u6761\u6821\u9A8C\uFF0C\u8F6C\u6210 `scoreboard` \u63A7\u5236\u53F0\u547D\u4EE4\uFF0C\u7ECF\u6CE8\u5165\u7684 send \u5199\u5165 BDS \u6807\u51C6\u8F93\u5165\u3002\n * stdio \u4F1A\u8BDD\u628A\u547D\u4EE4\u8F6C\u53D1\u7ED9\u5B88\u62A4\u8FDB\u7A0B\u7684 services.send\uFF0C\u5B88\u62A4\u8FDB\u7A0B\u5185\u5219\u76F4\u63A5\u5199\u5165\u6258\u7BA1 BDS \u7684\u6807\u51C6\u8F93\u5165\uFF08DIP\uFF09\u3002\n */\nimport {\n SCOREBOARD_APPLY_MAX,\n scoreboardCommand,\n scoreboardOperationError,\n scoreboardTargetBlock,\n type ScoreboardApplyResult,\n type ScoreboardOperation,\n type ScoreboardParticipant,\n type ScoreboardReadResult,\n} from \"@sfmc-bds/management\";\nimport type { ScoreboardReadView } from \"@sfmc-bds/db-server/scoreboard\";\nimport { getRoot } from \"../runtime.js\";\nimport { dbConfig, offline } from \"./metrics-read.js\";\n\n/** \u7B49\u5F85\u65B0\u5FEB\u7167\u7684\u6700\u957F\u65F6\u95F4\uFF1A\u8986\u76D6\u811A\u672C\u5F97\u77E5\u6709\u4EBA\u67E5\u770B\u540E\u7684\u9996\u6B21\u8BA1\u7B97\u4E0E\u4E00\u6B21\u4E0A\u62A5\u5468\u671F */\nconst READ_WAIT_MS = 6_000;\n/** \u7B49\u5F85\u671F\u95F4\u91CD\u65B0\u8BFB\u53D6\u7684\u95F4\u9694 */\nconst READ_POLL_MS = 400;\n\n/** \u628A\u4E00\u884C\u547D\u4EE4\u53D1\u9001\u5230 BDS \u63A7\u5236\u53F0 */\nexport type ConsoleSender = (line: string) => Promise<void>;\n\n/** \u5355\u6B21\u8BFB\u53D6\u6570\u636E\u670D\u52A1\u4E2D\u7684\u5FEB\u7167\uFF1B\u6570\u636E\u670D\u52A1\u672A\u8FD0\u884C\u65F6\u8FD4\u56DE null */\nasync function fetchView(): Promise<ScoreboardReadView | null> {\n const cfg = dbConfig(getRoot());\n try {\n const response = await fetch(`http://127.0.0.1:${cfg.db_port ?? 3001}/api/sfmc/scoreboard`, {\n headers: cfg.http_auth ? { authorization: `Bearer ${cfg.http_auth}` } : {},\n signal: AbortSignal.timeout(5_000),\n });\n if (!response.ok) throw new Error(`\u8BA1\u5206\u677F\u8BFB\u53D6\u5931\u8D25 (${response.status})`);\n const body = (await response.json()) as ScoreboardReadView;\n if (!body || typeof body !== \"object\" || !Array.isArray(body.objectives)) throw new Error(\"\u8BA1\u5206\u677F\u8BFB\u53D6\u5931\u8D25\");\n return body;\n } catch (error) {\n if (offline(error)) return null;\n throw error;\n }\n}\n\n/** \u6570\u636E\u670D\u52A1\u5185\u90E8\u89C6\u56FE \u2192 \u534F\u8BAE\u7ED3\u679C\uFF08\u53BB\u6389 scriptConnected \u7B49\u5185\u90E8\u5B57\u6BB5\uFF09 */\nfunction toResult(view: ScoreboardReadView): ScoreboardReadResult {\n const result: ScoreboardReadResult = {\n available: view.available,\n fresh: view.fresh,\n updatedAt: view.updatedAt,\n objectives: view.objectives,\n displaySlots: view.displaySlots,\n truncated: view.truncated,\n };\n if (view.note) result.note = view.note;\n return result;\n}\n\n/** \u6570\u636E\u670D\u52A1\u672A\u8FD0\u884C\u65F6\u7684\u7ED3\u679C */\nconst OFFLINE_RESULT: ScoreboardReadResult = {\n available: false,\n fresh: false,\n updatedAt: null,\n objectives: [],\n displaySlots: [],\n truncated: false,\n note: \"\u6570\u636E\u670D\u52A1\u672A\u8FD0\u884C\uFF0C\u65E0\u6CD5\u8BFB\u53D6\u8BA1\u5206\u677F\",\n};\n\n/** \u89E3\u6790 scoreboard.read \u7684 after \u53C2\u6570 */\nfunction afterOf(params: unknown): number | undefined {\n if (params === undefined || params === null) return undefined;\n if (typeof params !== \"object\" || Array.isArray(params)) throw new Error(\"\u53C2\u6570\u5FC5\u987B\u4E3A\u5BF9\u8C61\");\n const after = (params as { after?: unknown }).after;\n if (after === undefined) return undefined;\n if (typeof after !== \"number\" || !Number.isFinite(after) || after < 0) throw new Error(\"after \u5FC5\u987B\u4E3A\u6BEB\u79D2\u65F6\u95F4\u6233\");\n return after;\n}\n\n/**\n * \u7BA1\u7406\u534F\u8BAE scoreboard.read\u3002\n * \u5FEB\u7167\u4E0D\u65B0\u9C9C\u3001\u6216\u65E9\u4E8E after \u65F6\uFF0C\u5728\u811A\u672C\u4ECD\u8FDE\u63A5\u7684\u524D\u63D0\u4E0B\u6700\u591A\u7B49\u5F85 READ_WAIT_MS\uFF1B\u8D85\u65F6\u8FD4\u56DE\u5F53\u65F6\u7684\u5FEB\u7167\uFF08fresh \u5982\u5B9E\u6807\u6CE8\uFF09\u3002\n */\nexport async function readScoreboard(params: unknown): Promise<ScoreboardReadResult> {\n const after = afterOf(params);\n const deadline = Date.now() + READ_WAIT_MS;\n for (;;) {\n const view = await fetchView();\n if (!view) return OFFLINE_RESULT;\n const current = view.fresh && (after === undefined || (view.updatedAt ?? 0) > after);\n if (current || !view.scriptConnected || Date.now() + READ_POLL_MS > deadline) return toResult(view);\n await new Promise((resolve) => setTimeout(resolve, READ_POLL_MS));\n }\n}\n\n/** \u89E3\u6790\u5E76\u9010\u6761\u6821\u9A8C scoreboard.apply \u7684\u64CD\u4F5C\u5217\u8868 */\nfunction operationsOf(params: unknown): ScoreboardOperation[] {\n if (!params || typeof params !== \"object\" || Array.isArray(params)) throw new Error(\"\u53C2\u6570\u5FC5\u987B\u4E3A\u5BF9\u8C61\");\n const operations = (params as { operations?: unknown }).operations;\n if (!Array.isArray(operations) || !operations.length) throw new Error(\"\u8BF7\u63D0\u4F9B\u81F3\u5C11\u4E00\u6761\u8BA1\u5206\u677F\u64CD\u4F5C\");\n if (operations.length > SCOREBOARD_APPLY_MAX) throw new Error(`\u4E00\u6B21\u6700\u591A\u63D0\u4EA4 ${SCOREBOARD_APPLY_MAX} \u6761\u8BA1\u5206\u677F\u64CD\u4F5C`);\n operations.forEach((operation, index) => {\n const error = scoreboardOperationError(operation);\n if (error) throw new Error(operations.length > 1 ? `\u7B2C ${index + 1} \u6761\u64CD\u4F5C\uFF1A${error}` : error);\n });\n return operations as ScoreboardOperation[];\n}\n\n/**\n * \u6309\u6700\u65B0\u5FEB\u7167\u590D\u6838\u5206\u6570\u64CD\u4F5C\u7684\u76EE\u6807\uFF08\u6743\u5A01\u6821\u9A8C\uFF0C\u4E0E\u754C\u9762\u7981\u7528\u89C4\u5219\u540C\u6E90\uFF09\uFF1A\n * - \u5E26 participantId \u7684\u5DF2\u6709\u53C2\u4E0E\u8005\uFF1A\u5FC5\u987B\u4ECD\u53EF\u7ECF\u547D\u4EE4\u5B9A\u4F4D\uFF08scoreboardTargetBlock\uFF09\uFF1B\n * - \u65B0\u540D\u79F0\uFF1A\u82E5\u4E0E\u79BB\u7EBF\u73A9\u5BB6\u540C\u540D\uFF0C\u547D\u4EE4\u4F1A\u521B\u5EFA\u540C\u540D\u865A\u62DF\u73A9\u5BB6\u800C\u4E0D\u662F\u4FEE\u6539\u8BE5\u73A9\u5BB6\uFF0C\u62D2\u7EDD\u3002\n */\nfunction checkTargets(operations: ScoreboardOperation[], view: ScoreboardReadView | null): void {\n const scoreOps = operations.filter((operation) => operation.op.startsWith(\"score.\"));\n if (!scoreOps.length) return;\n if (!view?.available) throw new Error(\"\u6682\u65F6\u8BFB\u4E0D\u5230\u8BA1\u5206\u677F\u5FEB\u7167\uFF0C\u65E0\u6CD5\u786E\u8BA4\u53C2\u4E0E\u8005\u72B6\u6001\uFF0C\u8BF7\u786E\u8BA4 BDS \u6B63\u5728\u8FD0\u884C\u540E\u91CD\u8BD5\");\n const participants = new Map<number, ScoreboardParticipant>();\n for (const objective of view.objectives) for (const row of objective.participants) participants.set(row.id, row);\n for (const operation of scoreOps) {\n if (!(\"target\" in operation)) continue;\n const known = operation.participantId !== undefined ? participants.get(operation.participantId) : undefined;\n if (known) {\n const block = scoreboardTargetBlock(known);\n if (block) throw new Error(`${known.name}\uFF1A${block}`);\n continue;\n }\n const offlineSameName = [...participants.values()].find((row) => row.type === \"player\" && !row.online && row.name === operation.target);\n if (offlineSameName) throw new Error(`${operation.target} \u662F\u79BB\u7EBF\u73A9\u5BB6\uFF0C\u547D\u4EE4\u4F1A\u521B\u5EFA\u540C\u540D\u865A\u62DF\u73A9\u5BB6\u800C\u4E0D\u662F\u4FEE\u6539\u8BE5\u73A9\u5BB6\uFF0C\u8BF7\u7B49\u73A9\u5BB6\u4E0A\u7EBF\u540E\u518D\u4FEE\u6539`);\n }\n}\n\n/**\n * \u7BA1\u7406\u534F\u8BAE scoreboard.apply\uFF1A\u6821\u9A8C \u2192 \u6309\u5FEB\u7167\u590D\u6838\u76EE\u6807 \u2192 \u9010\u6761\u53D1\u9001\u547D\u4EE4\u3002\n * \u547D\u4EE4\u6267\u884C\u7ED3\u679C\u51FA\u73B0\u5728\u63A7\u5236\u53F0\u65E5\u5FD7\u91CC\uFF0C\u6700\u65B0\u5206\u6570\u7531\u4E4B\u540E\u7684 scoreboard.read\uFF08after = sentAt\uFF09\u4F53\u73B0\u3002\n */\nexport async function applyScoreboard(params: unknown, send: ConsoleSender): Promise<ScoreboardApplyResult> {\n const operations = operationsOf(params);\n checkTargets(operations, operations.some((operation) => operation.op.startsWith(\"score.\")) ? await fetchView() : null);\n const commands = operations.map(scoreboardCommand);\n for (const command of commands) await send(command);\n return { commands, sentAt: Date.now() };\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/management/server.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAA6C,KAAK,iBAAiB,EAAE,KAAK,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAO/H,OAAO,EAAE,SAAS,EAAgC,MAAM,YAAY,CAAC;AAsBrE,wBAAgB,eAAe,cAQ9B;AACD,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,IAAI,2BAA+E;AA4C3J,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,OAAO,CAAC,CAuNrF"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/management/server.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAA6C,KAAK,iBAAiB,EAAE,KAAK,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAQ/H,OAAO,EAAE,SAAS,EAAgC,MAAM,YAAY,CAAC;AAwBrE,wBAAgB,eAAe,cAQ9B;AACD,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,IAAI,2BAA+E;AA+D3J,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,OAAO,CAAC,CAyNrF"}
@@ -4,6 +4,7 @@ import os from "node:os";
4
4
  import { EventEmitter } from "node:events";
5
5
  import { LOG_TAIL_MAX, MANAGEMENT_PROTOCOL_VERSION } from "@sfmc-bds/management";
6
6
  import { readQqBindings } from "@sfmc-bds/db-server/qq-bindings";
7
+ import { parseActivityFilter, parseActivityPaging, readActivityPage, readActivityStats } from "@sfmc-bds/db-server/activity-log";
7
8
  import { ROOT, isRuntimeInitialized, spawnService } from "../runtime.js";
8
9
  import { queryServicesRuntimeLocal, services, START_ORDER, SERVICE_NAMES, refreshServices, onServiceStateChange } from "../services.js";
9
10
  import { readDiskLogs, deleteStoredLogs, onLog } from "../logs.js";
@@ -19,6 +20,8 @@ import { withMaintenanceLock } from "@sfmc-bds/management/node";
19
20
  import { deploymentPreflight, deploymentPort } from "./deployment.js";
20
21
  import { resolveBdsContext } from "../pack-lifecycle.js";
21
22
  import { readRuntimeMetrics } from "./metrics-read.js";
23
+ import { applyScoreboard, readScoreboard } from "./scoreboard.js";
24
+ import { LOCAL_CAPABILITIES } from "./local-methods.js";
22
25
  import { importPacks, planPackImport, readImportFilenames } from "./pack-import.js";
23
26
  const events = new EventEmitter();
24
27
  function deploymentInitialized() {
@@ -67,11 +70,17 @@ async function rebuildModules() {
67
70
  if (!deploy.ok) throw new Error(deploy.message);
68
71
  return { changed: true };
69
72
  }
73
+ function dbConfig() {
74
+ return readJson(path.join(ROOT, "configs", "db_config.json"), {});
75
+ }
76
+ function businessDatabase(cfg = dbConfig()) {
77
+ return path.resolve(ROOT, typeof cfg.dbDir === "string" && cfg.dbDir.trim() ? cfg.dbDir : "data/sfmc_data.db");
78
+ }
70
79
  async function players() {
71
80
  const files = playerFiles();
72
81
  const allowlist = readJson(files.allowlist, []);
73
- const cfg = readJson(path.join(ROOT, "configs", "db_config.json"), {});
74
- const database = path.resolve(ROOT, typeof cfg.dbDir === "string" && cfg.dbDir.trim() ? cfg.dbDir : "data/sfmc_data.db");
82
+ const cfg = dbConfig();
83
+ const database = businessDatabase(cfg);
75
84
  let data = {};
76
85
  try {
77
86
  const response = await fetch(`http://127.0.0.1:${cfg.db_port ?? 3001}/api/sfmc/status`, { headers: cfg.http_auth ? { authorization: `Bearer ${cfg.http_auth}` } : {}, signal: AbortSignal.timeout(5e3) });
@@ -81,6 +90,14 @@ async function players() {
81
90
  const fresh = typeof data.updatedAt === "number" && Date.now() - data.updatedAt < 6e4;
82
91
  return { players: (data.online ?? []).map((row) => ({ name: row.name, xuid: "", online: fresh ? true : null })), updatedAt: data.updatedAt ? new Date(data.updatedAt).toISOString() : "", fresh, allowlist, permissions: readJson(files.permissions, []), sfmcPermissions: readJson(files.sfmcPermissions, []), bindings: readQqBindings(database) };
83
92
  }
93
+ async function sendServiceLine(name, message) {
94
+ if (/[\r\n]/.test(message) || !message.trim()) throw new Error("\u4E00\u6B21\u53EA\u80FD\u53D1\u9001\u4E00\u884C\u547D\u4EE4");
95
+ const target = services[name];
96
+ if (!target.proc?.stdin || !target.running) throw new Error("\u670D\u52A1\u672A\u6258\u7BA1\u6216\u6CA1\u6709\u547D\u4EE4\u8F93\u5165\u901A\u9053");
97
+ await withMaintenanceLock(ROOT, async () => {
98
+ target.proc.stdin.write(message + "\n");
99
+ });
100
+ }
84
101
  async function bdsUpdate(context, checkOnly = false) {
85
102
  context.phase("download", checkOnly ? "\u68C0\u67E5 BDS \u66F4\u65B0" : "\u66F4\u65B0 BDS");
86
103
  const args = checkOnly ? ["--check-only", "--no-notify"] : ["--no-start", "--no-notify"];
@@ -100,7 +117,7 @@ async function dispatchManagement(request) {
100
117
  const store = managementTasks();
101
118
  switch (request.method) {
102
119
  case "handshake":
103
- return { protocolVersion: MANAGEMENT_PROTOCOL_VERSION, platformVersion: platformVersion(), host: { os: process.platform === "win32" ? "windows" : process.platform, arch: process.arch, release: os.release() }, root: ROOT, capabilities: ["services", "logs", "logs-range", "modules", "config", "packs", "players", "updates", "operations", "metrics", "manual-restart", "manual-backup", "pack-import-plan", "pack-icons", "pack-uninstall", "backup-delete", "pack-import-batch", "pack-version"], daemonPid: process.pid, daemonStartedAt: new Date(Date.now() - process.uptime() * 1e3).toISOString(), initialized: deploymentInitialized() };
120
+ return { protocolVersion: MANAGEMENT_PROTOCOL_VERSION, platformVersion: platformVersion(), host: { os: process.platform === "win32" ? "windows" : process.platform, arch: process.arch, release: os.release() }, root: ROOT, capabilities: ["services", "logs", "logs-range", "modules", "config", "packs", "players", "updates", "operations", "metrics", "manual-restart", "manual-backup", "pack-import-plan", "pack-icons", "pack-uninstall", "backup-delete", "pack-import-batch", "pack-version", ...LOCAL_CAPABILITIES], daemonPid: process.pid, daemonStartedAt: new Date(Date.now() - process.uptime() * 1e3).toISOString(), initialized: deploymentInitialized() };
104
121
  case "events.subscribe":
105
122
  return { subscribed: true };
106
123
  case "services.list":
@@ -138,15 +155,8 @@ async function dispatchManagement(request) {
138
155
  });
139
156
  }
140
157
  case "services.send": {
141
- const name = service(p.name);
142
- const message = string(p.message, "\u547D\u4EE4");
143
- if (/[\r\n]/.test(message) || !message.trim()) throw new Error("\u4E00\u6B21\u53EA\u80FD\u53D1\u9001\u4E00\u884C\u547D\u4EE4");
144
- const target = services[name];
145
- if (!target.proc?.stdin || !target.running) throw new Error("\u670D\u52A1\u672A\u6258\u7BA1\u6216\u6CA1\u6709\u547D\u4EE4\u8F93\u5165\u901A\u9053");
146
- return withMaintenanceLock(ROOT, async () => {
147
- target.proc.stdin.write(message + "\n");
148
- return { delivered: true };
149
- });
158
+ await sendServiceLine(service(p.name), string(p.message, "\u547D\u4EE4"));
159
+ return { delivered: true };
150
160
  }
151
161
  case "logs.tail": {
152
162
  const since = timeBound(p.since, "\u5F00\u59CB\u65F6\u95F4");
@@ -289,6 +299,14 @@ async function dispatchManagement(request) {
289
299
  return players();
290
300
  case "metrics.read":
291
301
  return readRuntimeMetrics(request.params);
302
+ case "scoreboard.read":
303
+ return readScoreboard(request.params);
304
+ case "scoreboard.apply":
305
+ return applyScoreboard(request.params, (line) => sendServiceLine("bds", line));
306
+ case "activity.query":
307
+ return readActivityPage(businessDatabase(), parseActivityFilter(p), parseActivityPaging(p));
308
+ case "activity.stats":
309
+ return readActivityStats(businessDatabase(), parseActivityFilter(p));
292
310
  case "players.apply":
293
311
  return store.submit(request.method, (context) => withStoppedServices(context, [...START_ORDER], async () => savePlayerPermissions(string(p.kind, "\u6743\u9650\u7C7B\u578B"), p.entries)));
294
312
  case "attachment.plan":
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/management/server.ts"],
4
- "sourcesContent": ["import fs from \"node:fs\";\nimport path from \"node:path\";\nimport os from \"node:os\";\nimport { EventEmitter } from \"node:events\";\nimport { LOG_TAIL_MAX, MANAGEMENT_PROTOCOL_VERSION, type ManagementRequest, type ManagementEvent } from \"@sfmc-bds/management\";\nimport { readQqBindings } from \"@sfmc-bds/db-server/qq-bindings\";\nimport { ROOT, isRuntimeInitialized, spawnService } from \"../runtime.js\";\nimport { queryServicesRuntimeLocal, services, START_ORDER, SERVICE_NAMES, refreshServices, onServiceStateChange, type ServiceName } from \"../services.js\";\nimport { readDiskLogs, deleteStoredLogs, onLog } from \"../logs.js\";\nimport { cmdModuleEnable, cmdModuleDisable } from \"../module-commands.js\";\nimport { ensureCoreConfigs } from \"@sfmc-bds/sdk/node/config\";\nimport { TaskStore, atomicJson, type TaskContext } from \"./tasks.js\";\nimport { configFiles, readDocument, revision, saveDocument, validateDocument } from \"./config.js\";\nimport { listModules, searchModules, identifier, runFetch, readJson, listPacks, togglePack, readPackIcon, uninstallPack, setPackVersion, playerFiles, savePlayerPermissions, modulePlan, applyModulePlan, moduleInstallBlock } from \"./domain.js\";\nimport { attachmentPlan, platformVersion, withStoppedServices, launchPlatformUpdate, createBackup, restoreSnapshot, deleteSnapshot, verifyRunning } from \"./maintenance.js\";\nimport { startupPlan } from \"./startup.js\";\nimport { cmdPackBuild, cmdPackDeploy } from \"../pack-lifecycle.js\";\nimport { withMaintenanceLock } from \"@sfmc-bds/management/node\";\nimport { deploymentPreflight, deploymentPort } from \"./deployment.js\";\nimport { resolveBdsContext } from \"../pack-lifecycle.js\";\nimport { readRuntimeMetrics } from \"./metrics-read.js\";\n\nimport { importPacks, planPackImport, readImportFilenames } from \"./pack-import.js\";\n\nconst events = new EventEmitter();\n/** \u7A7A\u76EE\u5F55\u4E5F\u8981\u80FD\u5B8C\u6210\u63E1\u624B\uFF0C\u4F9B\u684C\u9762\u521D\u59CB\u5316\u5411\u5BFC\u7EE7\u7EED\uFF1B\u65E7\u90E8\u7F72\u4ECD\u8BC6\u522B\u5DF2\u6709 BDS\u3002 */\nfunction deploymentInitialized(): boolean {\n if (isRuntimeInitialized()) return true;\n const config = readJson<{ bds_path?: string }>(path.join(ROOT, \"configs\", \"bds_updater.json\"), {});\n if (!config.bds_path) return false;\n return fs.existsSync(path.join(resolveBdsContext().bdsRoot, process.platform === \"win32\" ? \"bedrock_server.exe\" : \"bedrock_server\"));\n}\nlet tasks: TaskStore | undefined;\nexport function managementTasks() {\n if (!tasks) {\n tasks = new TaskStore(ROOT);\n tasks.on(\"operation\", payload => events.emit(\"event\", { type: \"event\", event: \"operation\", instanceId: ROOT, payload }));\n onLog(log => events.emit(\"event\", { type: \"event\", event: \"log\", instanceId: ROOT, payload: { ...log, time: log.time.toISOString() } }));\n onServiceStateChange(payload => events.emit(\"event\", { type: \"event\", event: \"serviceState\", instanceId: ROOT, payload }));\n }\n return tasks;\n}\nexport function onManagementEvent(callback: (event: ManagementEvent) => void) { events.on(\"event\", callback); return () => events.off(\"event\", callback); }\nfunction params(request: ManagementRequest): Record<string, unknown> {\n if (request.params === undefined) return {};\n if (!request.params || typeof request.params !== \"object\" || Array.isArray(request.params)) throw new Error(\"\u53C2\u6570\u5FC5\u987B\u4E3A\u5BF9\u8C61\");\n return request.params as Record<string, unknown>;\n}\nfunction string(value: unknown, label: string) { if (typeof value !== \"string\" || value.length > 2 * 1024 * 1024) throw new Error(`\u975E\u6CD5 ${label}`); return value; }\n/** \u89E3\u6790\u65E5\u5FD7\u67E5\u8BE2\u7528\u7684 ISO \u65F6\u95F4\u3002\u7F3A\u7701\u8FD4\u56DE undefined\u3002 */\nfunction timeBound(value: unknown, label: string): Date | undefined {\n if (value === undefined) return undefined;\n const date = new Date(string(value, label));\n if (Number.isNaN(date.getTime())) throw new Error(`\u975E\u6CD5 ${label}`);\n return date;\n}\nfunction service(value: unknown): ServiceName { if (!SERVICE_NAMES.includes(value as ServiceName)) throw new Error(\"\u672A\u77E5\u670D\u52A1\"); return value as ServiceName; }\nasync function rebuildModules() {\n const build = await cmdPackBuild([]); if (!build.ok) throw new Error(build.message);\n const deploy = await cmdPackDeploy([]); if (!deploy.ok) throw new Error(deploy.message);\n return { changed: true };\n}\n\nasync function players() {\n const files = playerFiles(); const allowlist = readJson<unknown[]>(files.allowlist, []);\n const cfg = readJson<{ db_port?: number; http_auth?: string; dbDir?: string }>(path.join(ROOT, \"configs\", \"db_config.json\"), {});\n const database = path.resolve(ROOT, typeof cfg.dbDir === \"string\" && cfg.dbDir.trim() ? cfg.dbDir : \"data/sfmc_data.db\");\n let data: { online?: { name: string }[]; updatedAt?: number } = {};\n try {\n const response = await fetch(`http://127.0.0.1:${cfg.db_port ?? 3001}/api/sfmc/status`, { headers: cfg.http_auth ? { authorization: `Bearer ${cfg.http_auth}` } : {}, signal: AbortSignal.timeout(5000) });\n if (response.ok) data = await response.json() as typeof data;\n } catch { /* \u672A\u8FDE\u63A5\u65F6\u4F7F\u7528\u672A\u77E5\u72B6\u6001 */ }\n const fresh = typeof data.updatedAt === \"number\" && Date.now() - data.updatedAt < 60_000;\n return { players: (data.online ?? []).map(row => ({ name: row.name, xuid: \"\", online: fresh ? true : null })), updatedAt: data.updatedAt ? new Date(data.updatedAt).toISOString() : \"\", fresh, allowlist, permissions: readJson<unknown[]>(files.permissions, []), sfmcPermissions: readJson<unknown[]>(files.sfmcPermissions, []), bindings: readQqBindings(database) };\n}\nasync function bdsUpdate(context: TaskContext, checkOnly = false) {\n context.phase(\"download\", checkOnly ? \"\u68C0\u67E5 BDS \u66F4\u65B0\" : \"\u66F4\u65B0 BDS\");\n const args = checkOnly ? [\"--check-only\", \"--no-notify\"] : [\"--no-start\", \"--no-notify\"];\n let output = \"\";\n await new Promise<void>((resolve, reject) => {\n const child = spawnService(\"update\", args, { stdio: \"pipe\", cwd: ROOT });\n for (const stream of [child.stdout, child.stderr]) stream?.on(\"data\", chunk => { output = (output + String(chunk)).slice(-64_000); });\n child.on(\"error\", reject); child.on(\"close\", code => code === 0 ? resolve() : reject(new Error(`BDS \u66F4\u65B0\u5931\u8D25 (${code})`)));\n });\n return { checked: checkOnly, updated: /SFMC_UPDATE_RESULT=deployed/.test(output), currentVersion: /CURRENT=([^\\r\\n]+)/.exec(output)?.[1] ?? \"unknown\", latestVersion: /LATEST=([^\\r\\n]+)/.exec(output)?.[1] ?? \"unknown\", result: /SFMC_UPDATE_RESULT=([^\\r\\n]+)/.exec(output)?.[1] ?? \"unknown\" };\n}\nexport async function dispatchManagement(request: ManagementRequest): Promise<unknown> {\n const p = params(request); const store = managementTasks();\n switch (request.method) {\n case \"handshake\": return { protocolVersion: MANAGEMENT_PROTOCOL_VERSION, platformVersion: platformVersion(), host: { os: process.platform === \"win32\" ? \"windows\" : process.platform, arch: process.arch, release: os.release() }, root: ROOT, capabilities: [\"services\", \"logs\", \"logs-range\", \"modules\", \"config\", \"packs\", \"players\", \"updates\", \"operations\", \"metrics\", \"manual-restart\", \"manual-backup\", \"pack-import-plan\", \"pack-icons\", \"pack-uninstall\", \"backup-delete\", \"pack-import-batch\", \"pack-version\"], daemonPid: process.pid, daemonStartedAt: new Date(Date.now() - process.uptime() * 1000).toISOString(), initialized: deploymentInitialized() };\n case \"events.subscribe\": return { subscribed: true };\n case \"services.list\": return { rows: await queryServicesRuntimeLocal() };\n case \"services.start\": case \"services.stop\": case \"services.restart\": {\n const requestedNames = p.name === \"all\" ? [...START_ORDER] : [service(p.name)];\n const reloadConfig = p.reloadConfig === true;\n if (reloadConfig && (p.name !== \"all\" || request.method !== \"services.restart\")) throw new Error(\"\u91CD\u65B0\u8BFB\u53D6\u914D\u7F6E\u9700\u8981\u91CD\u542F\u5168\u90E8\u670D\u52A1\");\n return store.submit(request.method, async context => {\n context.phase(\"execute\");\n const rows = await queryServicesRuntimeLocal();\n const names = p.runningOnly === true\n ? requestedNames.filter(name => rows.some(row => row.name === name && row.running))\n : requestedNames;\n if (rows.some(row => names.includes(row.name) && row.running && row.ownership === \"external\") && request.method !== \"services.start\") throw new Error(\"\u5916\u90E8\u8FDB\u7A0B\u65E0\u6CD5\u5B89\u5168\u505C\u6B62\uFF0C\u8BF7\u901A\u8FC7\u539F\u7BA1\u7406\u5668\u64CD\u4F5C\");\n if (request.method !== \"services.start\") for (const name of [...names].reverse()) await services[name].stop(false, false);\n if (reloadConfig) {\n const after = await queryServicesRuntimeLocal();\n if (after.some(row => requestedNames.includes(row.name) && row.running)) throw new Error(\"\u670D\u52A1\u672A\u5B8C\u5168\u9000\u51FA\uFF0C\u5DF2\u4E2D\u6B62\u914D\u7F6E\u5237\u65B0\");\n refreshServices();\n }\n if (request.method !== \"services.stop\") {\n if (!reloadConfig) {\n const after = await queryServicesRuntimeLocal();\n if (request.method === \"services.restart\" && after.some(row => names.includes(row.name) && row.running)) throw new Error(\"\u670D\u52A1\u672A\u5B8C\u5168\u9000\u51FA\uFF0C\u5DF2\u4E2D\u6B62\u91CD\u542F\");\n const stopped = names.filter(name => !after.some(row => row.name === name && row.running));\n if (stopped.length) refreshServices(stopped);\n }\n const outcomes = [];\n for (const name of names) outcomes.push({ name, ...(await services[name].start()) });\n await verifyRunning(outcomes.filter(row => row.status !== \"skipped\").map(row => row.name));\n return { outcomes };\n }\n return { stopped: names };\n });\n }\n case \"services.send\": {\n const name = service(p.name); const message = string(p.message, \"\u547D\u4EE4\");\n if (/[\\r\\n]/.test(message) || !message.trim()) throw new Error(\"\u4E00\u6B21\u53EA\u80FD\u53D1\u9001\u4E00\u884C\u547D\u4EE4\");\n const target = services[name]; if (!target.proc?.stdin || !target.running) throw new Error(\"\u670D\u52A1\u672A\u6258\u7BA1\u6216\u6CA1\u6709\u547D\u4EE4\u8F93\u5165\u901A\u9053\");\n return withMaintenanceLock(ROOT, async () => { target.proc!.stdin!.write(message + \"\\n\"); return { delivered: true }; });\n }\n case \"logs.tail\": {\n const since = timeBound(p.since, \"\u5F00\u59CB\u65F6\u95F4\");\n const until = timeBound(p.until, \"\u7ED3\u675F\u65F6\u95F4\");\n if (since && until && until < since) throw new Error(\"\u7ED3\u675F\u65F6\u95F4\u4E0D\u80FD\u65E9\u4E8E\u5F00\u59CB\u65F6\u95F4\");\n const limit = Math.min(LOG_TAIL_MAX, Math.max(1, Number(p.limit) || 1000));\n const ranged = Boolean(since || until);\n const entries = readDiskLogs({\n ...(ranged ? {} : { limit }),\n ...(since ? { since } : {}),\n ...(until ? { until } : {}),\n ...(Array.isArray(p.sources) ? { sources: p.sources.map(value => string(value, \"\u65E5\u5FD7\u6765\u6E90\")) } : {}),\n ...(Array.isArray(p.levels) ? { levels: p.levels as (\"info\" | \"warn\" | \"error\")[] } : {}),\n });\n const truncated = entries.length > limit;\n return { entries: (truncated ? entries.slice(entries.length - limit) : entries).map(log => ({ ...log, time: log.time.toISOString() })), ...(truncated ? { truncated: true } : {}) };\n }\n case \"logs.delete\": {\n const since = timeBound(p.since, \"\u5F00\u59CB\u65F6\u95F4\");\n const until = timeBound(p.until, \"\u7ED3\u675F\u65F6\u95F4\");\n if (!since || !until) throw new Error(\"\u5220\u9664\u65E5\u5FD7\u9700\u8981\u5F00\u59CB\u548C\u7ED3\u675F\u65F6\u95F4\");\n if (until < since) throw new Error(\"\u7ED3\u675F\u65F6\u95F4\u4E0D\u80FD\u65E9\u4E8E\u5F00\u59CB\u65F6\u95F4\");\n const source = p.source === undefined ? undefined : string(p.source, \"\u65E5\u5FD7\u6765\u6E90\");\n if (source !== undefined && (source.length > 128 || /[\\r\\n]/.test(source))) throw new Error(\"\u975E\u6CD5\u65E5\u5FD7\u6765\u6E90\");\n const text = p.text === undefined ? undefined : string(p.text, \"\u65E5\u5FD7\u6B63\u6587\");\n return deleteStoredLogs({ since, until, ...(source === undefined ? {} : { source }), ...(text === undefined ? {} : { text }) });\n }\n case \"operations.list\": return { operations: store.list().filter(row => !Array.isArray(p.statuses) || p.statuses.includes(row.status)).slice(0, Math.min(Number(p.limit) || 100, 200)) };\n case \"operations.get\": return { operation: store.get(string(p.operationId, \"\u4EFB\u52A1\u7F16\u53F7\")) };\n case \"modules.list\": return listModules();\n case \"modules.search\": return searchModules(typeof p.query === \"string\" ? p.query : \"\");\n case \"modules.install\": {\n const id = identifier(p.id);\n const linked = (await listModules()).modules.find(row => row.id === id || row.folder === id)?.linked;\n if (linked) throw new Error(\"\u4FDD\u7559\u672C\u5730\u94FE\u63A5\u6A21\u5757\uFF0C\u4E0D\u901A\u8FC7\u5305\u5B89\u88C5\u6216\u5378\u8F7D\u8986\u76D6\u5F00\u53D1\u76EE\u5F55\");\n const block = await moduleInstallBlock(id);\n if (block) throw new Error(block);\n return store.submit(request.method, async context => {\n context.phase(\"download\", \"\u4E0B\u8F7D\u5E76\u5B89\u88C5\u6A21\u5757\uFF0C\u670D\u52A1\u5668\u4FDD\u6301\u8FD0\u884C\");\n const args = [\"install\", id];\n if (typeof p.source === \"string\" && p.source) args.push(\"--from\", p.source);\n await runFetch(args);\n context.phase(\"execute\", \"\u91CD\u5EFA\u884C\u4E3A\u5305\uFF0C\u7B49\u5F85\u624B\u52A8\u91CD\u542F BDS\");\n return { ...(await rebuildModules()), restartRequired: true };\n });\n }\n case \"modules.uninstall\": case \"modules.toggle\": {\n const id = identifier(p.id);\n if (request.method !== \"modules.toggle\") {\n const linked = (await listModules()).modules.find(row => row.id === id || row.folder === id)?.linked;\n if (linked) throw new Error(\"\u4FDD\u7559\u672C\u5730\u94FE\u63A5\u6A21\u5757\uFF0C\u4E0D\u901A\u8FC7\u5305\u5B89\u88C5\u6216\u5378\u8F7D\u8986\u76D6\u5F00\u53D1\u76EE\u5F55\");\n }\n return store.submit(request.method, async context => {\n context.phase(\"execute\", \"\u66F4\u65B0\u6A21\u5757\u5E76\u91CD\u5EFA\u884C\u4E3A\u5305\uFF0C\u7B49\u5F85\u624B\u52A8\u91CD\u542F BDS\");\n if (request.method === \"modules.toggle\") {\n const result = await (p.enabled === true ? cmdModuleEnable([id]) : cmdModuleDisable([id])); if (!result.ok) throw new Error(result.message);\n } else {\n await runFetch([\"uninstall\", id]);\n }\n return { ...(await rebuildModules()), restartRequired: true };\n });\n }\n case \"config.list\": return { keys: [...configFiles().keys()] };\n case \"config.read\": return readDocument(string(p.key, \"\u914D\u7F6E\u540D\u79F0\"));\n case \"config.save\": {\n const key = string(p.key, \"\u914D\u7F6E\u540D\u79F0\"); const text = string(p.text, \"\u914D\u7F6E\u5185\u5BB9\"); const expected = string(p.revision, \"\u914D\u7F6E\u7248\u672C\");\n const document = readDocument(key); validateDocument(document, text);\n if (document.revision !== expected) throw Object.assign(new Error(\"\u914D\u7F6E\u5DF2\u53D8\u66F4\uFF0C\u8BF7\u91CD\u65B0\u8BFB\u53D6\"), { code: \"conflict\" });\n return store.submit(request.method, async context => {\n context.phase(\"execute\", \"\u4FDD\u5B58\u914D\u7F6E\u6587\u4EF6\uFF0C\u4E0D\u91CD\u542F\u670D\u52A1\");\n saveDocument(key, expected, text);\n return { saved: true, revision: revision(text), restartRequired: true };\n });\n }\n case \"config.apply\": {\n const key = string(p.key, \"\u914D\u7F6E\u540D\u79F0\"); const text = string(p.text, \"\u914D\u7F6E\u5185\u5BB9\"); const expected = string(p.revision, \"\u914D\u7F6E\u7248\u672C\");\n const document = readDocument(key); validateDocument(document, text);\n if (document.revision !== expected) throw Object.assign(new Error(\"\u914D\u7F6E\u5DF2\u53D8\u66F4\uFF0C\u8BF7\u91CD\u65B0\u8BFB\u53D6\"), { code: \"conflict\" });\n return store.submit(request.method, async context => {\n let saved = false;\n try { return await withStoppedServices(context, [...START_ORDER], async () => {\n saveDocument(key, expected, text); context.phase(\"apply\", \"\u6587\u4EF6\u5DF2\u4FDD\u5B58\uFF0C\u6B63\u5728\u5E94\u7528\u8FD0\u884C\u914D\u7F6E\");\n saved = true;\n refreshServices(); return { saved: true, revision: readDocument(key).revision, applied: true };\n }); } catch (error) { throw Object.assign(new Error(`${saved ? \"\u6587\u4EF6\u5DF2\u4FDD\u5B58\uFF0C\u8FD0\u884C\u65F6\u5E94\u7528\u5931\u8D25\" : \"\u914D\u7F6E\u672A\u4FDD\u5B58\"}: ${error instanceof Error ? error.message : String(error)}`), { code: \"io\", details: { saved, applied: false } }); }\n });\n }\n case \"packs.list\": return listPacks();\n case \"packs.icon\": return readPackIcon(identifier(p.id));\n case \"packs.import.plan\": return planPackImport(identifier(p.filename));\n case \"packs.import\": {\n const names = readImportFilenames(p);\n return store.submit(request.method, async context => {\n context.phase(\"execute\", names.length > 1 ? `\u5BFC\u5165 ${names.length} \u4E2A\u4E16\u754C\u5305\uFF0C\u7B49\u5F85\u624B\u52A8\u91CD\u542F BDS` : \"\u5BFC\u5165\u4E16\u754C\u5305\uFF0C\u7B49\u5F85\u624B\u52A8\u91CD\u542F BDS\");\n return importPacks(names, { force: p.force === true, ...(p.revision === undefined ? {} : { revision: string(p.revision, \"\u5BFC\u5165\u8BA1\u5212\u7248\u672C\") }) });\n });\n }\n case \"packs.toggle\": return store.submit(request.method, async context => {\n context.phase(\"execute\", \"\u4FDD\u5B58\u4E16\u754C\u5305\u72B6\u6001\uFF0C\u7B49\u5F85\u624B\u52A8\u91CD\u542F BDS\");\n return togglePack(identifier(p.id), p.enabled === true);\n });\n case \"packs.uninstall\": return store.submit(request.method, async context => {\n context.phase(\"execute\", \"\u5378\u8F7D\u4E16\u754C\u5305\u5E76\u79FB\u5165\u56DE\u6536\u7AD9\uFF0C\u7B49\u5F85\u624B\u52A8\u91CD\u542F BDS\");\n return uninstallPack(identifier(p.id));\n });\n case \"packs.version\": {\n const id = identifier(p.id);\n const version = p.version;\n return store.submit(request.method, async context => {\n context.phase(\"execute\", \"\u5199\u5165\u8D44\u6E90\u5305\u7248\u672C\uFF0C\u7B49\u5F85\u624B\u52A8\u91CD\u542F BDS\");\n return setPackVersion(id, version);\n });\n }\n case \"players.list\": return players();\n case \"metrics.read\": return readRuntimeMetrics(request.params);\n case \"players.apply\": return store.submit(request.method, context => withStoppedServices(context, [...START_ORDER], async () => savePlayerPermissions(string(p.kind, \"\u6743\u9650\u7C7B\u578B\"), p.entries)));\n case \"attachment.plan\": return attachmentPlan();\n case \"attachment.apply\": return store.submit(request.method, async context => {\n const plan = await attachmentPlan(false);\n if (p.targetVersion !== undefined && p.targetVersion !== plan.targetVersion) throw Object.assign(new Error(\"\u76EE\u6807\u7248\u672C\u5DF2\u53D8\u66F4\uFF0C\u8BF7\u91CD\u65B0\u68C0\u67E5\u66F4\u65B0\u65E5\u5FD7\u540E\u786E\u8BA4\"), { code: \"conflict\" });\n if (plan.externalServices.length) throw new Error(\"\u65E0\u6CD5\u53EF\u9760\u8FC1\u79FB\u5916\u90E8\u8FDB\u7A0B\uFF1B\u8BF7\u5148\u901A\u8FC7\u539F\u7BA1\u7406\u5668\u4F18\u96C5\u505C\u670D\");\n if (plan.upgradeRequired) return launchPlatformUpdate(store, context, plan.targetVersion);\n return { attached: true, version: plan.currentVersion, development: plan.development };\n });\n case \"updates.check\": {\n const results = await Promise.allSettled([attachmentPlan(), modulePlan(), bdsUpdate({ id: \"check\", phase: () => {} }, true)]);\n return Object.fromEntries(results.map((result, index) => [[\"platform\", \"modules\", \"bds\"][index], result.status === \"fulfilled\" ? result.value : { error: String(result.reason) }]));\n }\n case \"updates.run\": {\n if (p.kind === \"platform\") return store.submit(request.method, async context => { const plan = await attachmentPlan(false); if (p.targetVersion !== undefined && p.targetVersion !== plan.targetVersion) throw Object.assign(new Error(\"\u76EE\u6807\u7248\u672C\u5DF2\u53D8\u66F4\uFF0C\u8BF7\u91CD\u65B0\u68C0\u67E5\u66F4\u65B0\u65E5\u5FD7\u540E\u786E\u8BA4\"), { code: \"conflict\" }); return plan.upgradeRequired ? launchPlatformUpdate(store, context, plan.targetVersion) : { upToDate: true, version: plan.currentVersion }; });\n if (p.kind === \"modules\") return store.submit(request.method, context => withStoppedServices(context, [...START_ORDER], async () => { const result = await applyModulePlan(Array.isArray(p.ids) ? p.ids.map(identifier) : []); await rebuildModules(); return result; }));\n if (p.kind === \"bds\") return store.submit(request.method, context => withStoppedServices(context, [...START_ORDER], () => bdsUpdate(context)));\n throw new Error(\"\u672A\u77E5\u66F4\u65B0\u7C7B\u578B\");\n }\n case \"deployment.create\": {\n if (p.acceptEula !== true) throw new Error(\"\u521B\u5EFA\u90E8\u7F72\u524D\u5FC5\u987B\u786E\u8BA4 BDS \u4F7F\u7528\u6761\u6B3E\");\n return store.submit(request.method, async context => {\n if (isRuntimeInitialized()) throw new Error(\"\u76EE\u5F55\u5DF2\u7ECF\u521D\u59CB\u5316\uFF0C\u4E0D\u8986\u76D6\u5DF2\u6709\u90E8\u7F72\");\n const ports = { db: deploymentPort(p.dbPort, 3001), bds: deploymentPort(p.bdsPort, 19132), bds6: deploymentPort(p.bdsPort6, 19133) };\n context.phase(\"preflight\", \"\u68C0\u67E5\u76EE\u5F55\u3001\u78C1\u76D8\u7A7A\u95F4\u548C TCP\uFF0FUDP \u7AEF\u53E3\"); await deploymentPreflight(ports);\n context.phase(\"prepare\"); ensureCoreConfigs(ROOT, [\"db_config\", \"qq_config\", \"bds_updater\", \"permissions\", \"qq_link\"]);\n const updater = path.join(ROOT, \"configs\", \"bds_updater.json\");\n atomicJson(updater, { ...readJson(updater, {}), bds_path: \"BDS\", backup_dir: \"backups\" });\n const dbFile = path.join(ROOT, \"configs\", \"db_config.json\"); atomicJson(dbFile, { ...readJson(dbFile, {}), db_port: ports.db });\n fs.mkdirSync(path.join(ROOT, \"modules\", \"packages\"), { recursive: true });\n await bdsUpdate(context);\n const properties = path.join(ROOT, \"BDS\", \"server.properties\");\n let text = fs.readFileSync(properties, \"utf8\");\n for (const [key, port] of [[\"server-port\", ports.bds], [\"server-portv6\", ports.bds6]] as const) text = text.replace(new RegExp(`^${key}=.*$`, \"m\"), `${key}=${port}`);\n fs.writeFileSync(properties, text);\n await rebuildModules();\n refreshServices(); context.phase(\"start\");\n const started: ServiceName[] = [];\n try { for (const name of START_ORDER) { const result = await services[name].start(); if (result.status !== \"skipped\") started.push(name); } await verifyRunning(started); }\n catch (error) { for (const name of [...START_ORDER].reverse()) await services[name].stop(false, false).catch(() => {}); throw error; }\n atomicJson(path.join(ROOT, \"configs\", \"runtime.json\"), { ...readJson(path.join(ROOT, \"configs\", \"runtime.json\"), {}), initialized_at: new Date().toISOString() });\n return { created: true, rows: await queryServicesRuntimeLocal() };\n });\n }\n case \"backups.list\": { const directory = path.join(ROOT, \".sfmc\", \"backups\"); return { backups: fs.existsSync(directory) ? fs.readdirSync(directory).filter(id => fs.existsSync(path.join(directory, id, \"manifest.json\"))) : [] }; }\n case \"backups.create\": return store.submit(request.method, context => createBackup(context));\n case \"backups.restore\": {\n if (p.confirmDataLoss !== true) throw new Error(\"\u6062\u590D\u6570\u636E\u9700\u8981\u660E\u786E\u786E\u8BA4\u4E22\u5F03\u5907\u4EFD\u4E4B\u540E\u7684\u53D8\u66F4\");\n return store.submit(request.method, context => withStoppedServices(context, [...START_ORDER], () => restoreSnapshot(identifier(p.id), context.phase)));\n }\n case \"backups.delete\": return store.submit(request.method, async context => {\n context.phase(\"execute\", \"\u5220\u9664\u5907\u4EFD\u76EE\u5F55\");\n return deleteSnapshot(identifier(p.id));\n });\n case \"startup.plan\": return startupPlan();\n default: throw Object.assign(new Error(`\u4E0D\u652F\u6301\u7684\u7BA1\u7406\u65B9\u6CD5: ${request.method}`), { code: \"unsupported\" });\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import fs from \"node:fs\";\nimport path from \"node:path\";\nimport os from \"node:os\";\nimport { EventEmitter } from \"node:events\";\nimport { LOG_TAIL_MAX, MANAGEMENT_PROTOCOL_VERSION, type ManagementRequest, type ManagementEvent } from \"@sfmc-bds/management\";\nimport { readQqBindings } from \"@sfmc-bds/db-server/qq-bindings\";\nimport { parseActivityFilter, parseActivityPaging, readActivityPage, readActivityStats } from \"@sfmc-bds/db-server/activity-log\";\nimport { ROOT, isRuntimeInitialized, spawnService } from \"../runtime.js\";\nimport { queryServicesRuntimeLocal, services, START_ORDER, SERVICE_NAMES, refreshServices, onServiceStateChange, type ServiceName } from \"../services.js\";\nimport { readDiskLogs, deleteStoredLogs, onLog } from \"../logs.js\";\nimport { cmdModuleEnable, cmdModuleDisable } from \"../module-commands.js\";\nimport { ensureCoreConfigs } from \"@sfmc-bds/sdk/node/config\";\nimport { TaskStore, atomicJson, type TaskContext } from \"./tasks.js\";\nimport { configFiles, readDocument, revision, saveDocument, validateDocument } from \"./config.js\";\nimport { listModules, searchModules, identifier, runFetch, readJson, listPacks, togglePack, readPackIcon, uninstallPack, setPackVersion, playerFiles, savePlayerPermissions, modulePlan, applyModulePlan, moduleInstallBlock } from \"./domain.js\";\nimport { attachmentPlan, platformVersion, withStoppedServices, launchPlatformUpdate, createBackup, restoreSnapshot, deleteSnapshot, verifyRunning } from \"./maintenance.js\";\nimport { startupPlan } from \"./startup.js\";\nimport { cmdPackBuild, cmdPackDeploy } from \"../pack-lifecycle.js\";\nimport { withMaintenanceLock } from \"@sfmc-bds/management/node\";\nimport { deploymentPreflight, deploymentPort } from \"./deployment.js\";\nimport { resolveBdsContext } from \"../pack-lifecycle.js\";\nimport { readRuntimeMetrics } from \"./metrics-read.js\";\nimport { applyScoreboard, readScoreboard } from \"./scoreboard.js\";\nimport { LOCAL_CAPABILITIES } from \"./local-methods.js\";\n\nimport { importPacks, planPackImport, readImportFilenames } from \"./pack-import.js\";\n\nconst events = new EventEmitter();\n/** \u7A7A\u76EE\u5F55\u4E5F\u8981\u80FD\u5B8C\u6210\u63E1\u624B\uFF0C\u4F9B\u684C\u9762\u521D\u59CB\u5316\u5411\u5BFC\u7EE7\u7EED\uFF1B\u65E7\u90E8\u7F72\u4ECD\u8BC6\u522B\u5DF2\u6709 BDS\u3002 */\nfunction deploymentInitialized(): boolean {\n if (isRuntimeInitialized()) return true;\n const config = readJson<{ bds_path?: string }>(path.join(ROOT, \"configs\", \"bds_updater.json\"), {});\n if (!config.bds_path) return false;\n return fs.existsSync(path.join(resolveBdsContext().bdsRoot, process.platform === \"win32\" ? \"bedrock_server.exe\" : \"bedrock_server\"));\n}\nlet tasks: TaskStore | undefined;\nexport function managementTasks() {\n if (!tasks) {\n tasks = new TaskStore(ROOT);\n tasks.on(\"operation\", payload => events.emit(\"event\", { type: \"event\", event: \"operation\", instanceId: ROOT, payload }));\n onLog(log => events.emit(\"event\", { type: \"event\", event: \"log\", instanceId: ROOT, payload: { ...log, time: log.time.toISOString() } }));\n onServiceStateChange(payload => events.emit(\"event\", { type: \"event\", event: \"serviceState\", instanceId: ROOT, payload }));\n }\n return tasks;\n}\nexport function onManagementEvent(callback: (event: ManagementEvent) => void) { events.on(\"event\", callback); return () => events.off(\"event\", callback); }\nfunction params(request: ManagementRequest): Record<string, unknown> {\n if (request.params === undefined) return {};\n if (!request.params || typeof request.params !== \"object\" || Array.isArray(request.params)) throw new Error(\"\u53C2\u6570\u5FC5\u987B\u4E3A\u5BF9\u8C61\");\n return request.params as Record<string, unknown>;\n}\nfunction string(value: unknown, label: string) { if (typeof value !== \"string\" || value.length > 2 * 1024 * 1024) throw new Error(`\u975E\u6CD5 ${label}`); return value; }\n/** \u89E3\u6790\u65E5\u5FD7\u67E5\u8BE2\u7528\u7684 ISO \u65F6\u95F4\u3002\u7F3A\u7701\u8FD4\u56DE undefined\u3002 */\nfunction timeBound(value: unknown, label: string): Date | undefined {\n if (value === undefined) return undefined;\n const date = new Date(string(value, label));\n if (Number.isNaN(date.getTime())) throw new Error(`\u975E\u6CD5 ${label}`);\n return date;\n}\nfunction service(value: unknown): ServiceName { if (!SERVICE_NAMES.includes(value as ServiceName)) throw new Error(\"\u672A\u77E5\u670D\u52A1\"); return value as ServiceName; }\nasync function rebuildModules() {\n const build = await cmdPackBuild([]); if (!build.ok) throw new Error(build.message);\n const deploy = await cmdPackDeploy([]); if (!deploy.ok) throw new Error(deploy.message);\n return { changed: true };\n}\n\n/** configs/db_config.json \u4E2D\u7BA1\u7406\u901A\u9053\u7528\u5230\u7684\u5B57\u6BB5 */\ntype DbConfig = { db_port?: number; http_auth?: string; dbDir?: string };\n/** \u8BFB\u53D6\u4E1A\u52A1\u5E93\u914D\u7F6E\u3002\u4F7F\u7528\u573A\u666F\uFF1Aplayers.list \u67E5\u5728\u7EBF\u5FEB\u7167\u4E0E\u7ED1\u5B9A\uFF0Cactivity.* \u5B9A\u4F4D\u4E1A\u52A1\u5E93\u6587\u4EF6\u3002 */\nfunction dbConfig(): DbConfig {\n return readJson<DbConfig>(path.join(ROOT, \"configs\", \"db_config.json\"), {});\n}\n/** \u4E1A\u52A1\u5E93 SQLite \u6587\u4EF6\u8DEF\u5F84\uFF08dbDir \u7F3A\u7701\u4E3A data/sfmc_data.db\uFF0C\u4E0E db-server \u4E00\u81F4\uFF09\u3002 */\nfunction businessDatabase(cfg: DbConfig = dbConfig()): string {\n return path.resolve(ROOT, typeof cfg.dbDir === \"string\" && cfg.dbDir.trim() ? cfg.dbDir : \"data/sfmc_data.db\");\n}\nasync function players() {\n const files = playerFiles(); const allowlist = readJson<unknown[]>(files.allowlist, []);\n const cfg = dbConfig();\n const database = businessDatabase(cfg);\n let data: { online?: { name: string }[]; updatedAt?: number } = {};\n try {\n const response = await fetch(`http://127.0.0.1:${cfg.db_port ?? 3001}/api/sfmc/status`, { headers: cfg.http_auth ? { authorization: `Bearer ${cfg.http_auth}` } : {}, signal: AbortSignal.timeout(5000) });\n if (response.ok) data = await response.json() as typeof data;\n } catch { /* \u672A\u8FDE\u63A5\u65F6\u4F7F\u7528\u672A\u77E5\u72B6\u6001 */ }\n const fresh = typeof data.updatedAt === \"number\" && Date.now() - data.updatedAt < 60_000;\n return { players: (data.online ?? []).map(row => ({ name: row.name, xuid: \"\", online: fresh ? true : null })), updatedAt: data.updatedAt ? new Date(data.updatedAt).toISOString() : \"\", fresh, allowlist, permissions: readJson<unknown[]>(files.permissions, []), sfmcPermissions: readJson<unknown[]>(files.sfmcPermissions, []), bindings: readQqBindings(database) };\n}\n/**\n * \u5411\u6258\u7BA1\u670D\u52A1\u7684\u6807\u51C6\u8F93\u5165\u5199\u5165\u4E00\u884C\u547D\u4EE4\u3002\n * \u4F7F\u7528\u573A\u666F\uFF1Aservices.send\uFF08\u63A7\u5236\u53F0\u9875\u624B\u52A8\u547D\u4EE4\uFF09\u4E0E scoreboard.apply\uFF08\u8BA1\u5206\u677F\u7F16\u8F91\u751F\u6210\u7684\u547D\u4EE4\uFF09\u3002\n */\nasync function sendServiceLine(name: ServiceName, message: string): Promise<void> {\n if (/[\\r\\n]/.test(message) || !message.trim()) throw new Error(\"\u4E00\u6B21\u53EA\u80FD\u53D1\u9001\u4E00\u884C\u547D\u4EE4\");\n const target = services[name]; if (!target.proc?.stdin || !target.running) throw new Error(\"\u670D\u52A1\u672A\u6258\u7BA1\u6216\u6CA1\u6709\u547D\u4EE4\u8F93\u5165\u901A\u9053\");\n await withMaintenanceLock(ROOT, async () => { target.proc!.stdin!.write(message + \"\\n\"); });\n}\nasync function bdsUpdate(context: TaskContext, checkOnly = false) {\n context.phase(\"download\", checkOnly ? \"\u68C0\u67E5 BDS \u66F4\u65B0\" : \"\u66F4\u65B0 BDS\");\n const args = checkOnly ? [\"--check-only\", \"--no-notify\"] : [\"--no-start\", \"--no-notify\"];\n let output = \"\";\n await new Promise<void>((resolve, reject) => {\n const child = spawnService(\"update\", args, { stdio: \"pipe\", cwd: ROOT });\n for (const stream of [child.stdout, child.stderr]) stream?.on(\"data\", chunk => { output = (output + String(chunk)).slice(-64_000); });\n child.on(\"error\", reject); child.on(\"close\", code => code === 0 ? resolve() : reject(new Error(`BDS \u66F4\u65B0\u5931\u8D25 (${code})`)));\n });\n return { checked: checkOnly, updated: /SFMC_UPDATE_RESULT=deployed/.test(output), currentVersion: /CURRENT=([^\\r\\n]+)/.exec(output)?.[1] ?? \"unknown\", latestVersion: /LATEST=([^\\r\\n]+)/.exec(output)?.[1] ?? \"unknown\", result: /SFMC_UPDATE_RESULT=([^\\r\\n]+)/.exec(output)?.[1] ?? \"unknown\" };\n}\nexport async function dispatchManagement(request: ManagementRequest): Promise<unknown> {\n const p = params(request); const store = managementTasks();\n switch (request.method) {\n case \"handshake\": return { protocolVersion: MANAGEMENT_PROTOCOL_VERSION, platformVersion: platformVersion(), host: { os: process.platform === \"win32\" ? \"windows\" : process.platform, arch: process.arch, release: os.release() }, root: ROOT, capabilities: [\"services\", \"logs\", \"logs-range\", \"modules\", \"config\", \"packs\", \"players\", \"updates\", \"operations\", \"metrics\", \"manual-restart\", \"manual-backup\", \"pack-import-plan\", \"pack-icons\", \"pack-uninstall\", \"backup-delete\", \"pack-import-batch\", \"pack-version\", ...LOCAL_CAPABILITIES], daemonPid: process.pid, daemonStartedAt: new Date(Date.now() - process.uptime() * 1000).toISOString(), initialized: deploymentInitialized() };\n case \"events.subscribe\": return { subscribed: true };\n case \"services.list\": return { rows: await queryServicesRuntimeLocal() };\n case \"services.start\": case \"services.stop\": case \"services.restart\": {\n const requestedNames = p.name === \"all\" ? [...START_ORDER] : [service(p.name)];\n const reloadConfig = p.reloadConfig === true;\n if (reloadConfig && (p.name !== \"all\" || request.method !== \"services.restart\")) throw new Error(\"\u91CD\u65B0\u8BFB\u53D6\u914D\u7F6E\u9700\u8981\u91CD\u542F\u5168\u90E8\u670D\u52A1\");\n return store.submit(request.method, async context => {\n context.phase(\"execute\");\n const rows = await queryServicesRuntimeLocal();\n const names = p.runningOnly === true\n ? requestedNames.filter(name => rows.some(row => row.name === name && row.running))\n : requestedNames;\n if (rows.some(row => names.includes(row.name) && row.running && row.ownership === \"external\") && request.method !== \"services.start\") throw new Error(\"\u5916\u90E8\u8FDB\u7A0B\u65E0\u6CD5\u5B89\u5168\u505C\u6B62\uFF0C\u8BF7\u901A\u8FC7\u539F\u7BA1\u7406\u5668\u64CD\u4F5C\");\n if (request.method !== \"services.start\") for (const name of [...names].reverse()) await services[name].stop(false, false);\n if (reloadConfig) {\n const after = await queryServicesRuntimeLocal();\n if (after.some(row => requestedNames.includes(row.name) && row.running)) throw new Error(\"\u670D\u52A1\u672A\u5B8C\u5168\u9000\u51FA\uFF0C\u5DF2\u4E2D\u6B62\u914D\u7F6E\u5237\u65B0\");\n refreshServices();\n }\n if (request.method !== \"services.stop\") {\n if (!reloadConfig) {\n const after = await queryServicesRuntimeLocal();\n if (request.method === \"services.restart\" && after.some(row => names.includes(row.name) && row.running)) throw new Error(\"\u670D\u52A1\u672A\u5B8C\u5168\u9000\u51FA\uFF0C\u5DF2\u4E2D\u6B62\u91CD\u542F\");\n const stopped = names.filter(name => !after.some(row => row.name === name && row.running));\n if (stopped.length) refreshServices(stopped);\n }\n const outcomes = [];\n for (const name of names) outcomes.push({ name, ...(await services[name].start()) });\n await verifyRunning(outcomes.filter(row => row.status !== \"skipped\").map(row => row.name));\n return { outcomes };\n }\n return { stopped: names };\n });\n }\n case \"services.send\": {\n await sendServiceLine(service(p.name), string(p.message, \"\u547D\u4EE4\"));\n return { delivered: true };\n }\n case \"logs.tail\": {\n const since = timeBound(p.since, \"\u5F00\u59CB\u65F6\u95F4\");\n const until = timeBound(p.until, \"\u7ED3\u675F\u65F6\u95F4\");\n if (since && until && until < since) throw new Error(\"\u7ED3\u675F\u65F6\u95F4\u4E0D\u80FD\u65E9\u4E8E\u5F00\u59CB\u65F6\u95F4\");\n const limit = Math.min(LOG_TAIL_MAX, Math.max(1, Number(p.limit) || 1000));\n const ranged = Boolean(since || until);\n const entries = readDiskLogs({\n ...(ranged ? {} : { limit }),\n ...(since ? { since } : {}),\n ...(until ? { until } : {}),\n ...(Array.isArray(p.sources) ? { sources: p.sources.map(value => string(value, \"\u65E5\u5FD7\u6765\u6E90\")) } : {}),\n ...(Array.isArray(p.levels) ? { levels: p.levels as (\"info\" | \"warn\" | \"error\")[] } : {}),\n });\n const truncated = entries.length > limit;\n return { entries: (truncated ? entries.slice(entries.length - limit) : entries).map(log => ({ ...log, time: log.time.toISOString() })), ...(truncated ? { truncated: true } : {}) };\n }\n case \"logs.delete\": {\n const since = timeBound(p.since, \"\u5F00\u59CB\u65F6\u95F4\");\n const until = timeBound(p.until, \"\u7ED3\u675F\u65F6\u95F4\");\n if (!since || !until) throw new Error(\"\u5220\u9664\u65E5\u5FD7\u9700\u8981\u5F00\u59CB\u548C\u7ED3\u675F\u65F6\u95F4\");\n if (until < since) throw new Error(\"\u7ED3\u675F\u65F6\u95F4\u4E0D\u80FD\u65E9\u4E8E\u5F00\u59CB\u65F6\u95F4\");\n const source = p.source === undefined ? undefined : string(p.source, \"\u65E5\u5FD7\u6765\u6E90\");\n if (source !== undefined && (source.length > 128 || /[\\r\\n]/.test(source))) throw new Error(\"\u975E\u6CD5\u65E5\u5FD7\u6765\u6E90\");\n const text = p.text === undefined ? undefined : string(p.text, \"\u65E5\u5FD7\u6B63\u6587\");\n return deleteStoredLogs({ since, until, ...(source === undefined ? {} : { source }), ...(text === undefined ? {} : { text }) });\n }\n case \"operations.list\": return { operations: store.list().filter(row => !Array.isArray(p.statuses) || p.statuses.includes(row.status)).slice(0, Math.min(Number(p.limit) || 100, 200)) };\n case \"operations.get\": return { operation: store.get(string(p.operationId, \"\u4EFB\u52A1\u7F16\u53F7\")) };\n case \"modules.list\": return listModules();\n case \"modules.search\": return searchModules(typeof p.query === \"string\" ? p.query : \"\");\n case \"modules.install\": {\n const id = identifier(p.id);\n const linked = (await listModules()).modules.find(row => row.id === id || row.folder === id)?.linked;\n if (linked) throw new Error(\"\u4FDD\u7559\u672C\u5730\u94FE\u63A5\u6A21\u5757\uFF0C\u4E0D\u901A\u8FC7\u5305\u5B89\u88C5\u6216\u5378\u8F7D\u8986\u76D6\u5F00\u53D1\u76EE\u5F55\");\n const block = await moduleInstallBlock(id);\n if (block) throw new Error(block);\n return store.submit(request.method, async context => {\n context.phase(\"download\", \"\u4E0B\u8F7D\u5E76\u5B89\u88C5\u6A21\u5757\uFF0C\u670D\u52A1\u5668\u4FDD\u6301\u8FD0\u884C\");\n const args = [\"install\", id];\n if (typeof p.source === \"string\" && p.source) args.push(\"--from\", p.source);\n await runFetch(args);\n context.phase(\"execute\", \"\u91CD\u5EFA\u884C\u4E3A\u5305\uFF0C\u7B49\u5F85\u624B\u52A8\u91CD\u542F BDS\");\n return { ...(await rebuildModules()), restartRequired: true };\n });\n }\n case \"modules.uninstall\": case \"modules.toggle\": {\n const id = identifier(p.id);\n if (request.method !== \"modules.toggle\") {\n const linked = (await listModules()).modules.find(row => row.id === id || row.folder === id)?.linked;\n if (linked) throw new Error(\"\u4FDD\u7559\u672C\u5730\u94FE\u63A5\u6A21\u5757\uFF0C\u4E0D\u901A\u8FC7\u5305\u5B89\u88C5\u6216\u5378\u8F7D\u8986\u76D6\u5F00\u53D1\u76EE\u5F55\");\n }\n return store.submit(request.method, async context => {\n context.phase(\"execute\", \"\u66F4\u65B0\u6A21\u5757\u5E76\u91CD\u5EFA\u884C\u4E3A\u5305\uFF0C\u7B49\u5F85\u624B\u52A8\u91CD\u542F BDS\");\n if (request.method === \"modules.toggle\") {\n const result = await (p.enabled === true ? cmdModuleEnable([id]) : cmdModuleDisable([id])); if (!result.ok) throw new Error(result.message);\n } else {\n await runFetch([\"uninstall\", id]);\n }\n return { ...(await rebuildModules()), restartRequired: true };\n });\n }\n case \"config.list\": return { keys: [...configFiles().keys()] };\n case \"config.read\": return readDocument(string(p.key, \"\u914D\u7F6E\u540D\u79F0\"));\n case \"config.save\": {\n const key = string(p.key, \"\u914D\u7F6E\u540D\u79F0\"); const text = string(p.text, \"\u914D\u7F6E\u5185\u5BB9\"); const expected = string(p.revision, \"\u914D\u7F6E\u7248\u672C\");\n const document = readDocument(key); validateDocument(document, text);\n if (document.revision !== expected) throw Object.assign(new Error(\"\u914D\u7F6E\u5DF2\u53D8\u66F4\uFF0C\u8BF7\u91CD\u65B0\u8BFB\u53D6\"), { code: \"conflict\" });\n return store.submit(request.method, async context => {\n context.phase(\"execute\", \"\u4FDD\u5B58\u914D\u7F6E\u6587\u4EF6\uFF0C\u4E0D\u91CD\u542F\u670D\u52A1\");\n saveDocument(key, expected, text);\n return { saved: true, revision: revision(text), restartRequired: true };\n });\n }\n case \"config.apply\": {\n const key = string(p.key, \"\u914D\u7F6E\u540D\u79F0\"); const text = string(p.text, \"\u914D\u7F6E\u5185\u5BB9\"); const expected = string(p.revision, \"\u914D\u7F6E\u7248\u672C\");\n const document = readDocument(key); validateDocument(document, text);\n if (document.revision !== expected) throw Object.assign(new Error(\"\u914D\u7F6E\u5DF2\u53D8\u66F4\uFF0C\u8BF7\u91CD\u65B0\u8BFB\u53D6\"), { code: \"conflict\" });\n return store.submit(request.method, async context => {\n let saved = false;\n try { return await withStoppedServices(context, [...START_ORDER], async () => {\n saveDocument(key, expected, text); context.phase(\"apply\", \"\u6587\u4EF6\u5DF2\u4FDD\u5B58\uFF0C\u6B63\u5728\u5E94\u7528\u8FD0\u884C\u914D\u7F6E\");\n saved = true;\n refreshServices(); return { saved: true, revision: readDocument(key).revision, applied: true };\n }); } catch (error) { throw Object.assign(new Error(`${saved ? \"\u6587\u4EF6\u5DF2\u4FDD\u5B58\uFF0C\u8FD0\u884C\u65F6\u5E94\u7528\u5931\u8D25\" : \"\u914D\u7F6E\u672A\u4FDD\u5B58\"}: ${error instanceof Error ? error.message : String(error)}`), { code: \"io\", details: { saved, applied: false } }); }\n });\n }\n case \"packs.list\": return listPacks();\n case \"packs.icon\": return readPackIcon(identifier(p.id));\n case \"packs.import.plan\": return planPackImport(identifier(p.filename));\n case \"packs.import\": {\n const names = readImportFilenames(p);\n return store.submit(request.method, async context => {\n context.phase(\"execute\", names.length > 1 ? `\u5BFC\u5165 ${names.length} \u4E2A\u4E16\u754C\u5305\uFF0C\u7B49\u5F85\u624B\u52A8\u91CD\u542F BDS` : \"\u5BFC\u5165\u4E16\u754C\u5305\uFF0C\u7B49\u5F85\u624B\u52A8\u91CD\u542F BDS\");\n return importPacks(names, { force: p.force === true, ...(p.revision === undefined ? {} : { revision: string(p.revision, \"\u5BFC\u5165\u8BA1\u5212\u7248\u672C\") }) });\n });\n }\n case \"packs.toggle\": return store.submit(request.method, async context => {\n context.phase(\"execute\", \"\u4FDD\u5B58\u4E16\u754C\u5305\u72B6\u6001\uFF0C\u7B49\u5F85\u624B\u52A8\u91CD\u542F BDS\");\n return togglePack(identifier(p.id), p.enabled === true);\n });\n case \"packs.uninstall\": return store.submit(request.method, async context => {\n context.phase(\"execute\", \"\u5378\u8F7D\u4E16\u754C\u5305\u5E76\u79FB\u5165\u56DE\u6536\u7AD9\uFF0C\u7B49\u5F85\u624B\u52A8\u91CD\u542F BDS\");\n return uninstallPack(identifier(p.id));\n });\n case \"packs.version\": {\n const id = identifier(p.id);\n const version = p.version;\n return store.submit(request.method, async context => {\n context.phase(\"execute\", \"\u5199\u5165\u8D44\u6E90\u5305\u7248\u672C\uFF0C\u7B49\u5F85\u624B\u52A8\u91CD\u542F BDS\");\n return setPackVersion(id, version);\n });\n }\n case \"players.list\": return players();\n case \"metrics.read\": return readRuntimeMetrics(request.params);\n case \"scoreboard.read\": return readScoreboard(request.params);\n case \"scoreboard.apply\": return applyScoreboard(request.params, line => sendServiceLine(\"bds\", line));\n case \"activity.query\": return readActivityPage(businessDatabase(), parseActivityFilter(p), parseActivityPaging(p));\n case \"activity.stats\": return readActivityStats(businessDatabase(), parseActivityFilter(p));\n case \"players.apply\": return store.submit(request.method, context => withStoppedServices(context, [...START_ORDER], async () => savePlayerPermissions(string(p.kind, \"\u6743\u9650\u7C7B\u578B\"), p.entries)));\n case \"attachment.plan\": return attachmentPlan();\n case \"attachment.apply\": return store.submit(request.method, async context => {\n const plan = await attachmentPlan(false);\n if (p.targetVersion !== undefined && p.targetVersion !== plan.targetVersion) throw Object.assign(new Error(\"\u76EE\u6807\u7248\u672C\u5DF2\u53D8\u66F4\uFF0C\u8BF7\u91CD\u65B0\u68C0\u67E5\u66F4\u65B0\u65E5\u5FD7\u540E\u786E\u8BA4\"), { code: \"conflict\" });\n if (plan.externalServices.length) throw new Error(\"\u65E0\u6CD5\u53EF\u9760\u8FC1\u79FB\u5916\u90E8\u8FDB\u7A0B\uFF1B\u8BF7\u5148\u901A\u8FC7\u539F\u7BA1\u7406\u5668\u4F18\u96C5\u505C\u670D\");\n if (plan.upgradeRequired) return launchPlatformUpdate(store, context, plan.targetVersion);\n return { attached: true, version: plan.currentVersion, development: plan.development };\n });\n case \"updates.check\": {\n const results = await Promise.allSettled([attachmentPlan(), modulePlan(), bdsUpdate({ id: \"check\", phase: () => {} }, true)]);\n return Object.fromEntries(results.map((result, index) => [[\"platform\", \"modules\", \"bds\"][index], result.status === \"fulfilled\" ? result.value : { error: String(result.reason) }]));\n }\n case \"updates.run\": {\n if (p.kind === \"platform\") return store.submit(request.method, async context => { const plan = await attachmentPlan(false); if (p.targetVersion !== undefined && p.targetVersion !== plan.targetVersion) throw Object.assign(new Error(\"\u76EE\u6807\u7248\u672C\u5DF2\u53D8\u66F4\uFF0C\u8BF7\u91CD\u65B0\u68C0\u67E5\u66F4\u65B0\u65E5\u5FD7\u540E\u786E\u8BA4\"), { code: \"conflict\" }); return plan.upgradeRequired ? launchPlatformUpdate(store, context, plan.targetVersion) : { upToDate: true, version: plan.currentVersion }; });\n if (p.kind === \"modules\") return store.submit(request.method, context => withStoppedServices(context, [...START_ORDER], async () => { const result = await applyModulePlan(Array.isArray(p.ids) ? p.ids.map(identifier) : []); await rebuildModules(); return result; }));\n if (p.kind === \"bds\") return store.submit(request.method, context => withStoppedServices(context, [...START_ORDER], () => bdsUpdate(context)));\n throw new Error(\"\u672A\u77E5\u66F4\u65B0\u7C7B\u578B\");\n }\n case \"deployment.create\": {\n if (p.acceptEula !== true) throw new Error(\"\u521B\u5EFA\u90E8\u7F72\u524D\u5FC5\u987B\u786E\u8BA4 BDS \u4F7F\u7528\u6761\u6B3E\");\n return store.submit(request.method, async context => {\n if (isRuntimeInitialized()) throw new Error(\"\u76EE\u5F55\u5DF2\u7ECF\u521D\u59CB\u5316\uFF0C\u4E0D\u8986\u76D6\u5DF2\u6709\u90E8\u7F72\");\n const ports = { db: deploymentPort(p.dbPort, 3001), bds: deploymentPort(p.bdsPort, 19132), bds6: deploymentPort(p.bdsPort6, 19133) };\n context.phase(\"preflight\", \"\u68C0\u67E5\u76EE\u5F55\u3001\u78C1\u76D8\u7A7A\u95F4\u548C TCP\uFF0FUDP \u7AEF\u53E3\"); await deploymentPreflight(ports);\n context.phase(\"prepare\"); ensureCoreConfigs(ROOT, [\"db_config\", \"qq_config\", \"bds_updater\", \"permissions\", \"qq_link\"]);\n const updater = path.join(ROOT, \"configs\", \"bds_updater.json\");\n atomicJson(updater, { ...readJson(updater, {}), bds_path: \"BDS\", backup_dir: \"backups\" });\n const dbFile = path.join(ROOT, \"configs\", \"db_config.json\"); atomicJson(dbFile, { ...readJson(dbFile, {}), db_port: ports.db });\n fs.mkdirSync(path.join(ROOT, \"modules\", \"packages\"), { recursive: true });\n await bdsUpdate(context);\n const properties = path.join(ROOT, \"BDS\", \"server.properties\");\n let text = fs.readFileSync(properties, \"utf8\");\n for (const [key, port] of [[\"server-port\", ports.bds], [\"server-portv6\", ports.bds6]] as const) text = text.replace(new RegExp(`^${key}=.*$`, \"m\"), `${key}=${port}`);\n fs.writeFileSync(properties, text);\n await rebuildModules();\n refreshServices(); context.phase(\"start\");\n const started: ServiceName[] = [];\n try { for (const name of START_ORDER) { const result = await services[name].start(); if (result.status !== \"skipped\") started.push(name); } await verifyRunning(started); }\n catch (error) { for (const name of [...START_ORDER].reverse()) await services[name].stop(false, false).catch(() => {}); throw error; }\n atomicJson(path.join(ROOT, \"configs\", \"runtime.json\"), { ...readJson(path.join(ROOT, \"configs\", \"runtime.json\"), {}), initialized_at: new Date().toISOString() });\n return { created: true, rows: await queryServicesRuntimeLocal() };\n });\n }\n case \"backups.list\": { const directory = path.join(ROOT, \".sfmc\", \"backups\"); return { backups: fs.existsSync(directory) ? fs.readdirSync(directory).filter(id => fs.existsSync(path.join(directory, id, \"manifest.json\"))) : [] }; }\n case \"backups.create\": return store.submit(request.method, context => createBackup(context));\n case \"backups.restore\": {\n if (p.confirmDataLoss !== true) throw new Error(\"\u6062\u590D\u6570\u636E\u9700\u8981\u660E\u786E\u786E\u8BA4\u4E22\u5F03\u5907\u4EFD\u4E4B\u540E\u7684\u53D8\u66F4\");\n return store.submit(request.method, context => withStoppedServices(context, [...START_ORDER], () => restoreSnapshot(identifier(p.id), context.phase)));\n }\n case \"backups.delete\": return store.submit(request.method, async context => {\n context.phase(\"execute\", \"\u5220\u9664\u5907\u4EFD\u76EE\u5F55\");\n return deleteSnapshot(identifier(p.id));\n });\n case \"startup.plan\": return startupPlan();\n default: throw Object.assign(new Error(`\u4E0D\u652F\u6301\u7684\u7BA1\u7406\u65B9\u6CD5: ${request.method}`), { code: \"unsupported\" });\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1 +1 @@
1
- {"version":3,"file":"stdio.d.ts","sourceRoot":"","sources":["../../src/management/stdio.ts"],"names":[],"mappings":"AAKA,uCAAuC;AACvC,wBAAsB,kBAAkB,kBA+EvC"}
1
+ {"version":3,"file":"stdio.d.ts","sourceRoot":"","sources":["../../src/management/stdio.ts"],"names":[],"mappings":"AA6BA,uCAAuC;AACvC,wBAAsB,kBAAkB,kBAyFvC"}
@@ -1,7 +1,21 @@
1
1
  import readline from "node:readline";
2
2
  import path from "node:path";
3
3
  import fs from "node:fs";
4
+ import { randomUUID } from "node:crypto";
4
5
  import { toManagementError } from "@sfmc-bds/management";
6
+ import { LOCAL_CAPABILITIES, LOCAL_METHODS } from "./local-methods.js";
7
+ function withLocalCapabilities(response) {
8
+ const result = response.result;
9
+ if (!response.ok || !result || !Array.isArray(result.capabilities)) return response;
10
+ const capabilities = [.../* @__PURE__ */ new Set([...result.capabilities, ...LOCAL_CAPABILITIES])];
11
+ return { ...response, result: { ...result, capabilities } };
12
+ }
13
+ async function sendViaDaemon(callDaemon, line) {
14
+ const request = { id: `scoreboard-${randomUUID()}`, method: "services.send", params: { name: "bds", message: line } };
15
+ const result = await callDaemon("management", { request });
16
+ if (result.kind !== "management") throw new Error("\u5B88\u62A4\u8FDB\u7A0B\u6CA1\u6709\u7BA1\u7406\u5165\u53E3\uFF0C\u65E0\u6CD5\u53D1\u9001\u8BA1\u5206\u677F\u547D\u4EE4");
17
+ if (!result.response.ok) throw new Error(result.response.error?.message ?? "\u53D1\u9001\u8BA1\u5206\u677F\u547D\u4EE4\u5931\u8D25");
18
+ }
5
19
  async function runManagementStdio() {
6
20
  const output = process.stdout.write.bind(process.stdout);
7
21
  for (const key of ["log", "info", "warn", "error", "debug"]) console[key] = (...args) => {
@@ -35,7 +49,13 @@ async function runManagementStdio() {
35
49
  output(JSON.stringify({ type: "res", id: request.id, ok: true, result: await metrics.readRuntimeMetrics(request.params) }) + "\n");
36
50
  return;
37
51
  }
38
- if (ready && request.method === "players.list") {
52
+ if (ready && (request.method === "scoreboard.read" || request.method === "scoreboard.apply")) {
53
+ const scoreboard = await import("./scoreboard.js");
54
+ const result = request.method === "scoreboard.read" ? await scoreboard.readScoreboard(request.params) : await scoreboard.applyScoreboard(request.params, (line2) => sendViaDaemon(client.callDaemon, line2));
55
+ output(JSON.stringify({ type: "res", id: request.id, ok: true, result }) + "\n");
56
+ return;
57
+ }
58
+ if (ready && LOCAL_METHODS.has(request.method)) {
39
59
  const backend2 = await import("./server.js");
40
60
  output(JSON.stringify({ type: "res", id: request.id, ok: true, result: await backend2.dispatchManagement(request) }) + "\n");
41
61
  return;
@@ -45,7 +65,7 @@ async function runManagementStdio() {
45
65
  const result = await client.callDaemon("management", { request });
46
66
  if (result.kind !== "management") throw new Error("\u65E7\u5B88\u62A4\u8FDB\u7A0B\u6CA1\u6709\u7BA1\u7406\u5165\u53E3");
47
67
  if (request.method === "events.subscribe" && result.response.ok && !dispose) dispose = await client.ensureDaemonSubscription();
48
- output(JSON.stringify(result.response) + "\n");
68
+ output(JSON.stringify(request.method === "handshake" ? withLocalCapabilities(result.response) : result.response) + "\n");
49
69
  return;
50
70
  } catch (error) {
51
71
  if (request.method !== "handshake" || !/unknown method|管理入口/.test(error instanceof Error ? error.message : String(error))) throw error;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/management/stdio.ts"],
4
- "sourcesContent": ["import readline from \"node:readline\";\nimport path from \"node:path\";\nimport fs from \"node:fs\";\nimport { toManagementError, type ManagementRequest } from \"@sfmc-bds/management\";\n\n/** \u9996\u5E27\u786E\u5B9A\u5B9E\u4F8B\u76EE\u5F55\uFF0C\u4E4B\u540E\u624D\u52A0\u8F7D\u542B ROOT \u5355\u4F8B\u7684 CLI \u4EE3\u7801\u3002 */\nexport async function runManagementStdio() {\n const output = process.stdout.write.bind(process.stdout);\n for (const key of [\"log\", \"info\", \"warn\", \"error\", \"debug\"] as const) console[key] = (...args: unknown[]) => { process.stderr.write(args.map(value => typeof value === \"string\" ? value : JSON.stringify(value)).join(\" \") + \"\\n\"); };\n const lines = readline.createInterface({ input: process.stdin, crlfDelay: Infinity });\n let ready = false;\n let dispose: (() => void) | undefined;\n let forwarding: (() => void) | undefined;\n let legacy = false;\n const pending = new Set<Promise<void>>();\n const processLine = async (line: string) => {\n let request: ManagementRequest = { id: \"invalid\", method: \"invalid\" };\n try {\n if (Buffer.byteLength(line) > 4 * 1024 * 1024) throw new Error(\"\u7BA1\u7406\u5E27\u8FC7\u5927\");\n request = JSON.parse(line) as ManagementRequest;\n if (!request || typeof request.id !== \"string\" || request.id.length > 128 || typeof request.method !== \"string\" || request.method.length > 128) throw new Error(\"\u975E\u6CD5\u7BA1\u7406\u5E27\");\n if (!ready) {\n if (request.method !== \"handshake\") throw new Error(\"\u9996\u4E2A\u8BF7\u6C42\u5FC5\u987B\u4E3A\u63E1\u624B\");\n const params = request.params as { root?: unknown } | undefined;\n if (typeof params?.root !== \"string\" || !path.isAbsolute(params.root) || !fs.statSync(params.root).isDirectory()) throw new Error(\"\u9700\u8981\u6709\u6548\u7684\u5B9E\u4F8B\u7EDD\u5BF9\u76EE\u5F55\");\n process.env.SFMC_ROOT = path.resolve(params.root); ready = true;\n } else if (request.method === \"handshake\" && (request.params as { root?: string } | undefined)?.root && path.resolve((request.params as { root: string }).root) !== process.env.SFMC_ROOT) {\n throw new Error(\"\u4E00\u4E2A\u7BA1\u7406\u4F1A\u8BDD\u53EA\u80FD\u8FDE\u63A5\u4E00\u4E2A\u5B9E\u4F8B\");\n }\n const client = await import(\"../daemon/client.js\");\n if (!forwarding) forwarding = client.onDaemonManagementEvent(event => output(JSON.stringify(event) + \"\\n\"));\n // \u6307\u6807\u548C\u73A9\u5BB6\u540D\u5355\u8BFB\u5F53\u524D\u78C1\u76D8\u4E0A\u7684\u4EE3\u7801\u4E0E\u6570\u636E\u5E93\u3002\u7BA1\u7406\u901A\u9053\u6BCF\u6B21\u8FDE\u63A5\u90FD\u4F1A\u52A0\u8F7D\u65B0\u6587\u4EF6\uFF0C\u4E0D\u5FC5\u4E3A\u6B64\u91CD\u542F\u4ECD\u5728\u6258\u7BA1\u670D\u52A1\u7684\u5B88\u62A4\u8FDB\u7A0B\u3002\n if (ready && request.method === \"metrics.read\") {\n const metrics = await import(\"./metrics-read.js\");\n output(JSON.stringify({ type: \"res\", id: request.id, ok: true, result: await metrics.readRuntimeMetrics(request.params) }) + \"\\n\");\n return;\n }\n if (ready && request.method === \"players.list\") {\n const backend = await import(\"./server.js\");\n output(JSON.stringify({ type: \"res\", id: request.id, ok: true, result: await backend.dispatchManagement(request) }) + \"\\n\");\n return;\n }\n if (!legacy) {\n try {\n const result = await client.callDaemon(\"management\", { request });\n if (result.kind !== \"management\") throw new Error(\"\u65E7\u5B88\u62A4\u8FDB\u7A0B\u6CA1\u6709\u7BA1\u7406\u5165\u53E3\");\n if (request.method === \"events.subscribe\" && result.response.ok && !dispose) dispose = await client.ensureDaemonSubscription();\n output(JSON.stringify(result.response) + \"\\n\");\n return;\n } catch (error) {\n if (request.method !== \"handshake\" || !/unknown method|\u7BA1\u7406\u5165\u53E3/.test(error instanceof Error ? error.message : String(error))) throw error;\n legacy = true;\n try { process.env.SFMC_PLATFORM_VERSION = (JSON.parse(fs.readFileSync(path.join(process.env.SFMC_ROOT!, \"node_modules\", \"@sfmc-bds\", \"sfmc\", \"package.json\"), \"utf8\")) as { version: string }).version; } catch { process.env.SFMC_PLATFORM_VERSION = \"unknown\"; }\n }\n }\n // \u65E7\u90E8\u7F72\u53EA\u5F00\u653E\u63A5\u5165\u89C4\u5212\u3001\u72B6\u6001\u548C\u6301\u4E45\u5316\u4EFB\u52A1\uFF1B\u5347\u7EA7\u4EA4\u7ED9\u72EC\u7ACB\u7EF4\u62A4\u8FDB\u7A0B\u3002\n const backend = await import(\"./server.js\");\n let value: unknown;\n if (request.method === \"handshake\") {\n value = { ...(await backend.dispatchManagement(request) as object), capabilities: [\"services\", \"logs\", \"operations\", \"updates\"], legacy: true };\n } else if (request.method === \"services.list\") {\n const result = await client.callDaemon(\"status\");\n if (result.kind !== \"status\") throw new Error(\"\u65E7\u90E8\u7F72\u65E0\u6CD5\u63D0\u4F9B\u670D\u52A1\u72B6\u6001\");\n value = { rows: result.rows };\n } else if (request.method === \"attachment.plan\" || request.method === \"attachment.apply\") {\n const status = await client.callDaemon(\"status\");\n if (status.kind !== \"status\") throw new Error(\"\u65E7\u90E8\u7F72\u65E0\u6CD5\u63D0\u4F9B\u670D\u52A1\u72B6\u6001\");\n const running = status.rows.filter(row => row.running).map(row => row.name);\n if (request.method === \"attachment.apply\" && running.length) throw Object.assign(new Error(\"\u65E7\u5B88\u62A4\u8FDB\u7A0B\u7F3A\u5C11\u53EF\u786E\u8BA4\u7684\u4F18\u96C5\u7EF4\u62A4\u63A5\u53E3\uFF1B\u8BF7\u5148\u901A\u8FC7\u539F\u7BA1\u7406\u5668\u505C\u6B62\u670D\u52A1\uFF0C\u518D\u6267\u884C\u63A5\u5165\u5347\u7EA7\"), { code: \"conflict\" });\n const plan = await backend.dispatchManagement(request);\n value = request.method === \"attachment.plan\" ? { ...plan as object, externalServices: running } : plan;\n } else if ([\"events.subscribe\", \"logs.tail\", \"operations.list\", \"operations.get\", \"backups.list\"].includes(request.method)) value = await backend.dispatchManagement(request);\n else throw Object.assign(new Error(\"\u65E7\u90E8\u7F72\u9700\u5148\u901A\u8FC7\u63A5\u5165\u6D41\u7A0B\u5347\u7EA7\u5E73\u53F0\uFF0C\u518D\u4F7F\u7528\u5B8C\u6574\u7BA1\u7406\u529F\u80FD\"), { code: \"unsupported\" });\n output(JSON.stringify({ type: \"res\", id: request.id, ok: true, result: value }) + \"\\n\");\n } catch (error) { output(JSON.stringify({ type: \"res\", id: request?.id ?? \"invalid\", ok: false, error: toManagementError(error) }) + \"\\n\"); }\n };\n lines.on(\"line\", line => {\n if (pending.size >= 64) { process.stderr.write(\"\u7BA1\u7406\u8BF7\u6C42\u79EF\u538B\uFF0C\u5173\u95ED\u5F53\u524D\u4F1A\u8BDD\\n\"); lines.close(); return; }\n const action = processLine(line).catch(error => { process.stderr.write(String(error) + \"\\n\"); });\n pending.add(action); void action.finally(() => pending.delete(action));\n });\n // \u6807\u51C6\u8F93\u5165\u5173\u95ED\u8868\u793A\u7BA1\u7406\u7AEF\u79BB\u5F00\u3002\u53EA\u65AD\u5F00\u4E0E\u5B88\u62A4\u8FDB\u7A0B\u7684\u7BA1\u9053\uFF0C\u4E0D\u505C\u6B62\u670D\u52A1\u3002\n await new Promise<void>(resolve => lines.once(\"close\", resolve));\n await Promise.allSettled(pending); dispose?.(); forwarding?.();\n if (ready) (await import(\"../daemon/client.js\")).disconnectDaemonClient();\n}\n"],
5
- "mappings": "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",
6
- "names": ["backend"]
4
+ "sourcesContent": ["import readline from \"node:readline\";\nimport path from \"node:path\";\nimport fs from \"node:fs\";\nimport { randomUUID } from \"node:crypto\";\nimport { toManagementError, type ManagementRequest } from \"@sfmc-bds/management\";\nimport { LOCAL_CAPABILITIES, LOCAL_METHODS } from \"./local-methods.js\";\n\n/**\n * \u5B88\u62A4\u8FDB\u7A0B\u53EF\u80FD\u4ECD\u5728\u8FD0\u884C\u5347\u7EA7\u524D\u7684\u4EE3\u7801\uFF0C\u63E1\u624B\u7ED3\u679C\u91CC\u7F3A\u5C11\u672C\u5730\u65B9\u6CD5\u7684\u80FD\u529B\u3002\n * \u672C\u8FDB\u7A0B\u4F1A\u76F4\u63A5\u5904\u7406\u8FD9\u4E9B\u65B9\u6CD5\uFF0C\u6240\u4EE5\u628A\u80FD\u529B\u8865\u8FDB\u6210\u529F\u7684\u63E1\u624B\u54CD\u5E94\uFF1B\u5931\u8D25\u54CD\u5E94\u539F\u6837\u8FD4\u56DE\u3002\n */\nfunction withLocalCapabilities<T extends { ok: boolean; result?: unknown }>(response: T): T {\n const result = response.result as { capabilities?: unknown } | undefined;\n if (!response.ok || !result || !Array.isArray(result.capabilities)) return response;\n const capabilities = [...new Set([...(result.capabilities as string[]), ...LOCAL_CAPABILITIES])];\n return { ...response, result: { ...result, capabilities } };\n}\n\n/**\n * \u7ECF\u5B88\u62A4\u8FDB\u7A0B\u7684 services.send \u5411 BDS \u63A7\u5236\u53F0\u5199\u5165\u4E00\u884C\u547D\u4EE4\uFF1B\u5B88\u62A4\u8FDB\u7A0B\u8FD4\u56DE\u5931\u8D25\u65F6\u629B\u51FA\u5176\u9519\u8BEF\u4FE1\u606F\u3002\n * \u4F7F\u7528\u573A\u666F\uFF1Astdio \u4F1A\u8BDD\u5904\u7406 scoreboard.apply\uFF08BDS \u6807\u51C6\u8F93\u5165\u53EA\u5728\u5B88\u62A4\u8FDB\u7A0B\u624B\u91CC\uFF09\u3002\n */\nasync function sendViaDaemon(callDaemon: typeof import(\"../daemon/client.js\").callDaemon, line: string): Promise<void> {\n const request: ManagementRequest = { id: `scoreboard-${randomUUID()}`, method: \"services.send\", params: { name: \"bds\", message: line } };\n const result = await callDaemon(\"management\", { request });\n if (result.kind !== \"management\") throw new Error(\"\u5B88\u62A4\u8FDB\u7A0B\u6CA1\u6709\u7BA1\u7406\u5165\u53E3\uFF0C\u65E0\u6CD5\u53D1\u9001\u8BA1\u5206\u677F\u547D\u4EE4\");\n if (!result.response.ok) throw new Error(result.response.error?.message ?? \"\u53D1\u9001\u8BA1\u5206\u677F\u547D\u4EE4\u5931\u8D25\");\n}\n\n/** \u9996\u5E27\u786E\u5B9A\u5B9E\u4F8B\u76EE\u5F55\uFF0C\u4E4B\u540E\u624D\u52A0\u8F7D\u542B ROOT \u5355\u4F8B\u7684 CLI \u4EE3\u7801\u3002 */\nexport async function runManagementStdio() {\n const output = process.stdout.write.bind(process.stdout);\n for (const key of [\"log\", \"info\", \"warn\", \"error\", \"debug\"] as const) console[key] = (...args: unknown[]) => { process.stderr.write(args.map(value => typeof value === \"string\" ? value : JSON.stringify(value)).join(\" \") + \"\\n\"); };\n const lines = readline.createInterface({ input: process.stdin, crlfDelay: Infinity });\n let ready = false;\n let dispose: (() => void) | undefined;\n let forwarding: (() => void) | undefined;\n let legacy = false;\n const pending = new Set<Promise<void>>();\n const processLine = async (line: string) => {\n let request: ManagementRequest = { id: \"invalid\", method: \"invalid\" };\n try {\n if (Buffer.byteLength(line) > 4 * 1024 * 1024) throw new Error(\"\u7BA1\u7406\u5E27\u8FC7\u5927\");\n request = JSON.parse(line) as ManagementRequest;\n if (!request || typeof request.id !== \"string\" || request.id.length > 128 || typeof request.method !== \"string\" || request.method.length > 128) throw new Error(\"\u975E\u6CD5\u7BA1\u7406\u5E27\");\n if (!ready) {\n if (request.method !== \"handshake\") throw new Error(\"\u9996\u4E2A\u8BF7\u6C42\u5FC5\u987B\u4E3A\u63E1\u624B\");\n const params = request.params as { root?: unknown } | undefined;\n if (typeof params?.root !== \"string\" || !path.isAbsolute(params.root) || !fs.statSync(params.root).isDirectory()) throw new Error(\"\u9700\u8981\u6709\u6548\u7684\u5B9E\u4F8B\u7EDD\u5BF9\u76EE\u5F55\");\n process.env.SFMC_ROOT = path.resolve(params.root); ready = true;\n } else if (request.method === \"handshake\" && (request.params as { root?: string } | undefined)?.root && path.resolve((request.params as { root: string }).root) !== process.env.SFMC_ROOT) {\n throw new Error(\"\u4E00\u4E2A\u7BA1\u7406\u4F1A\u8BDD\u53EA\u80FD\u8FDE\u63A5\u4E00\u4E2A\u5B9E\u4F8B\");\n }\n const client = await import(\"../daemon/client.js\");\n if (!forwarding) forwarding = client.onDaemonManagementEvent(event => output(JSON.stringify(event) + \"\\n\"));\n // \u6307\u6807\u548C\u73A9\u5BB6\u540D\u5355\u8BFB\u5F53\u524D\u78C1\u76D8\u4E0A\u7684\u4EE3\u7801\u4E0E\u6570\u636E\u5E93\u3002\u7BA1\u7406\u901A\u9053\u6BCF\u6B21\u8FDE\u63A5\u90FD\u4F1A\u52A0\u8F7D\u65B0\u6587\u4EF6\uFF0C\u4E0D\u5FC5\u4E3A\u6B64\u91CD\u542F\u4ECD\u5728\u6258\u7BA1\u670D\u52A1\u7684\u5B88\u62A4\u8FDB\u7A0B\u3002\n if (ready && request.method === \"metrics.read\") {\n const metrics = await import(\"./metrics-read.js\");\n output(JSON.stringify({ type: \"res\", id: request.id, ok: true, result: await metrics.readRuntimeMetrics(request.params) }) + \"\\n\");\n return;\n }\n // \u8BA1\u5206\u677F\u540C\u6837\u7528\u78C1\u76D8\u4E0A\u7684\u65B0\u4EE3\u7801\u5904\u7406\uFF1A\u8BFB\u53D6\u8D70\u6570\u636E\u670D\u52A1\uFF1B\u5199\u5165\u751F\u6210\u547D\u4EE4\u540E\u8F6C\u4EA4\u5B88\u62A4\u8FDB\u7A0B\u7684 services.send\uFF0C\n // \u65E7\u5B88\u62A4\u8FDB\u7A0B\u4E5F\u80FD\u5199\u5165\u5B83\u6258\u7BA1\u7684 BDS \u6807\u51C6\u8F93\u5165\uFF0C\u4E0D\u5FC5\u4E3A\u6B64\u91CD\u542F\u3002\n if (ready && (request.method === \"scoreboard.read\" || request.method === \"scoreboard.apply\")) {\n const scoreboard = await import(\"./scoreboard.js\");\n const result = request.method === \"scoreboard.read\"\n ? await scoreboard.readScoreboard(request.params)\n : await scoreboard.applyScoreboard(request.params, line => sendViaDaemon(client.callDaemon, line));\n output(JSON.stringify({ type: \"res\", id: request.id, ok: true, result }) + \"\\n\");\n return;\n }\n if (ready && LOCAL_METHODS.has(request.method)) {\n const backend = await import(\"./server.js\");\n output(JSON.stringify({ type: \"res\", id: request.id, ok: true, result: await backend.dispatchManagement(request) }) + \"\\n\");\n return;\n }\n if (!legacy) {\n try {\n const result = await client.callDaemon(\"management\", { request });\n if (result.kind !== \"management\") throw new Error(\"\u65E7\u5B88\u62A4\u8FDB\u7A0B\u6CA1\u6709\u7BA1\u7406\u5165\u53E3\");\n if (request.method === \"events.subscribe\" && result.response.ok && !dispose) dispose = await client.ensureDaemonSubscription();\n output(JSON.stringify(request.method === \"handshake\" ? withLocalCapabilities(result.response) : result.response) + \"\\n\");\n return;\n } catch (error) {\n if (request.method !== \"handshake\" || !/unknown method|\u7BA1\u7406\u5165\u53E3/.test(error instanceof Error ? error.message : String(error))) throw error;\n legacy = true;\n try { process.env.SFMC_PLATFORM_VERSION = (JSON.parse(fs.readFileSync(path.join(process.env.SFMC_ROOT!, \"node_modules\", \"@sfmc-bds\", \"sfmc\", \"package.json\"), \"utf8\")) as { version: string }).version; } catch { process.env.SFMC_PLATFORM_VERSION = \"unknown\"; }\n }\n }\n // \u65E7\u90E8\u7F72\u53EA\u5F00\u653E\u63A5\u5165\u89C4\u5212\u3001\u72B6\u6001\u548C\u6301\u4E45\u5316\u4EFB\u52A1\uFF1B\u5347\u7EA7\u4EA4\u7ED9\u72EC\u7ACB\u7EF4\u62A4\u8FDB\u7A0B\u3002\n const backend = await import(\"./server.js\");\n let value: unknown;\n if (request.method === \"handshake\") {\n value = { ...(await backend.dispatchManagement(request) as object), capabilities: [\"services\", \"logs\", \"operations\", \"updates\"], legacy: true };\n } else if (request.method === \"services.list\") {\n const result = await client.callDaemon(\"status\");\n if (result.kind !== \"status\") throw new Error(\"\u65E7\u90E8\u7F72\u65E0\u6CD5\u63D0\u4F9B\u670D\u52A1\u72B6\u6001\");\n value = { rows: result.rows };\n } else if (request.method === \"attachment.plan\" || request.method === \"attachment.apply\") {\n const status = await client.callDaemon(\"status\");\n if (status.kind !== \"status\") throw new Error(\"\u65E7\u90E8\u7F72\u65E0\u6CD5\u63D0\u4F9B\u670D\u52A1\u72B6\u6001\");\n const running = status.rows.filter(row => row.running).map(row => row.name);\n if (request.method === \"attachment.apply\" && running.length) throw Object.assign(new Error(\"\u65E7\u5B88\u62A4\u8FDB\u7A0B\u7F3A\u5C11\u53EF\u786E\u8BA4\u7684\u4F18\u96C5\u7EF4\u62A4\u63A5\u53E3\uFF1B\u8BF7\u5148\u901A\u8FC7\u539F\u7BA1\u7406\u5668\u505C\u6B62\u670D\u52A1\uFF0C\u518D\u6267\u884C\u63A5\u5165\u5347\u7EA7\"), { code: \"conflict\" });\n const plan = await backend.dispatchManagement(request);\n value = request.method === \"attachment.plan\" ? { ...plan as object, externalServices: running } : plan;\n } else if ([\"events.subscribe\", \"logs.tail\", \"operations.list\", \"operations.get\", \"backups.list\"].includes(request.method)) value = await backend.dispatchManagement(request);\n else throw Object.assign(new Error(\"\u65E7\u90E8\u7F72\u9700\u5148\u901A\u8FC7\u63A5\u5165\u6D41\u7A0B\u5347\u7EA7\u5E73\u53F0\uFF0C\u518D\u4F7F\u7528\u5B8C\u6574\u7BA1\u7406\u529F\u80FD\"), { code: \"unsupported\" });\n output(JSON.stringify({ type: \"res\", id: request.id, ok: true, result: value }) + \"\\n\");\n } catch (error) { output(JSON.stringify({ type: \"res\", id: request?.id ?? \"invalid\", ok: false, error: toManagementError(error) }) + \"\\n\"); }\n };\n lines.on(\"line\", line => {\n if (pending.size >= 64) { process.stderr.write(\"\u7BA1\u7406\u8BF7\u6C42\u79EF\u538B\uFF0C\u5173\u95ED\u5F53\u524D\u4F1A\u8BDD\\n\"); lines.close(); return; }\n const action = processLine(line).catch(error => { process.stderr.write(String(error) + \"\\n\"); });\n pending.add(action); void action.finally(() => pending.delete(action));\n });\n // \u6807\u51C6\u8F93\u5165\u5173\u95ED\u8868\u793A\u7BA1\u7406\u7AEF\u79BB\u5F00\u3002\u53EA\u65AD\u5F00\u4E0E\u5B88\u62A4\u8FDB\u7A0B\u7684\u7BA1\u9053\uFF0C\u4E0D\u505C\u6B62\u670D\u52A1\u3002\n await new Promise<void>(resolve => lines.once(\"close\", resolve));\n await Promise.allSettled(pending); dispose?.(); forwarding?.();\n if (ready) (await import(\"../daemon/client.js\")).disconnectDaemonClient();\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["line", "backend"]
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sfmc-bds/cli",
3
- "version": "0.8.0",
3
+ "version": "0.10.0",
4
4
  "description": "SFMC management CLI — REPL, service supervisor, module install, behavior-pack build/deploy",
5
5
  "author": "Shiroha7z",
6
6
  "license": "AGPL-3.0-only",
@@ -55,14 +55,14 @@
55
55
  "esbuild": "^0.28.1",
56
56
  "ajv": "8.20.0",
57
57
  "jsonc-parser": "3.3.1",
58
- "@sfmc-bds/bds-tools": "0.3.0",
59
- "@sfmc-bds/devkit": "2.0.7",
60
- "@sfmc-bds/sdk": "0.6.0",
61
- "@sfmc-bds/management": "0.7.0",
62
- "@sfmc-bds/db-server": "0.6.0"
58
+ "@sfmc-bds/bds-tools": "0.3.1",
59
+ "@sfmc-bds/devkit": "2.0.8",
60
+ "@sfmc-bds/sdk": "0.7.0",
61
+ "@sfmc-bds/management": "0.9.0",
62
+ "@sfmc-bds/db-server": "0.8.0"
63
63
  },
64
64
  "devDependencies": {
65
- "@sfmc-bds/tools": "0.2.11"
65
+ "@sfmc-bds/tools": "0.2.12"
66
66
  },
67
67
  "publishConfig": {
68
68
  "access": "public",
@@ -1,5 +1,5 @@
1
1
  {
2
- "fetchedAt": 1792926615467,
2
+ "fetchedAt": 1792928891224,
3
3
  "index": {
4
4
  "activity-log": {
5
5
  "npm": "@sfmc-bds/module-activity-log",
@@ -165,9 +165,9 @@
165
165
  },
166
166
  "online-time": {
167
167
  "npm": "@sfmc-bds/module-online-time",
168
- "version": "0.2.2",
168
+ "version": "1.0.0",
169
169
  "sdk": ">=0.2.0-beta.17",
170
- "repo": "https://github.com/Tanya7z/sfmc-module-online-time",
170
+ "repo": "https://github.com/DogeLakeDev/sfmc-module-online-time",
171
171
  "name": "在线时长统计",
172
172
  "description": "进服打点与心跳增量结转在线统计",
173
173
  "category": "utility",