@sfmc-bds/cli 0.2.0-beta.11 → 0.2.0-beta.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands.d.ts +57 -4
- package/dist/commands.d.ts.map +1 -1
- package/dist/commands.js.map +2 -2
- package/dist/module-commands.d.ts.map +1 -1
- package/dist/module-commands.js +5 -2
- package/dist/module-commands.js.map +2 -2
- package/dist/module-toggle.d.ts +1 -1
- package/dist/module-toggle.d.ts.map +1 -1
- package/dist/module-toggle.js.map +1 -1
- package/dist/pack-lifecycle.js +1 -1
- package/dist/pack-lifecycle.js.map +2 -2
- package/dist/services.d.ts +14 -0
- package/dist/services.d.ts.map +1 -1
- package/dist/services.js.map +2 -2
- package/dist/wizard.d.ts.map +1 -1
- package/dist/wizard.js +20 -22
- package/dist/wizard.js.map +2 -2
- package/package.json +4 -4
- package/scripts/module-install/check-modules.mjs +10 -76
- package/scripts/module-install/lib/catalog.mjs +1 -1
- package/scripts/module-install/lib/lock.mjs +2 -2
- package/scripts/module-install/lib/packages.mjs +16 -22
package/dist/wizard.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/wizard.ts"],
|
|
4
|
-
"sourcesContent": ["import { confirm, intro, isCancel, multiselect, note, outro, password, select, tasks, text } from \"@clack/prompts\";\nimport {\n configPath,\n ensureCoreConfigs,\n modulePath,\n patchJson as patchConfig,\n readJson,\n withConfigSchema,\n writeJson,\n type Catalog,\n type ConfigName,\n type ModuleLock,\n} from \"@sfmc-bds/sdk/node/config\";\nimport { bdsExePath } from \"@sfmc-bds/bds-tools/host-platform\";\nimport { execFileSync } from \"node:child_process\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { ensureDirectory, pickDirectory } from \"./interactive-prompts.js\";\nimport { persistLocale, t, type Locale } from \"./i18n/index.js\";\nimport { llbotExeName } from \"./llbot-launch.js\";\nimport { ROOT, isMonorepoLayout, isRuntimeInitialized, resolveFetchModule, spawnService } from \"./runtime.js\";\nimport { ensurePackUpdateConfigFile } from \"./pack-update/index.js\";\nimport { c } from \"./theme.js\";\n\n/** Shallow-merge write for top-level configs. Delegates to SDK; do not mkdir+writeFileSync here. */\nfunction patchJson<T extends object>(rootDir: string, name: ConfigName, updates: Partial<T>): void {\n patchConfig<T>(configPath(rootDir, name), updates);\n}\n\nasync function waitForHealth(port: number, ms = 15000): Promise<boolean> {\n const t = Date.now();\n while (Date.now() - t < ms) {\n try {\n if ((await fetch(`http://127.0.0.1:${port}/api/health`)).ok) return true;\n } catch {\n /* retry */\n }\n await new Promise((r) => setTimeout(r, 300));\n }\n return false;\n}\n\n/** \u8FD0\u884C\u65F6\u5FC5\u9700\u76EE\u5F55\u63A2\u6D4B(configs / modules) */\nconst RUNTIME_DIRS = [\n { target: \"configs\", npmTarget: \"configs\" },\n { target: \"modules\", npmTarget: \"modules\" },\n] as const;\n\nfunction missingRuntimeAssets(rootDir: string): string[] {\n return RUNTIME_DIRS.flatMap(({ target, npmTarget }) => {\n const directory = path.join(rootDir, npmTarget);\n try {\n return fs.statSync(directory).isDirectory() && fs.readdirSync(directory).length > 0 ? [] : [target];\n } catch {\n return [target];\n }\n });\n}\n\nasync function runBdsUpdate(rootDir: string, channel: string): Promise<{ code: number | null; output: string }> {\n const child = spawnService(\"update\", [`--channel=${channel}`, \"--force\", \"--no-start\"], {\n cwd: rootDir,\n stdio: \"pipe\",\n });\n const output: string[] = [];\n child.stdout?.on(\"data\", (data: Buffer) => output.push(data.toString()));\n child.stderr?.on(\"data\", (data: Buffer) => output.push(data.toString()));\n\n return new Promise((resolve) => {\n child.once(\"error\", (error) => resolve({ code: null, output: `${output.join(\"\")}${error.message}` }));\n child.once(\"close\", (code) => resolve({ code, output: output.join(\"\") }));\n });\n}\n\nasync function prepareRuntimeAssets(rootDir: string): Promise<void> {\n /* monorepo \u5E03\u5C40\uFF1Aconfigs/ modules/ \u5E94\u7531 npm \u5DE5\u4F5C\u533A\u5DF2\u63D0\u4F9B */\n if (isMonorepoLayout(rootDir)) {\n const missing = missingRuntimeAssets(rootDir);\n if (missing.length > 0) {\n throw new Error(t(\"wizard.npmMissing\", { list: missing.join(\", \") }));\n }\n return;\n }\n\n seedNpmRuntimeLayout(rootDir);\n}\n\n/** \u975E monorepo \u7684 npm \u5B89\u88C5\u5E03\u5C40\uFF1Aensure \u914D\u7F6E\u9AA8\u67B6 + \u7A7A modules */\nfunction seedNpmRuntimeLayout(rootDir: string): void {\n ensureCoreConfigs(rootDir, [\"db_config\", \"qq_config\", \"bds_updater\", \"permissions\"]);\n /* pack-update \u7684 ensure \u4F7F\u7528 runtime ROOT\uFF1Bnpm \u5E03\u5C40\u4E0B\u5E94\u4E0E rootDir \u4E00\u81F4 */\n if (path.resolve(rootDir) === path.resolve(ROOT)) {\n ensurePackUpdateConfigFile();\n }\n\n const modulesRoot = path.join(rootDir, \"modules\");\n const packagesDir = path.join(modulesRoot, \"packages\");\n fs.mkdirSync(packagesDir, { recursive: true });\n\n const catalogPath = path.join(modulesRoot, \"catalog.json\");\n if (!fs.existsSync(catalogPath)) {\n writeJson(\n catalogPath,\n withConfigSchema({ version: 1, modules: [] }, \"module_catalog\", \"modules\")\n );\n }\n const lockPath = path.join(modulesRoot, \"module-lock.json\");\n if (!fs.existsSync(lockPath)) {\n writeJson(lockPath, { version: 1, modules: {} });\n }\n}\n\nexport async function runWizard(): Promise<void> {\n intro(c.bold(t(\"wizard.intro\")));\n\n const langPick = await select({\n message: t(\"locale.wizard\"),\n options: [\n { value: \"zh-CN\", label: t(\"locale.opt.zh\") },\n { value: \"en\", label: t(\"locale.opt.en\") },\n ],\n initialValue: \"zh-CN\",\n });\n if (!isCancel(langPick)) {\n persistLocale(ROOT, langPick as Locale);\n }\n\n // Already initialized only when runtime.json#initialized_at is set (empty db_config skeleton does not count).\n if (isRuntimeInitialized()) {\n const r = await confirm({ message: t(\"wizard.rerun\"), initialValue: false });\n if (isCancel(r) || !r) {\n outro(c.dim(t(\"wizard.skipped\")));\n return;\n }\n }\n // Step 1: Runtime Environment\uFF08\u53EA\u64AD\u79CD configs/modules\uFF0C\u4E0D\u5199 initialized_at\u3001\u4E0D\u5EFA data/\uFF09\n const rootDir = ROOT;\n note(c.text(t(\"wizard.runtimeRoot\", { root: rootDir })), t(\"wizard.step1\"));\n\n try {\n await prepareRuntimeAssets(rootDir);\n } catch (error) {\n outro(c.red(t(\"wizard.prepFailed\", { message: (error as Error).message })));\n return;\n }\n\n // Step 2: External runtime paths\n note(c.text(t(\"wizard.step2Note\")), t(\"wizard.step2\"));\n\n const bdsResolved = await pickDirectory(t(\"wizard.bdsDir\"), path.join(rootDir, \"BDS\"));\n if (!ensureDirectory(bdsResolved)) {\n outro(c.red(t(\"wizard.cannotCreateBds\", { dir: bdsResolved })));\n return;\n }\n\n /* QQ \u6865\uFF1A\u9009\u540E\u7AEF \u2192 official \u51ED\u636E / llbot \u8DEF\u5F84\uFF1B\u7981\u7528\u5219 qq_enabled=false */\n const qqBackendPick = await select({\n message: t(\"wizard.qqBackend\"),\n options: [\n { value: \"official\", label: t(\"wizard.qqBackend.official\"), hint: t(\"wizard.qqBackend.officialHint\") },\n { value: \"llbot\", label: t(\"wizard.qqBackend.llbot\"), hint: t(\"wizard.qqBackend.llbotHint\") },\n { value: \"disabled\", label: t(\"wizard.qqBackend.disabled\"), hint: t(\"wizard.qqBackend.disabledHint\") },\n ],\n initialValue: \"official\",\n });\n const qqBackendChoice =\n isCancel(qqBackendPick) || !qqBackendPick ? \"official\" : String(qqBackendPick);\n\n let qqEnabled = true;\n let qqBackend: \"official\" | \"llbot\" = \"official\";\n let qqAppId = \"\";\n let qqAppSecret = \"\";\n let qqSandbox = false;\n let qqGroupOpenid = \"\";\n let llbotPath: string | undefined;\n let llbotEnabled = false;\n\n if (qqBackendChoice === \"disabled\") {\n qqEnabled = false;\n } else if (qqBackendChoice === \"llbot\") {\n qqBackend = \"llbot\";\n llbotEnabled = true;\n const picked = await pickDirectory(t(\"wizard.llbotDir\"), path.join(rootDir, \"LLBOT\"));\n if (ensureDirectory(picked)) {\n llbotPath = picked;\n } else {\n llbotPath = path.join(rootDir, \"LLBOT\");\n note(c.text(t(\"wizard.usingDefault\", { path: llbotPath })), t(\"common.tips\"));\n }\n } else {\n qqBackend = \"official\";\n const appIdRaw = await text({\n message: t(\"wizard.qqAppId\"),\n placeholder: \"102xxxxx\",\n validate: (v: any): any => {\n if (!String(v ?? \"\").trim()) return t(\"wizard.valueRequired\");\n },\n });\n if (!isCancel(appIdRaw)) qqAppId = String(appIdRaw).trim();\n\n const secretRaw = await password({\n message: t(\"wizard.qqAppSecret\"),\n validate: (v: any): any => {\n if (!String(v ?? \"\").trim()) return t(\"wizard.valueRequired\");\n },\n });\n if (!isCancel(secretRaw)) qqAppSecret = String(secretRaw).trim();\n\n const sandboxPick = await confirm({\n message: t(\"wizard.qqSandbox\"),\n initialValue: false,\n });\n if (!isCancel(sandboxPick)) qqSandbox = !!sandboxPick;\n\n const openidRaw = await text({\n message: t(\"wizard.qqGroupOpenid\"),\n placeholder: t(\"wizard.qqGroupOpenidHint\"),\n });\n if (!isCancel(openidRaw)) qqGroupOpenid = String(openidRaw).trim();\n }\n\n const dbDirInput = await pickDirectory(t(\"wizard.dbDir\"), path.join(rootDir, \"data\"));\n const dbDir = ensureDirectory(dbDirInput) ? dbDirInput : path.join(rootDir, \"data\");\n if (dbDir !== dbDirInput) {\n note(c.text(t(\"wizard.usingDefault\", { path: dbDir })), t(\"common.tips\"));\n }\n const dbPortRaw = await text({\n message: t(\"wizard.dbPort\"),\n initialValue: \"3001\",\n validate: (v: any): any => {\n const n = parseInt(v, 10);\n if (isNaN(n) || n < 1024 || n > 65535) return t(\"wizard.portRange\");\n if (v.length === 0) return t(\"wizard.valueRequired\");\n },\n });\n const dbPort = isCancel(dbPortRaw) ? 3001 : parseInt(dbPortRaw as string, 10);\n\n // Step 3: BDS environment\n const bdsExe = bdsExePath(bdsResolved);\n const bdsExists = fs.existsSync(bdsExe);\n\n note(\n bdsExists\n ? c.green(t(\"wizard.bdsFound\", { path: bdsResolved }))\n : c.yellow(t(\"wizard.bdsNotFound\", { path: bdsResolved })),\n t(\"wizard.step3\")\n );\n\n const EULA = await confirm({\n message: t(\"wizard.eula\"),\n initialValue: false,\n });\n if (isCancel(EULA) || !EULA) {\n outro(c.yellow(t(\"wizard.disagreed\")));\n return;\n }\n\n let downloadBds = false;\n let bdsChannel = \"release\";\n let backupDir = path.join(path.dirname(bdsResolved), \"backups\");\n let preserve: string[] = [];\n\n if (!bdsExists) {\n const d = await confirm({ message: t(\"wizard.downloadBds\"), initialValue: true });\n if (!isCancel(d) && d) {\n const ch = await select({\n message: t(\"wizard.selectChannel\"),\n options: [\n { value: \"release\", label: t(\"wizard.channel.release\"), hint: t(\"wizard.channel.releaseHint\") },\n { value: \"preview\", label: t(\"wizard.channel.preview\"), hint: t(\"wizard.channel.previewHint\") },\n ],\n });\n if (!isCancel(ch)) {\n bdsChannel = ch as string;\n downloadBds = true;\n }\n if (!ensureDirectory(backupDir)) {\n outro(c.red(t(\"wizard.cannotCreateBackup\", { dir: backupDir })));\n return;\n }\n }\n }\n\n backupDir = await pickDirectory(t(\"wizard.backupDir\"), backupDir);\n const preserveOptions = [\n { value: \"server.properties\", label: \"server.properties\", hint: t(\"wizard.preserve.serverProps\") },\n { value: \"whitelist.json\", label: \"whitelist.json\" },\n { value: \"permissions.json\", label: \"permissions.json\" },\n { value: \"allowlist.json\", label: \"allowlist.json\" },\n { value: \"worlds\", label: \"worlds/\", hint: t(\"wizard.preserve.worlds\") },\n { value: \"config\", label: \"config/\", hint: t(\"wizard.preserve.config\") },\n ] as const;\n const pr = await multiselect({\n message: t(\"wizard.preserve\"),\n options: [...preserveOptions],\n initialValues: preserveOptions.map((o) => o.value),\n required: false,\n });\n if (!isCancel(pr)) preserve = pr as string[];\n note(c.yellow(t(\"wizard.updaterTip\")), t(\"common.tips\"));\n\n // Step 4: Module initialization\n const catalog = readJson<Catalog>(modulePath(rootDir, \"catalog.json\")) ?? {};\n const catalogModules: Array<{ id: string; name?: string; type?: string; description?: string }> = [];\n if (Array.isArray(catalog.modules)) {\n for (const m of catalog.modules) {\n const entry = m as Record<string, unknown>;\n catalogModules.push({\n id: String(entry.id ?? \"\"),\n name: String(entry.name ?? entry.id ?? \"\"),\n type: String(entry.type ?? \"feature\"),\n description: String(entry.description ?? \"\"),\n });\n }\n }\n\n note(\n c.text(\n catalogModules.length > 0\n ? t(\"wizard.modulesFound\", { count: catalogModules.length })\n : t(\"wizard.modulesNone\")\n ),\n t(\"wizard.step4\")\n );\n\n let selectedModules: string[] = [];\n const coreMd: any[] = [];\n const featMd: any[] = [];\n catalogModules.forEach((k) => {\n if (k.type === \"core\") {\n coreMd.push({\n value: k.id,\n label: `${k.name} (${k.type})`,\n hint: String(k.description ?? t(\"wizard.emptyHint\")),\n disabled: true,\n });\n } else if (k.type === \"feature\") {\n featMd.push({\n value: k.id,\n label: `${k.name} (${k.type})`,\n hint: String(k.description ?? t(\"wizard.emptyHint\")),\n });\n }\n });\n if (catalogModules.length > 0) {\n const r = await multiselect({\n message: t(\"wizard.enableModules\"),\n options: [...coreMd, ...featMd],\n required: false,\n });\n if (!isCancel(r)) selectedModules = r as string[];\n }\n\n const wizardTasks = [\n {\n title: t(\"wizard.updatingConfigs\"),\n task: () => {\n const slashPath = (value: string) => value.replace(/\\\\/g, \"/\");\n patchJson(rootDir, \"db_config.json\", {\n db_port: dbPort,\n dbDir: slashPath(path.relative(rootDir, path.join(dbDir, \"sfmc_data.db\"))),\n modulesDir: \"modules\",\n });\n\n const llbotOn = qqBackend === \"llbot\" && !!llbotEnabled && !!llbotPath;\n const qqNotify = qqEnabled && (qqBackend === \"official\" || llbotOn);\n const exeName = llbotExeName();\n patchJson(rootDir, \"qq_config.json\", {\n qq_enabled: qqEnabled,\n qq_backend: qqBackend,\n qq_app_id: qqAppId,\n qq_app_secret: qqAppSecret,\n qq_sandbox: qqSandbox,\n qq_group_openid: qqGroupOpenid,\n llbot_enabled: llbotOn,\n // path = \u53EF\u6267\u884C\u6587\u4EF6\uFF1Bcwd = \u8FD0\u884C\u76EE\u5F55\uFF08\u5411\u5BFC\u9009\u7684\u662F\u76EE\u5F55\uFF09\n llbot_path: llbotPath ? slashPath(path.join(llbotPath, exeName)) : \"\",\n llbot_cwd: llbotPath ? slashPath(llbotPath) : \"\",\n });\n patchJson(rootDir, \"bds_updater.json\", {\n bds_path: slashPath(bdsResolved),\n channel: bdsChannel,\n backup_dir: slashPath(backupDir),\n preserve,\n qq_notify: qqNotify,\n });\n /* \u8DEF\u5F84\u9009\u5B9A\u540E\u518D\u6807\u8BB0\u5DF2\u521D\u59CB\u5316\uFF0C\u907F\u514D\u534A\u9014\u53D6\u6D88\u4ECD\u7559\u4E0B data/ \u8BED\u4E49 */\n patchJson(rootDir, \"runtime.json\", {\n runtime_root: rootDir,\n initialized_at: new Date().toISOString(),\n locale: isCancel(langPick) ? undefined : (langPick as string),\n });\n return t(\"wizard.configsUpdated\");\n },\n },\n {\n title: t(\"wizard.updatingModules\"),\n task: async (): Promise<string> => {\n const lock = readJson<ModuleLock>(modulePath(rootDir, \"module-lock.json\")) ?? {\n version: 1,\n modules: {},\n };\n if (!lock.modules) lock.modules = {};\n const now = Date.now();\n for (const id of selectedModules) lock.modules[id] = { enabled: true, updatedAt: now };\n writeJson(modulePath(rootDir, \"module-lock.json\"), lock);\n return t(\"wizard.modulesUpdated\");\n },\n },\n {\n title: t(\"wizard.initDb\"),\n task: async (): Promise<string> => {\n const child = spawnService(\"db\", [], {\n cwd: rootDir,\n stdio: \"ignore\",\n env: { ...process.env, DB_PORT: String(dbPort) },\n });\n if (!(await waitForHealth(dbPort))) {\n child.kill(\"SIGTERM\");\n return t(\"wizard.dbTimeout\");\n }\n\n await new Promise((resolve) => setTimeout(resolve, 1000));\n child.kill(\"SIGTERM\");\n setTimeout(() => child.kill(\"SIGKILL\"), 3000).unref();\n return t(\"wizard.dbOk\");\n },\n },\n ];\n if (downloadBds) {\n wizardTasks.push({\n title: t(\"wizard.downloadingBds\"),\n task: async (): Promise<string> => {\n const result = await runBdsUpdate(rootDir, bdsChannel);\n if (result.code !== 0) {\n return t(\"wizard.downloadFail\");\n }\n return t(\"wizard.bdsDownloaded\");\n },\n });\n }\n try {\n await tasks(wizardTasks);\n } catch (e) {\n outro(c.red(t(\"common.error\", { message: (e as Error).message })));\n return;\n }\n\n /* install \u2192 build \u2192 deploy chain */\n await runInstallBuildDeploy(rootDir, selectedModules, bdsResolved);\n\n outro(c.green(t(\"wizard.done\")));\n}\n\nasync function runInstallBuildDeploy(rootDir: string, selectedModules: string[], bdsResolved: string): Promise<void> {\n if (selectedModules.length > 0) {\n const fetchScript = resolveFetchModule();\n if (fetchScript) {\n const installT = [\n {\n title: t(\"wizard.installing\", { count: selectedModules.length }),\n task: async (): Promise<string> => {\n execFileSync(process.execPath, [fetchScript, \"install\", ...selectedModules], {\n cwd: rootDir,\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n env: { ...process.env, SFMC_ROOT: rootDir },\n });\n return t(\"wizard.installed\", { count: selectedModules.length });\n },\n },\n ];\n try {\n await tasks(installT);\n } catch (e) {\n note(c.yellow(t(\"wizard.installFailed\", { message: (e as Error).message })));\n }\n } else {\n note(c.yellow(t(\"wizard.fetchMissing\", { list: selectedModules.join(\", \") })));\n }\n } else {\n note(c.dim(t(\"wizard.noModulesSelected\")));\n }\n\n const { cmdBehaviorPackBuild, cmdBehaviorPackDeploy } = await import(\"./commands-behavior-pack.js\");\n const buildT = [\n {\n title: t(\"wizard.buildingBp\"),\n task: async (): Promise<string> => {\n const r = await cmdBehaviorPackBuild([]);\n if (!r.ok) throw new Error(r.message);\n return r.message;\n },\n },\n ];\n try {\n await tasks(buildT);\n } catch (e) {\n note(c.yellow(t(\"wizard.buildFailed\", { message: (e as Error).message })));\n return;\n }\n\n const deployT = [\n {\n title: t(\"wizard.deploying\", { path: bdsResolved }),\n task: async (): Promise<string> => {\n const r = await cmdBehaviorPackDeploy([]);\n if (!r.ok) throw new Error(r.message);\n return r.message;\n },\n },\n ];\n try {\n await tasks(deployT);\n note(c.green(t(\"wizard.restartBds\")));\n } catch (e) {\n note(c.yellow(t(\"wizard.deployFailed\", { message: (e as Error).message })));\n }\n void rootDir;\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["import { confirm, intro, isCancel, multiselect, note, outro, password, select, tasks, text } from \"@clack/prompts\";\nimport {\n configPath,\n ensureCoreConfigs,\n modulePath,\n patchJson as patchConfig,\n readJson,\n withConfigSchema,\n writeJson,\n type Catalog,\n type ConfigName,\n type ModuleLock,\n} from \"@sfmc-bds/sdk/node/config\";\nimport { bdsExePath } from \"@sfmc-bds/bds-tools/host-platform\";\nimport { execFileSync } from \"node:child_process\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { ensureDirectory, pickDirectory } from \"./interactive-prompts.js\";\nimport { persistLocale, t, type Locale } from \"./i18n/index.js\";\nimport { llbotExeName } from \"./llbot-launch.js\";\nimport { ROOT, isMonorepoLayout, isRuntimeInitialized, resolveFetchModule, spawnService } from \"./runtime.js\";\nimport { ensurePackUpdateConfigFile } from \"./pack-update/index.js\";\nimport { c } from \"./theme.js\";\n\n/** Shallow-merge write for top-level configs. Delegates to SDK; do not mkdir+writeFileSync here. */\nfunction patchJson<T extends object>(rootDir: string, name: ConfigName, updates: Partial<T>): void {\n patchConfig<T>(configPath(rootDir, name), updates);\n}\n\nasync function waitForHealth(port: number, ms = 15000): Promise<boolean> {\n const t = Date.now();\n while (Date.now() - t < ms) {\n try {\n if ((await fetch(`http://127.0.0.1:${port}/api/health`)).ok) return true;\n } catch {\n /* retry */\n }\n await new Promise((r) => setTimeout(r, 300));\n }\n return false;\n}\n\n/** \u8FD0\u884C\u65F6\u5FC5\u9700\u76EE\u5F55\u63A2\u6D4B(configs / modules) */\nconst RUNTIME_DIRS = [\n { target: \"configs\", npmTarget: \"configs\" },\n { target: \"modules\", npmTarget: \"modules\" },\n] as const;\n\nfunction missingRuntimeAssets(rootDir: string): string[] {\n return RUNTIME_DIRS.flatMap(({ target, npmTarget }) => {\n const directory = path.join(rootDir, npmTarget);\n try {\n return fs.statSync(directory).isDirectory() && fs.readdirSync(directory).length > 0 ? [] : [target];\n } catch {\n return [target];\n }\n });\n}\n\nasync function runBdsUpdate(rootDir: string, channel: string): Promise<{ code: number | null; output: string }> {\n const child = spawnService(\"update\", [`--channel=${channel}`, \"--force\", \"--no-start\"], {\n cwd: rootDir,\n stdio: \"pipe\",\n });\n const output: string[] = [];\n child.stdout?.on(\"data\", (data: Buffer) => output.push(data.toString()));\n child.stderr?.on(\"data\", (data: Buffer) => output.push(data.toString()));\n\n return new Promise((resolve) => {\n child.once(\"error\", (error) => resolve({ code: null, output: `${output.join(\"\")}${error.message}` }));\n child.once(\"close\", (code) => resolve({ code, output: output.join(\"\") }));\n });\n}\n\nasync function prepareRuntimeAssets(rootDir: string): Promise<void> {\n /* monorepo \u5E03\u5C40\uFF1Aconfigs/ modules/ \u5E94\u7531 npm \u5DE5\u4F5C\u533A\u5DF2\u63D0\u4F9B */\n if (isMonorepoLayout(rootDir)) {\n const missing = missingRuntimeAssets(rootDir);\n if (missing.length > 0) {\n throw new Error(t(\"wizard.npmMissing\", { list: missing.join(\", \") }));\n }\n return;\n }\n\n seedNpmRuntimeLayout(rootDir);\n}\n\n/** \u975E monorepo \u7684 npm \u5B89\u88C5\u5E03\u5C40\uFF1Aensure \u914D\u7F6E\u9AA8\u67B6 + \u7A7A modules */\nfunction seedNpmRuntimeLayout(rootDir: string): void {\n ensureCoreConfigs(rootDir, [\"db_config\", \"qq_config\", \"bds_updater\", \"permissions\"]);\n /* pack-update \u7684 ensure \u4F7F\u7528 runtime ROOT\uFF1Bnpm \u5E03\u5C40\u4E0B\u5E94\u4E0E rootDir \u4E00\u81F4 */\n if (path.resolve(rootDir) === path.resolve(ROOT)) {\n ensurePackUpdateConfigFile();\n }\n\n const modulesRoot = path.join(rootDir, \"modules\");\n const packagesDir = path.join(modulesRoot, \"packages\");\n fs.mkdirSync(packagesDir, { recursive: true });\n\n const catalogPath = path.join(modulesRoot, \"catalog.json\");\n if (!fs.existsSync(catalogPath)) {\n writeJson(\n catalogPath,\n withConfigSchema({ version: 1, modules: [] }, \"module_catalog\", \"modules\")\n );\n }\n const lockPath = path.join(modulesRoot, \"module-lock.json\");\n if (!fs.existsSync(lockPath)) {\n writeJson(lockPath, { version: 1, modules: {} });\n }\n}\n\nexport async function runWizard(): Promise<void> {\n intro(c.bold(t(\"wizard.intro\")));\n\n const langPick = await select({\n message: t(\"locale.wizard\"),\n options: [\n { value: \"zh-CN\", label: t(\"locale.opt.zh\") },\n { value: \"en\", label: t(\"locale.opt.en\") },\n ],\n initialValue: \"zh-CN\",\n });\n if (!isCancel(langPick)) {\n persistLocale(ROOT, langPick as Locale);\n }\n\n // Already initialized only when runtime.json#initialized_at is set (empty db_config skeleton does not count).\n if (isRuntimeInitialized()) {\n const r = await confirm({ message: t(\"wizard.rerun\"), initialValue: false });\n if (isCancel(r) || !r) {\n outro(c.dim(t(\"wizard.skipped\")));\n return;\n }\n }\n // Step 1: Runtime Environment\uFF08\u53EA\u64AD\u79CD configs/modules\uFF0C\u4E0D\u5199 initialized_at\u3001\u4E0D\u5EFA data/\uFF09\n const rootDir = ROOT;\n note(c.text(t(\"wizard.runtimeRoot\", { root: rootDir })), t(\"wizard.step1\"));\n\n try {\n await prepareRuntimeAssets(rootDir);\n } catch (error) {\n outro(c.red(t(\"wizard.prepFailed\", { message: (error as Error).message })));\n return;\n }\n\n // Step 2: External runtime paths\n note(c.text(t(\"wizard.step2Note\")), t(\"wizard.step2\"));\n\n const bdsResolved = await pickDirectory(t(\"wizard.bdsDir\"), path.join(rootDir, \"BDS\"));\n if (!ensureDirectory(bdsResolved)) {\n outro(c.red(t(\"wizard.cannotCreateBds\", { dir: bdsResolved })));\n return;\n }\n\n /* QQ \u6865\uFF1A\u9009\u540E\u7AEF \u2192 official \u51ED\u636E / llbot \u8DEF\u5F84\uFF1B\u7981\u7528\u5219 qq_enabled=false */\n const qqBackendPick = await select({\n message: t(\"wizard.qqBackend\"),\n options: [\n { value: \"official\", label: t(\"wizard.qqBackend.official\"), hint: t(\"wizard.qqBackend.officialHint\") },\n { value: \"llbot\", label: t(\"wizard.qqBackend.llbot\"), hint: t(\"wizard.qqBackend.llbotHint\") },\n { value: \"disabled\", label: t(\"wizard.qqBackend.disabled\"), hint: t(\"wizard.qqBackend.disabledHint\") },\n ],\n initialValue: \"official\",\n });\n const qqBackendChoice =\n isCancel(qqBackendPick) || !qqBackendPick ? \"official\" : String(qqBackendPick);\n\n let qqEnabled = true;\n let qqBackend: \"official\" | \"llbot\" = \"official\";\n let qqAppId = \"\";\n let qqAppSecret = \"\";\n let qqSandbox = false;\n let qqGroupOpenid = \"\";\n let llbotPath: string | undefined;\n let llbotEnabled = false;\n\n if (qqBackendChoice === \"disabled\") {\n qqEnabled = false;\n } else if (qqBackendChoice === \"llbot\") {\n qqBackend = \"llbot\";\n llbotEnabled = true;\n const picked = await pickDirectory(t(\"wizard.llbotDir\"), path.join(rootDir, \"LLBOT\"));\n if (ensureDirectory(picked)) {\n llbotPath = picked;\n } else {\n llbotPath = path.join(rootDir, \"LLBOT\");\n note(c.text(t(\"wizard.usingDefault\", { path: llbotPath })), t(\"common.tips\"));\n }\n } else {\n qqBackend = \"official\";\n const appIdRaw = await text({\n message: t(\"wizard.qqAppId\"),\n placeholder: \"102xxxxx\",\n validate: (v: any): any => {\n if (!String(v ?? \"\").trim()) return t(\"wizard.valueRequired\");\n },\n });\n if (!isCancel(appIdRaw)) qqAppId = String(appIdRaw).trim();\n\n const secretRaw = await password({\n message: t(\"wizard.qqAppSecret\"),\n validate: (v: any): any => {\n if (!String(v ?? \"\").trim()) return t(\"wizard.valueRequired\");\n },\n });\n if (!isCancel(secretRaw)) qqAppSecret = String(secretRaw).trim();\n\n const sandboxPick = await confirm({\n message: t(\"wizard.qqSandbox\"),\n initialValue: false,\n });\n if (!isCancel(sandboxPick)) qqSandbox = !!sandboxPick;\n\n const openidRaw = await text({\n message: t(\"wizard.qqGroupOpenid\"),\n placeholder: t(\"wizard.qqGroupOpenidHint\"),\n });\n if (!isCancel(openidRaw)) qqGroupOpenid = String(openidRaw).trim();\n }\n\n const dbDirInput = await pickDirectory(t(\"wizard.dbDir\"), path.join(rootDir, \"data\"));\n const dbDir = ensureDirectory(dbDirInput) ? dbDirInput : path.join(rootDir, \"data\");\n if (dbDir !== dbDirInput) {\n note(c.text(t(\"wizard.usingDefault\", { path: dbDir })), t(\"common.tips\"));\n }\n const dbPortRaw = await text({\n message: t(\"wizard.dbPort\"),\n initialValue: \"3001\",\n validate: (v: any): any => {\n const n = parseInt(v, 10);\n if (isNaN(n) || n < 1024 || n > 65535) return t(\"wizard.portRange\");\n if (v.length === 0) return t(\"wizard.valueRequired\");\n },\n });\n const dbPort = isCancel(dbPortRaw) ? 3001 : parseInt(dbPortRaw as string, 10);\n\n // Step 3: BDS environment\n const bdsExe = bdsExePath(bdsResolved);\n const bdsExists = fs.existsSync(bdsExe);\n\n note(\n bdsExists\n ? c.green(t(\"wizard.bdsFound\", { path: bdsResolved }))\n : c.yellow(t(\"wizard.bdsNotFound\", { path: bdsResolved })),\n t(\"wizard.step3\")\n );\n\n const EULA = await confirm({\n message: t(\"wizard.eula\"),\n initialValue: false,\n });\n if (isCancel(EULA) || !EULA) {\n outro(c.yellow(t(\"wizard.disagreed\")));\n return;\n }\n\n let downloadBds = false;\n let bdsChannel = \"release\";\n let backupDir = path.join(path.dirname(bdsResolved), \"backups\");\n let preserve: string[] = [];\n\n if (!bdsExists) {\n const d = await confirm({ message: t(\"wizard.downloadBds\"), initialValue: true });\n if (!isCancel(d) && d) {\n const ch = await select({\n message: t(\"wizard.selectChannel\"),\n options: [\n { value: \"release\", label: t(\"wizard.channel.release\"), hint: t(\"wizard.channel.releaseHint\") },\n { value: \"preview\", label: t(\"wizard.channel.preview\"), hint: t(\"wizard.channel.previewHint\") },\n ],\n });\n if (!isCancel(ch)) {\n bdsChannel = ch as string;\n downloadBds = true;\n }\n if (!ensureDirectory(backupDir)) {\n outro(c.red(t(\"wizard.cannotCreateBackup\", { dir: backupDir })));\n return;\n }\n }\n }\n\n backupDir = await pickDirectory(t(\"wizard.backupDir\"), backupDir);\n const preserveOptions = [\n { value: \"server.properties\", label: \"server.properties\", hint: t(\"wizard.preserve.serverProps\") },\n { value: \"whitelist.json\", label: \"whitelist.json\" },\n { value: \"permissions.json\", label: \"permissions.json\" },\n { value: \"allowlist.json\", label: \"allowlist.json\" },\n { value: \"worlds\", label: \"worlds/\", hint: t(\"wizard.preserve.worlds\") },\n { value: \"config\", label: \"config/\", hint: t(\"wizard.preserve.config\") },\n ] as const;\n const pr = await multiselect({\n message: t(\"wizard.preserve\"),\n options: [...preserveOptions],\n initialValues: preserveOptions.map((o) => o.value),\n required: false,\n });\n if (!isCancel(pr)) preserve = pr as string[];\n note(c.yellow(t(\"wizard.updaterTip\")), t(\"common.tips\"));\n\n // Step 4: Module initialization\n const catalog = readJson<Catalog>(modulePath(rootDir, \"catalog.json\")) ?? {\n version: 1,\n modules: [],\n };\n const catalogModules: Array<{ id: string; name?: string; description?: string; canDisable?: boolean }> = [];\n if (Array.isArray(catalog.modules)) {\n for (const m of catalog.modules) {\n catalogModules.push({\n id: String(m.id ?? \"\"),\n name: String(m.name ?? m.id ?? \"\"),\n description: String(m.description ?? \"\"),\n canDisable: m.canDisable !== false,\n });\n }\n }\n\n note(\n c.text(\n catalogModules.length > 0\n ? t(\"wizard.modulesFound\", { count: catalogModules.length })\n : t(\"wizard.modulesNone\")\n ),\n t(\"wizard.step4\")\n );\n\n let selectedModules: string[] = [];\n const lockedMd: any[] = [];\n const optionalMd: any[] = [];\n catalogModules.forEach((k) => {\n const option = {\n value: k.id,\n label: String(k.name),\n hint: String(k.description ?? t(\"wizard.emptyHint\")),\n };\n if (k.canDisable === false) {\n lockedMd.push({ ...option, disabled: true });\n } else {\n optionalMd.push(option);\n }\n });\n if (catalogModules.length > 0) {\n const r = await multiselect({\n message: t(\"wizard.enableModules\"),\n options: [...lockedMd, ...optionalMd],\n required: false,\n });\n if (!isCancel(r)) selectedModules = r as string[];\n }\n\n const wizardTasks = [\n {\n title: t(\"wizard.updatingConfigs\"),\n task: () => {\n const slashPath = (value: string) => value.replace(/\\\\/g, \"/\");\n patchJson(rootDir, \"db_config.json\", {\n db_port: dbPort,\n dbDir: slashPath(path.relative(rootDir, path.join(dbDir, \"sfmc_data.db\"))),\n modulesDir: \"modules\",\n });\n\n const llbotOn = qqBackend === \"llbot\" && !!llbotEnabled && !!llbotPath;\n const qqNotify = qqEnabled && (qqBackend === \"official\" || llbotOn);\n const exeName = llbotExeName();\n patchJson(rootDir, \"qq_config.json\", {\n qq_enabled: qqEnabled,\n qq_backend: qqBackend,\n qq_app_id: qqAppId,\n qq_app_secret: qqAppSecret,\n qq_sandbox: qqSandbox,\n qq_group_openid: qqGroupOpenid,\n llbot_enabled: llbotOn,\n // path = \u53EF\u6267\u884C\u6587\u4EF6\uFF1Bcwd = \u8FD0\u884C\u76EE\u5F55\uFF08\u5411\u5BFC\u9009\u7684\u662F\u76EE\u5F55\uFF09\n llbot_path: llbotPath ? slashPath(path.join(llbotPath, exeName)) : \"\",\n llbot_cwd: llbotPath ? slashPath(llbotPath) : \"\",\n });\n patchJson(rootDir, \"bds_updater.json\", {\n bds_path: slashPath(bdsResolved),\n channel: bdsChannel,\n backup_dir: slashPath(backupDir),\n preserve,\n qq_notify: qqNotify,\n });\n /* \u8DEF\u5F84\u9009\u5B9A\u540E\u518D\u6807\u8BB0\u5DF2\u521D\u59CB\u5316\uFF0C\u907F\u514D\u534A\u9014\u53D6\u6D88\u4ECD\u7559\u4E0B data/ \u8BED\u4E49 */\n patchJson(rootDir, \"runtime.json\", {\n runtime_root: rootDir,\n initialized_at: new Date().toISOString(),\n locale: isCancel(langPick) ? undefined : (langPick as string),\n });\n return t(\"wizard.configsUpdated\");\n },\n },\n {\n title: t(\"wizard.updatingModules\"),\n task: async (): Promise<string> => {\n const lock = readJson<ModuleLock>(modulePath(rootDir, \"module-lock.json\")) ?? {\n version: 1,\n modules: {},\n };\n if (!lock.modules) lock.modules = {};\n const now = Date.now();\n for (const id of selectedModules) lock.modules[id] = { enabled: true, updatedAt: now };\n writeJson(modulePath(rootDir, \"module-lock.json\"), lock);\n return t(\"wizard.modulesUpdated\");\n },\n },\n {\n title: t(\"wizard.initDb\"),\n task: async (): Promise<string> => {\n const child = spawnService(\"db\", [], {\n cwd: rootDir,\n stdio: \"ignore\",\n env: { ...process.env, DB_PORT: String(dbPort) },\n });\n if (!(await waitForHealth(dbPort))) {\n child.kill(\"SIGTERM\");\n return t(\"wizard.dbTimeout\");\n }\n\n await new Promise((resolve) => setTimeout(resolve, 1000));\n child.kill(\"SIGTERM\");\n setTimeout(() => child.kill(\"SIGKILL\"), 3000).unref();\n return t(\"wizard.dbOk\");\n },\n },\n ];\n if (downloadBds) {\n wizardTasks.push({\n title: t(\"wizard.downloadingBds\"),\n task: async (): Promise<string> => {\n const result = await runBdsUpdate(rootDir, bdsChannel);\n if (result.code !== 0) {\n return t(\"wizard.downloadFail\");\n }\n return t(\"wizard.bdsDownloaded\");\n },\n });\n }\n try {\n await tasks(wizardTasks);\n } catch (e) {\n outro(c.red(t(\"common.error\", { message: (e as Error).message })));\n return;\n }\n\n /* install \u2192 build \u2192 deploy chain */\n await runInstallBuildDeploy(rootDir, selectedModules, bdsResolved);\n\n outro(c.green(t(\"wizard.done\")));\n}\n\nasync function runInstallBuildDeploy(rootDir: string, selectedModules: string[], bdsResolved: string): Promise<void> {\n if (selectedModules.length > 0) {\n const fetchScript = resolveFetchModule();\n if (fetchScript) {\n const installT = [\n {\n title: t(\"wizard.installing\", { count: selectedModules.length }),\n task: async (): Promise<string> => {\n execFileSync(process.execPath, [fetchScript, \"install\", ...selectedModules], {\n cwd: rootDir,\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n env: { ...process.env, SFMC_ROOT: rootDir },\n });\n return t(\"wizard.installed\", { count: selectedModules.length });\n },\n },\n ];\n try {\n await tasks(installT);\n } catch (e) {\n note(c.yellow(t(\"wizard.installFailed\", { message: (e as Error).message })));\n }\n } else {\n note(c.yellow(t(\"wizard.fetchMissing\", { list: selectedModules.join(\", \") })));\n }\n } else {\n note(c.dim(t(\"wizard.noModulesSelected\")));\n }\n\n const { cmdBehaviorPackBuild, cmdBehaviorPackDeploy } = await import(\"./commands-behavior-pack.js\");\n const buildT = [\n {\n title: t(\"wizard.buildingBp\"),\n task: async (): Promise<string> => {\n const r = await cmdBehaviorPackBuild([]);\n if (!r.ok) throw new Error(r.message);\n return r.message;\n },\n },\n ];\n try {\n await tasks(buildT);\n } catch (e) {\n note(c.yellow(t(\"wizard.buildFailed\", { message: (e as Error).message })));\n return;\n }\n\n const deployT = [\n {\n title: t(\"wizard.deploying\", { path: bdsResolved }),\n task: async (): Promise<string> => {\n const r = await cmdBehaviorPackDeploy([]);\n if (!r.ok) throw new Error(r.message);\n return r.message;\n },\n },\n ];\n try {\n await tasks(deployT);\n note(c.green(t(\"wizard.restartBds\")));\n } catch (e) {\n note(c.yellow(t(\"wizard.deployFailed\", { message: (e as Error).message })));\n }\n void rootDir;\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["t"]
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sfmc-bds/cli",
|
|
3
|
-
"version": "0.2.0-beta.
|
|
3
|
+
"version": "0.2.0-beta.12",
|
|
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",
|
|
@@ -51,11 +51,11 @@
|
|
|
51
51
|
"dependencies": {
|
|
52
52
|
"@clack/prompts": "^1.7.0",
|
|
53
53
|
"chalk": "^6.0.0",
|
|
54
|
-
"@sfmc-bds/bds-tools": "0.2.0-beta.
|
|
55
|
-
"@sfmc-bds/sdk": "0.2.0-beta.
|
|
54
|
+
"@sfmc-bds/bds-tools": "0.2.0-beta.10",
|
|
55
|
+
"@sfmc-bds/sdk": "0.2.0-beta.10"
|
|
56
56
|
},
|
|
57
57
|
"devDependencies": {
|
|
58
|
-
"@sfmc-bds/tools": "0.2.0-beta.
|
|
58
|
+
"@sfmc-bds/tools": "0.2.0-beta.11"
|
|
59
59
|
},
|
|
60
60
|
"publishConfig": {
|
|
61
61
|
"access": "public",
|
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
// @ts-check
|
|
3
3
|
/**
|
|
4
|
-
* @sfmc-bds/cli — 离线校验 catalog
|
|
4
|
+
* @sfmc-bds/cli — 离线校验 catalog 与已安装模块包的全局一致性
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
* -
|
|
6
|
+
* 职责分工边界:
|
|
7
|
+
* - 全局目录一致性:本文件专注于校验 catalog 唯一性(id / configKey)、requires 依赖闭包、以及 catalog.id 与 manifest.id 的严格对齐;
|
|
8
|
+
* - 字段形状校验解耦:模块 manifest 的具体字段结构、版本判定与必填规则完全委托给 SDK 的权威总入口 `validateManifest`,不再在本地重复实现字段形状检查。
|
|
8
9
|
*
|
|
9
|
-
*
|
|
10
|
+
* 用法:
|
|
10
11
|
* node packages/cli/scripts/module-install/check-modules.mjs
|
|
11
|
-
* node …/check-modules.mjs --sync # 先 sync catalog
|
|
12
|
+
* node …/check-modules.mjs --sync # 先 sync catalog 再执行校验
|
|
12
13
|
*/
|
|
14
|
+
import { validateManifest } from "@sfmc-bds/sdk/module-loader";
|
|
13
15
|
import fs from "node:fs";
|
|
14
16
|
import path from "node:path";
|
|
15
17
|
import process from "node:process";
|
|
@@ -31,77 +33,6 @@ import { ROOT } from "./lib/paths.mjs";
|
|
|
31
33
|
* @property {string} [summary]
|
|
32
34
|
*/
|
|
33
35
|
|
|
34
|
-
/**
|
|
35
|
-
* @param {*} manifest
|
|
36
|
-
* @returns {{ ok: true } | { ok: false; errors: string[] }}
|
|
37
|
-
*/
|
|
38
|
-
function validateManifest(manifest) {
|
|
39
|
-
const v = manifest?.schemaVersion;
|
|
40
|
-
if (v === 3) {
|
|
41
|
-
const errors = checkV3(manifest);
|
|
42
|
-
if (errors.length > 0) return { ok: false, errors };
|
|
43
|
-
return { ok: true };
|
|
44
|
-
}
|
|
45
|
-
if (v === 2) {
|
|
46
|
-
const errors = checkV2(manifest);
|
|
47
|
-
if (errors.length > 0) return { ok: false, errors };
|
|
48
|
-
return { ok: true };
|
|
49
|
-
}
|
|
50
|
-
return { ok: false, errors: [`schemaVersion 应为 2 或 3,实际 ${v}`] };
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/** @param {*} r */
|
|
54
|
-
function checkV2(r) {
|
|
55
|
-
const errs = [];
|
|
56
|
-
if (!r || typeof r !== "object") return ["manifest 根必须是 plain object"];
|
|
57
|
-
if (r.schemaVersion !== 2) errs.push("schemaVersion 必须为 2");
|
|
58
|
-
if (!r.id || typeof r.id !== "string") errs.push("id 缺失或类型错");
|
|
59
|
-
if (!r.name || typeof r.name !== "string") errs.push("name 缺失或类型错");
|
|
60
|
-
if (r.type !== "core" && r.type !== "feature") errs.push(`type 必须是 "core" 或 "feature",实际为 ${r.type}`);
|
|
61
|
-
if (!r.configKey || typeof r.configKey !== "string") errs.push("configKey 缺失");
|
|
62
|
-
if (!Array.isArray(r.requires)) errs.push("requires 必须是数组");
|
|
63
|
-
if (!Array.isArray(r.permissions)) errs.push("permissions 必须是数组");
|
|
64
|
-
if (!r.services || typeof r.services !== "object") errs.push("services 缺失");
|
|
65
|
-
return errs;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/** @param {*} r */
|
|
69
|
-
function checkV3(r) {
|
|
70
|
-
if (!r || typeof r !== "object") return ["manifest 根必须是 plain object"];
|
|
71
|
-
const errs = [];
|
|
72
|
-
if (r.schemaVersion !== 3) errs.push(`schemaVersion 必须为 3,实际为 ${r.schemaVersion}`);
|
|
73
|
-
if (!r.id || typeof r.id !== "string") errs.push("id 缺失或类型错");
|
|
74
|
-
if (!r.name || typeof r.name !== "string") errs.push("name 缺失或类型错");
|
|
75
|
-
if (r.type !== "core" && r.type !== "feature") errs.push(`type 必须是 "core" 或 "feature",实际为 ${r.type}`);
|
|
76
|
-
if (!r.configKey || typeof r.configKey !== "string") errs.push("configKey 缺失");
|
|
77
|
-
if (!Array.isArray(r.requires)) errs.push("requires 必须是数组");
|
|
78
|
-
if (!Array.isArray(r.permissions)) errs.push("permissions 必须是数组");
|
|
79
|
-
if (!r.services || typeof r.services !== "object") errs.push("services 缺失");
|
|
80
|
-
const s = r.semantic;
|
|
81
|
-
if (s !== undefined && s !== null && typeof s !== "object") {
|
|
82
|
-
errs.push("semantic 必须是 plain object(缺失合法)");
|
|
83
|
-
return errs;
|
|
84
|
-
}
|
|
85
|
-
if (s && typeof s === "object") {
|
|
86
|
-
if (s.configKeys !== undefined && !Array.isArray(s.configKeys)) {
|
|
87
|
-
errs.push("[semantic.configKeys] 必须是字符串数组");
|
|
88
|
-
}
|
|
89
|
-
if (s.dependsOn !== undefined && !Array.isArray(s.dependsOn)) {
|
|
90
|
-
errs.push("[semantic.dependsOn] 必须是字符串数组");
|
|
91
|
-
}
|
|
92
|
-
if (s.events !== undefined && (s.events === null || typeof s.events !== "object")) {
|
|
93
|
-
errs.push("[semantic.events] 必须是 plain object");
|
|
94
|
-
}
|
|
95
|
-
if (s.dbTables !== undefined && !Array.isArray(s.dbTables)) {
|
|
96
|
-
errs.push("[semantic.dbTables] 必须是数组");
|
|
97
|
-
}
|
|
98
|
-
if (s.publicApi !== undefined && !Array.isArray(s.publicApi)) {
|
|
99
|
-
errs.push("[semantic.publicApi] 必须是数组");
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
return errs;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
36
|
/**
|
|
106
37
|
* @param {CheckModulesOpts} [opts]
|
|
107
38
|
* @returns {CheckModulesResult}
|
|
@@ -157,15 +88,18 @@ export function runCheckModules(opts = {}) {
|
|
|
157
88
|
return { ok: false, error: `${m.id}: manifest 解析失败: ${message}` };
|
|
158
89
|
}
|
|
159
90
|
|
|
91
|
+
// 单个 manifest 字段形状校验:委托 SDK validateManifest 权威入口,本脚本不重复实现字段检查
|
|
160
92
|
const v = validateManifest(manifest);
|
|
161
93
|
if (!v.ok) {
|
|
162
94
|
return { ok: false, error: `${m.id}: manifest 校验未通过 — ${v.errors.join("; ")}` };
|
|
163
95
|
}
|
|
96
|
+
// 校验 catalog 条目与 manifest 实际声明的模块身份(id)严格一致
|
|
164
97
|
if (manifest.id !== m.id) {
|
|
165
98
|
return { ok: false, error: `${m.id}: catalog.id 与 manifest.id(${manifest.id}) 不一致` };
|
|
166
99
|
}
|
|
167
100
|
}
|
|
168
101
|
|
|
102
|
+
|
|
169
103
|
for (const m of modules) {
|
|
170
104
|
const reqs = Array.isArray(m.requires) ? m.requires : [];
|
|
171
105
|
for (const dep of reqs) {
|
|
@@ -16,7 +16,7 @@ const CATALOG_SCHEMA =
|
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
18
|
* @typedef {import("./packages.mjs").CatalogEntry} CatalogEntry
|
|
19
|
-
* @typedef {
|
|
19
|
+
* @typedef {import("@sfmc-bds/sdk/contracts").ModuleCatalog} ModuleCatalog
|
|
20
20
|
*/
|
|
21
21
|
|
|
22
22
|
/** @returns {ModuleCatalog} */
|
|
@@ -8,8 +8,8 @@ import { MODULE_LOCK_PATH } from "./paths.mjs";
|
|
|
8
8
|
import { readJson, writeJson } from "./io.mjs";
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
|
-
* @typedef {
|
|
12
|
-
* @typedef {
|
|
11
|
+
* @typedef {import("@sfmc-bds/sdk/contracts").ModuleRuntimeState} LockState
|
|
12
|
+
* @typedef {import("@sfmc-bds/sdk/contracts").ModuleLock} ModuleLock
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
15
|
const SERVICE_PREFIXES = ["service-", "tool-"];
|
|
@@ -31,17 +31,7 @@ import { catalogEntryRelPath, packageDir, packageEntryPath, packageManifestPath,
|
|
|
31
31
|
*/
|
|
32
32
|
|
|
33
33
|
/**
|
|
34
|
-
* @typedef {
|
|
35
|
-
* @property {string} id
|
|
36
|
-
* @property {string} configKey
|
|
37
|
-
* @property {string} name
|
|
38
|
-
* @property {string} type
|
|
39
|
-
* @property {string} description
|
|
40
|
-
* @property {boolean} enabledByDefault
|
|
41
|
-
* @property {boolean} canDisable
|
|
42
|
-
* @property {string[]} requires
|
|
43
|
-
* @property {{ kind: string, path: string }} entry
|
|
44
|
-
* @property {SemanticBlock} [semantic] v3 字段;v2 模块不写
|
|
34
|
+
* @typedef {import("@sfmc-bds/sdk/contracts").ModuleCatalogEntry} CatalogEntry
|
|
45
35
|
*/
|
|
46
36
|
|
|
47
37
|
/** @returns {PackageInfo[]} */
|
|
@@ -77,28 +67,30 @@ export function scanInstalledPackages() {
|
|
|
77
67
|
}
|
|
78
68
|
|
|
79
69
|
/**
|
|
80
|
-
* 从 v2 / v3 manifest
|
|
81
|
-
* v2
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
*
|
|
70
|
+
* 从 v2 / v3 manifest 及包所在目录名投影生成 catalog 条目。
|
|
71
|
+
* - v2 manifest:投影基础核心字段,不包含 semantic 块;
|
|
72
|
+
* - v3 manifest:在核心字段基础上将 semantic 块深拷贝透传至条目中;
|
|
73
|
+
* - 契约原则:本函数仅做结构投影与深拷贝,不负责校验字段形状合法性;形状校验统一以 SDK 的 `validateManifest` 为准(由 check-modules 离线自检或安装器统一调用)。
|
|
74
|
+
*
|
|
75
|
+
* @param {string} folder 安装目录名。
|
|
76
|
+
* @param {Record<string, unknown>} manifest 原始 manifest 对象。
|
|
77
|
+
* @returns {CatalogEntry} 投影生成的 catalog 条目。
|
|
85
78
|
*/
|
|
86
79
|
export function projectCatalogEntry(folder, manifest) {
|
|
87
|
-
const type = String(manifest.type || "feature");
|
|
88
80
|
const id = String(manifest.id || "").trim();
|
|
89
81
|
const configKey = String(manifest.configKey || "").trim();
|
|
90
82
|
if (!id) throw new Error(`packages/${folder}: manifest.id 缺失`);
|
|
91
83
|
if (!configKey) throw new Error(`packages/${folder}: manifest.configKey 缺失`);
|
|
92
84
|
|
|
93
|
-
|
|
94
|
-
const
|
|
85
|
+
/* 缺省:默认启用、允许禁用;不可禁用须在 manifest 显式 canDisable:false */
|
|
86
|
+
const enabledByDefault = typeof manifest.enabledByDefault === "boolean" ? manifest.enabledByDefault : true;
|
|
87
|
+
const canDisable = typeof manifest.canDisable === "boolean" ? manifest.canDisable : true;
|
|
95
88
|
|
|
96
89
|
/** @type {CatalogEntry} */
|
|
97
90
|
const entry = {
|
|
98
91
|
id,
|
|
99
92
|
configKey,
|
|
100
93
|
name: String(manifest.name || configKey),
|
|
101
|
-
type,
|
|
102
94
|
description: String(manifest.description || ""),
|
|
103
95
|
enabledByDefault,
|
|
104
96
|
canDisable,
|
|
@@ -108,14 +100,16 @@ export function projectCatalogEntry(folder, manifest) {
|
|
|
108
100
|
path: catalogEntryRelPath(folder),
|
|
109
101
|
},
|
|
110
102
|
};
|
|
111
|
-
/* v3 semantic
|
|
112
|
-
*
|
|
103
|
+
/* v3 semantic 语义块投影:
|
|
104
|
+
* 采用 structuredClone 执行只读深拷贝透传,不在此处重复校验字段形状。
|
|
105
|
+
* 契约原则:字段形状与类型的合法性统一以 SDK validateManifest 为唯一权威(由 check-modules 等上层检查脚本统一调用验证)。 */
|
|
113
106
|
if (manifest.schemaVersion === 3 && manifest.semantic && typeof manifest.semantic === "object") {
|
|
114
107
|
entry.semantic = /** @type {SemanticBlock} */ (structuredClone(manifest.semantic));
|
|
115
108
|
}
|
|
116
109
|
return entry;
|
|
117
110
|
}
|
|
118
111
|
|
|
112
|
+
|
|
119
113
|
/** @param {string} folder @returns {CatalogEntry | null} */
|
|
120
114
|
export function loadPackageCatalogEntry(folder) {
|
|
121
115
|
const manifestPath = packageManifestPath(folder);
|