From bc07e8b4831cbd564c684d8c604f6d035399b5eb Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Thu, 23 Jul 2026 08:26:25 +0000 Subject: [PATCH 1/2] =?UTF-8?q?fix(db-server):=20=E7=BB=8F=E6=B5=8E?= =?UTF-8?q?=E8=A1=8C=E7=B1=BB=E5=9E=8B=E5=86=85=E8=81=9A=E5=88=B0=20domain?= =?UTF-8?q?=EF=BC=8C=E4=BF=AE=E5=A4=8D=20contracts=20=E7=B2=BE=E7=AE=80?= =?UTF-8?q?=E5=90=8E=E6=9E=84=E5=BB=BA=E5=A4=B1=E8=B4=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SDK 移除 economy 契约后 db-server 仍从 @sfmc-bds/sdk/contracts 导入, 导致 ootb 在 emitDeclarationOnly 阶段失败。行模型改由表所有者本地定义 (DIP/DRY),并同步 contracts 文档描述。 Co-authored-by: Shiroha --- db-server/src/domain/economy.ts | 32 +++++++++++++++++++++++++++++--- docs/api/sdk/README.md | 2 +- modules/sdk/@sfmc-sdk/README.md | 2 +- 3 files changed, 31 insertions(+), 5 deletions(-) diff --git a/db-server/src/domain/economy.ts b/db-server/src/domain/economy.ts index bcea7801..f5a30e70 100644 --- a/db-server/src/domain/economy.ts +++ b/db-server/src/domain/economy.ts @@ -10,7 +10,6 @@ * alreadyInTx=true 时只跑 steps */ -import type { EconomyAccountRow, EconomyTransactionRow } from "@sfmc-bds/sdk/contracts"; import type { DatabaseSync } from "node:sqlite"; import type { SQLStatement } from "sql-template-strings"; import { isValidIdempotencyKey } from "../lib/idempotency.js"; @@ -18,6 +17,35 @@ import { sql } from "../lib/sql-helpers.js"; import type { TxResult } from "./transaction.js"; export type { TxResult }; +/** + * 经济域行模型(原 SDK contracts/economy;契约内聚到表所有者 db-server)。 + * 业务模块应通过 service(economy.*) 消费视图,不依赖这些内部行类型。 + */ +export interface EconomyAccountRow { + player_id: string; + player_name_snapshot: string; + balance: number; + version: number; + created_at: number; + updated_at: number; +} + +export interface EconomyTransactionRow { + id: string; + transaction_type: string; + actor_id: string; + source_player_id?: string; + target_player_id?: string; + amount: number; + balance_before?: number; + balance_after?: number; + reference_type: string; + reference_id: string; + reason: string; + created_at: number; + idempotency_key: string; +} + const TABLE_ACCOUNTS = "sfmc_economy_accounts"; const TABLE_TRANSACTIONS = "sfmc_economy_transactions"; const TABLE_IDEMPOTENCY = "sfmc_economy_idempotency"; @@ -337,8 +365,6 @@ export function applyEconomyTransaction( } } -export type { EconomyAccountRow, EconomyTransactionRow }; - /** 列出日常任务(默认仅 active 且未过期) */ export function listDailyTasks( query: AnyQuery, diff --git a/docs/api/sdk/README.md b/docs/api/sdk/README.md index 30cd18ec..ccfa88b9 100644 --- a/docs/api/sdk/README.md +++ b/docs/api/sdk/README.md @@ -21,7 +21,7 @@ import { ModuleRegistry } from "@sfmc-bds/sdk/module-loader"; |------|------| | `@sfmc-bds/sdk/module-loader` | ModuleRegistry、ConfigManager、installHostBootstrap | | `@sfmc-bds/sdk/sapi/host` | 平台 host 适配 | -| `@sfmc-bds/sdk/contracts` | 跨端共享类型 | +| `@sfmc-bds/sdk/contracts` | 平台级共享类型(catalog / lock) | | `@sfmc-bds/sdk/node/config` | Node 侧读 configs | | `@sfmc-bds/sdk/node/sdk` | Node 服务统一能力 | | `@sfmc-bds/sdk/logs` | 日志 | diff --git a/modules/sdk/@sfmc-sdk/README.md b/modules/sdk/@sfmc-sdk/README.md index 58bf8a51..8f92079b 100644 --- a/modules/sdk/@sfmc-sdk/README.md +++ b/modules/sdk/@sfmc-sdk/README.md @@ -2,7 +2,7 @@ ScriptsForMinecraftServer 平台 SDK。SAPI/Node umbrella,统一导出: -- **`@sfmc-bds/sdk/contracts`** — 跨模块共享类型契约(land / chat / coop / economy / player / world / 等) +- **`@sfmc-bds/sdk/contracts`** — 平台级共享类型(模块 catalog / lock;业务域类型由各模块自维护) - **`@sfmc-bds/sdk/sapi/runtime`** — SAPI 进程内运行时:`Msg` / `Command` / `Permission` / `MenuNavigator` / `Money` / `debug` - **`@sfmc-bds/sdk/sapi/db`** — 数据库友好 API:`db.defineTable` / `db.tx` / `db.query` / `db.audit` / `db.idempotent` - **`@sfmc-bds/sdk/sapi/config`** — 模块配置:`config.get` / `config.set` / `config.onChange` From 9ed2c01de58aa0c2b7c3b36ffd6483e1b4f13eea Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Thu, 23 Jul 2026 08:26:25 +0000 Subject: [PATCH 2/2] =?UTF-8?q?fix(bds-tools/sfmc):=20=E8=A7=A3=E9=99=A4?= =?UTF-8?q?=20qqutil=E2=86=94check-update=20=E5=BE=AA=E7=8E=AF=E4=BE=9D?= =?UTF-8?q?=E8=B5=96=EF=BC=8C=E4=BF=AE=E6=AD=A3=20SEA=20=E7=BB=88=E7=AB=AF?= =?UTF-8?q?=20commandline?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit qqutil 误从 check-update 取 log 形成环依赖(Demeter/DIP);改回 log.js。 preferredPowerShell 现返回完整 sfmc commandline,保留已发现的 pwsh 绝对路径 并加引号,避免 Program Files 路径与 PATH 不一致。 Co-authored-by: Shiroha --- bds-tools/src/check-update.ts | 2 +- bds-tools/src/qqutil.ts | 2 +- sfmc/src/terminal.ts | 19 ++++++++++++------- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/bds-tools/src/check-update.ts b/bds-tools/src/check-update.ts index 326fd4d7..07bb47ff 100644 --- a/bds-tools/src/check-update.ts +++ b/bds-tools/src/check-update.ts @@ -41,7 +41,7 @@ import { compareVersions, getCurrentVersionAsync, getCurrentVersionSync, saveVer // 独立入口:source = "updater",与 bds-manager 的 "bds-tools" 区分 const updaterFileSink = createFileSink(LOG_PATH); -export const log = createLogger({ source: "updater", sinks: [createStdoutSink({ bare: true }), updaterFileSink] }); +const log = createLogger({ source: "updater", sinks: [createStdoutSink({ bare: true }), updaterFileSink] }); const closeLog = (): void => updaterFileSink.close(); function parseArgs(argv: string[]): Record { diff --git a/bds-tools/src/qqutil.ts b/bds-tools/src/qqutil.ts index 2817b57f..60c38dfc 100644 --- a/bds-tools/src/qqutil.ts +++ b/bds-tools/src/qqutil.ts @@ -15,7 +15,7 @@ import { type QQBridgeConfig, } from "@sfmc-bds/sdk/node/config"; import http from "node:http"; -import { log } from "./check-update.js"; +import { log } from "./log.js"; import { ROOT_DIR } from "./paths.js"; type QqConfig = Pick; diff --git a/sfmc/src/terminal.ts b/sfmc/src/terminal.ts index 59a3c7c3..e4ba5222 100644 --- a/sfmc/src/terminal.ts +++ b/sfmc/src/terminal.ts @@ -55,7 +55,8 @@ function terminalSettingsFiles(): string[] { .filter((file) => fs.existsSync(file)); } -function preferredPowerShell(): string { +/** Windows Terminal profile.commandline:启动 shell 并立即进入 sfmc */ +function preferredSfmcCommandline(): string { const programFiles = [process.env.ProgramW6432, process.env.ProgramFiles].filter((value): value is string => Boolean(value) ); @@ -66,14 +67,18 @@ function preferredPowerShell(): string { ]; const installed = candidates.find((candidate) => fs.existsSync(candidate)); - if (installed) return "pwsh -Command sfmc"; + if (installed) return `"${installed}" -Command sfmc`; if (spawnSync("pwsh.exe", ["-NoProfile", "-Command", "exit"], { stdio: "ignore", windowsHide: true }).status === 0) { - return "pwsh -Command sfmc"; + return "pwsh.exe -Command sfmc"; } - return ( - path.join(process.env.SystemRoot ?? "C:\\Windows", "System32", "WindowsPowerShell", "v1.0", "powershell.exe") + - " -Command sfmc" + const windowsPowerShell = path.join( + process.env.SystemRoot ?? "C:\\Windows", + "System32", + "WindowsPowerShell", + "v1.0", + "powershell.exe" ); + return `"${windowsPowerShell}" -Command sfmc`; } function newGuid(): string { @@ -203,5 +208,5 @@ export function ensureSeaTerminalProfile(): void { const runtimeFile = configPath(ROOT, "runtime.json"); const state = terminalState(runtimeFile, path.dirname(process.execPath)); - for (const settingsFile of settingsFiles) updateProfile(settingsFile, state, preferredPowerShell()); + for (const settingsFile of settingsFiles) updateProfile(settingsFile, state, preferredSfmcCommandline()); }