From 3625a98365b12d39ff8845a572b1dda2289f96ae Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Tue, 21 Jul 2026 17:14:58 +0000 Subject: [PATCH 1/4] =?UTF-8?q?fix(tools):=20check-catalog.js=20=E6=94=B9?= =?UTF-8?q?=E7=94=A8=20CommonJS=20require=EF=BC=8C=E9=81=BF=E5=85=8D=20CI?= =?UTF-8?q?=20=E5=9B=BA=E5=AE=9A=20Node=2022.5.x=20=E4=B8=8A=E7=9A=84=20ES?= =?UTF-8?q?M=20SyntaxError?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit check-catalog.js 此前用 import/import.meta.url 编写,但仓库根 package.json 未 声明 "type": "module",且与其余 tools/*.js(均为 CommonJS)风格不一致。 本地较新的 Node(22.14+)具备自动模块语法探测所以能跑通,但 ootb.yml 固定 的 node-version: '22.5' 解析出的 22.5.1 不支持该探测,直接抛出 'Cannot use import statement outside a module',导致 check-ootb 第 3 项 必然失败。改为 require + __dirname 后不再依赖 Node 版本的探测行为。 Co-authored-by: Shiroha --- tools/check-catalog.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/tools/check-catalog.js b/tools/check-catalog.js index 26a3f4a..0a92ccb 100644 --- a/tools/check-catalog.js +++ b/tools/check-catalog.js @@ -11,12 +11,14 @@ * - entry.init 仅在 sapi 类型可选 * - 不允许循环依赖(拓扑排序检测) */ -import { accessSync, constants, readFileSync } from "node:fs"; -import { resolve, join, dirname } from "node:path"; -import { fileURLToPath } from 'node:url'; -import path from "node:path"; +const { accessSync, constants, readFileSync } = require("node:fs"); +const { resolve, join } = require("node:path"); +const path = require("node:path"); -const ROOT = resolve(dirname(fileURLToPath(import.meta.url)), ".."); +// 与其余 tools/*.js 保持一致的 CommonJS 写法:仓库根 package.json 未设置 +// "type": "module",若沿用 import 语法,在未启用模块语法自动探测的 Node 版本 +// (例如 CI 固定的 22.5.x)上会直接抛出 SyntaxError。 +const ROOT = resolve(__dirname, ".."); const CATALOG = join(ROOT, "modules", "catalog.json"); const SERVICES_CATALOG = join(ROOT, "services", "catalog.json"); /* SAPI modules no longer register through a single static entry.ts — From 25c0daa2cccdd02d189d22f874bbad9a3d8c7af0 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Tue, 21 Jul 2026 17:15:09 +0000 Subject: [PATCH 2/4] =?UTF-8?q?fix(tools):=20=E4=BF=AE=E6=AD=A3=20db-serve?= =?UTF-8?q?r=20=E5=85=A5=E5=8F=A3=E8=B7=AF=E5=BE=84=20=E2=80=94=E2=80=94?= =?UTF-8?q?=20db-server/index.js=20=E4=B8=8D=E5=AD=98=E5=9C=A8=EF=BC=8C?= =?UTF-8?q?=E5=BA=94=E4=B8=BA=20dist/index.js?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit db-server 只在 package.json#main 指向 dist/index.js(编译产物),仓库里 从没有 db-server/index.js 这个文件(历史上曾存在,后作为死代码被删除, 但引用它的三处调用点没有同步更新)。这导致: - check-ootb.js 第 6 项 'db-server 启动 + 模块接口' 必然报 'db-server 不可达' - check-ootb.js 第 7 项内部调用的 sim-new-user.js 必然超时 - tools/test-db-api.js 手测脚本同样起不来 db-server 统一改为 db-server/dist/index.js。顺带修正 test-db-api.js 里写入的 临时 db_config.json,其 modulesDir 沿用了同一处 '../modules' 笔误 (见下一条 commit 对 configs-default 的修正),改为与新建的 workspace/modules 目录匹配的 'modules'。 Co-authored-by: Shiroha --- tools/check-ootb.js | 2 +- tools/sim-new-user.js | 2 +- tools/test-db-api.js | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/check-ootb.js b/tools/check-ootb.js index 970b038..240bb13 100644 --- a/tools/check-ootb.js +++ b/tools/check-ootb.js @@ -106,7 +106,7 @@ function fileContains(p, needle) { { let dbProc = null; try { - dbProc = spawn(process.execPath, [path.join(ROOT, "db-server", "index.js")], { + dbProc = spawn(process.execPath, [path.join(ROOT, "db-server", "dist", "index.js")], { cwd: ROOT, env: { ...process.env }, stdio: ["ignore", "pipe", "pipe"], diff --git a/tools/sim-new-user.js b/tools/sim-new-user.js index 18990b9..8206073 100644 --- a/tools/sim-new-user.js +++ b/tools/sim-new-user.js @@ -30,7 +30,7 @@ let dbProc = null; function startDb(simDir) { const env = { ...process.env, SFMC_ROOT: simDir, DB_PORT: String(DB_PORT) }; - dbProc = spawn(process.execPath, [path.join(ROOT, "db-server", "index.js")], { + dbProc = spawn(process.execPath, [path.join(ROOT, "db-server", "dist", "index.js")], { cwd: ROOT, env, stdio: ["ignore", "pipe", "pipe"], diff --git a/tools/test-db-api.js b/tools/test-db-api.js index b82892d..cee487a 100644 --- a/tools/test-db-api.js +++ b/tools/test-db-api.js @@ -62,11 +62,11 @@ async function main() { copy(path.join(ROOT, 'modules', 'module-lock.json'), path.join(workspace, 'modules', 'module-lock.json')); fs.mkdirSync(path.join(workspace, 'data'), { recursive: true }); fs.mkdirSync(path.join(workspace, 'configs'), { recursive: true }); - fs.writeFileSync(path.join(workspace, 'configs', 'db_config.json'), JSON.stringify({ db_port: PORT, dbDir: './data/sfmc_data.db', modulesDir: '../modules' }) + '\n'); + fs.writeFileSync(path.join(workspace, 'configs', 'db_config.json'), JSON.stringify({ db_port: PORT, dbDir: './data/sfmc_data.db', modulesDir: 'modules' }) + '\n'); copy(path.join(ROOT, 'configs', 'qq_config.json'), path.join(workspace, 'configs', 'qq_config.json')); copy(path.join(ROOT, 'configs', 'settings.json'), path.join(workspace, 'configs', 'settings.json')); - const child = spawn(process.execPath, [path.join(ROOT, 'db-server', 'index.js')], { + const child = spawn(process.execPath, [path.join(ROOT, 'db-server', 'dist', 'index.js')], { cwd: ROOT, env: { ...process.env, SFMC_ROOT: workspace, SFMC_DB_PATH: dbPath, SFMC_MODULES_DIR: path.join(workspace, 'modules'), DB_PORT: String(PORT) }, stdio: ['ignore', 'pipe', 'pipe'], From febc2f5347c51f88362585ea32eb58bbdf8dfb0a Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Tue, 21 Jul 2026 17:15:17 +0000 Subject: [PATCH 3/4] =?UTF-8?q?fix(configs):=20db=5Fconfig.json=20?= =?UTF-8?q?=E9=BB=98=E8=AE=A4=20modulesDir=20=E5=BA=94=E4=B8=BA=E7=9B=B8?= =?UTF-8?q?=E5=AF=B9=E4=BB=93=E5=BA=93=E6=A0=B9=E7=9A=84=20'modules'?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit db-server/src/env.ts 用 resolve(PROJECT_ROOT, dbconfig.modulesDir) 解析 modulesDir,PROJECT_ROOT 就是仓库根(SFMC_ROOT)。默认模板写的 '../modules' 会解析到仓库根的上一级目录(即仓库外部),导致 GET /api/sfmc/modules/catalog 读到空目录、模块列表永远为空, 命中 AGENTS.md 里记录的已知坑。改为 'modules',与 'configs/ 缺失时回退到 join(PROJECT_ROOT, "modules")' 的默认行为保持一致。 Co-authored-by: Shiroha --- configs-default/db_config.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configs-default/db_config.json b/configs-default/db_config.json index 0dff98e..c1380db 100644 --- a/configs-default/db_config.json +++ b/configs-default/db_config.json @@ -3,5 +3,5 @@ "db_port": 3001, "http_auth": "", "dbDir": "./data/sfmc_data.db", - "modulesDir": "../modules" + "modulesDir": "modules" } From 8fd1c1602079ec7b8abe13da61f4640c2e2c0a9b Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Tue, 21 Jul 2026 17:15:26 +0000 Subject: [PATCH 4/4] =?UTF-8?q?ci(ootb):=20=E6=9E=84=E5=BB=BA=E5=90=8E?= =?UTF-8?q?=E4=BB=8E=20configs-default/=20=E8=A1=A5=E5=85=A8=20configs/?= =?UTF-8?q?=EF=BC=8C=E4=BF=AE=E5=A4=8D=20CI=20=E5=BF=85=E7=84=B6=E5=A4=B1?= =?UTF-8?q?=E8=B4=A5=E7=9A=84=20'=E5=BF=85=E5=A4=87=E4=BB=93=E5=BA=93?= =?UTF-8?q?=E6=96=87=E4=BB=B6=E9=BD=90=E5=85=A8'=20=E6=A3=80=E6=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit configs/ 在 .gitignore 中被忽略,全新 checkout(包括 CI runner)不会带上 db_config.json / bds_updater.json / qq_config.json。本地开发时靠 'sfmc init' 交互式向导写入,但 CI 里没有 TTY 跑不了向导,而 check-ootb.js 的第 1 项检查又要求这些文件必须存在于仓库工作区中,于是每次 push 到 main/refactor/** 都必然失败。新增一步,在 build 之后、check-ootb 之前, 从 configs-default/*.json 补全 configs/(已存在的文件不覆盖,保留人工 写入的真实配置)。 Co-authored-by: Shiroha --- .github/workflows/ootb.yml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/.github/workflows/ootb.yml b/.github/workflows/ootb.yml index c6ac97d..1f253e9 100644 --- a/.github/workflows/ootb.yml +++ b/.github/workflows/ootb.yml @@ -27,6 +27,20 @@ jobs: shell: pwsh run: npm run build --workspaces --if-present + - name: Populate default configs + shell: pwsh + run: | + # configs/ 在 .gitignore 中被忽略,全新 checkout 不会带上它。 + # 正常使用时由 `sfmc init` 向导写入;CI 里没有交互式向导, + # 所以直接从 configs-default/ 补全,避免 check-ootb 因缺文件而失败。 + New-Item -ItemType Directory -Force -Path configs | Out-Null + Get-ChildItem -Path configs-default -Filter *.json | ForEach-Object { + $dest = Join-Path configs $_.Name + if (-not (Test-Path $dest)) { + Copy-Item -Path $_.FullName -Destination $dest + } + } + - name: Run check-ootb shell: pwsh run: node tools/check-ootb.js