@sfmc-bds/cli 0.2.0-beta.7 → 0.2.0-beta.9

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.
Files changed (91) hide show
  1. package/dist/argv-parse.d.ts +0 -2
  2. package/dist/argv-parse.d.ts.map +1 -1
  3. package/dist/argv-parse.js +1 -5
  4. package/dist/argv-parse.js.map +2 -2
  5. package/dist/cli-gate.d.ts.map +1 -1
  6. package/dist/cli-gate.js +0 -2
  7. package/dist/cli-gate.js.map +2 -2
  8. package/dist/command-surface.d.ts +2 -12
  9. package/dist/command-surface.d.ts.map +1 -1
  10. package/dist/command-surface.js +2 -34
  11. package/dist/command-surface.js.map +2 -2
  12. package/dist/commands.d.ts.map +1 -1
  13. package/dist/commands.js +123 -10
  14. package/dist/commands.js.map +2 -2
  15. package/dist/help-text.d.ts.map +1 -1
  16. package/dist/help-text.js +1 -5
  17. package/dist/help-text.js.map +2 -2
  18. package/dist/i18n/locales/en.d.ts +27 -38
  19. package/dist/i18n/locales/en.d.ts.map +1 -1
  20. package/dist/i18n/locales/en.js +27 -41
  21. package/dist/i18n/locales/en.js.map +2 -2
  22. package/dist/i18n/locales/zh-CN.d.ts.map +1 -1
  23. package/dist/i18n/locales/zh-CN.js +27 -41
  24. package/dist/i18n/locales/zh-CN.js.map +2 -2
  25. package/dist/index.d.ts +2 -2
  26. package/dist/index.d.ts.map +1 -1
  27. package/dist/index.js +3 -4
  28. package/dist/index.js.map +2 -2
  29. package/dist/llbot-launch.d.ts +20 -0
  30. package/dist/llbot-launch.d.ts.map +1 -0
  31. package/dist/llbot-launch.js +40 -0
  32. package/dist/llbot-launch.js.map +7 -0
  33. package/dist/main.js +7 -12
  34. package/dist/main.js.map +2 -2
  35. package/dist/module-commands.d.ts +5 -18
  36. package/dist/module-commands.d.ts.map +1 -1
  37. package/dist/module-commands.js +89 -87
  38. package/dist/module-commands.js.map +2 -2
  39. package/dist/module-pack-build.d.ts.map +1 -1
  40. package/dist/module-pack-build.js +4 -0
  41. package/dist/module-pack-build.js.map +2 -2
  42. package/dist/module-toggle.d.ts +33 -0
  43. package/dist/module-toggle.d.ts.map +1 -0
  44. package/dist/module-toggle.js +28 -0
  45. package/dist/module-toggle.js.map +7 -0
  46. package/dist/node-service-probe.d.ts +18 -0
  47. package/dist/node-service-probe.d.ts.map +1 -0
  48. package/dist/node-service-probe.js +97 -0
  49. package/dist/node-service-probe.js.map +7 -0
  50. package/dist/pack-lifecycle.d.ts.map +1 -1
  51. package/dist/pack-lifecycle.js +11 -1
  52. package/dist/pack-lifecycle.js.map +2 -2
  53. package/dist/repl-windows/service-window.d.ts +1 -1
  54. package/dist/repl-windows/service-window.d.ts.map +1 -1
  55. package/dist/repl-windows/service-window.js +8 -1
  56. package/dist/repl-windows/service-window.js.map +2 -2
  57. package/dist/repl.d.ts +0 -2
  58. package/dist/repl.d.ts.map +1 -1
  59. package/dist/repl.js +0 -19
  60. package/dist/repl.js.map +2 -2
  61. package/dist/runtime.d.ts +4 -13
  62. package/dist/runtime.d.ts.map +1 -1
  63. package/dist/runtime.js +15 -27
  64. package/dist/runtime.js.map +2 -2
  65. package/dist/send-target.d.ts.map +1 -1
  66. package/dist/send-target.js +6 -2
  67. package/dist/send-target.js.map +2 -2
  68. package/dist/services.d.ts +32 -6
  69. package/dist/services.d.ts.map +1 -1
  70. package/dist/services.js +101 -16
  71. package/dist/services.js.map +2 -2
  72. package/dist/wizard.d.ts.map +1 -1
  73. package/dist/wizard.js +65 -7
  74. package/dist/wizard.js.map +2 -2
  75. package/package.json +7 -8
  76. package/dist/cmd-remote.d.ts +0 -13
  77. package/dist/cmd-remote.d.ts.map +0 -1
  78. package/dist/cmd-remote.js +0 -38
  79. package/dist/cmd-remote.js.map +0 -7
  80. package/dist/module-publish.d.ts +0 -69
  81. package/dist/module-publish.d.ts.map +0 -1
  82. package/dist/module-publish.js +0 -478
  83. package/dist/module-publish.js.map +0 -7
  84. package/dist/module-watch.d.ts +0 -32
  85. package/dist/module-watch.d.ts.map +0 -1
  86. package/dist/module-watch.js +0 -171
  87. package/dist/module-watch.js.map +0 -7
  88. package/dist/remote-agent.d.ts +0 -18
  89. package/dist/remote-agent.d.ts.map +0 -1
  90. package/dist/remote-agent.js +0 -198
  91. package/dist/remote-agent.js.map +0 -7
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/module-commands.ts"],
4
- "sourcesContent": ["/**\n * sfmc module-commands \u2014 runtime CLI for inspecting and managing modules\n * already on disk under `modules/packages/<id>/`.\n *\n * \u9876\u5C42\u547D\u4EE4\u522B\u540D:`module` / `mod`(\u7531 main.ts / repl.ts \u5171\u540C\u8BC6\u522B)\u3002\n * \u5B50\u547D\u4EE4\u901A\u9053\u95E8\u7981\u89C1 command-surface.ts\uFF08dispatch \u524D\u7531 main/repl \u5224\u5B9A\uFF09\u3002\n */\n\nimport fs from \"node:fs/promises\";\nimport { existsSync, lstatSync, readdirSync } from \"node:fs\";\nimport path from \"node:path\";\nimport { spawn } from \"node:child_process\";\nimport { configPath, modulePath, readJson, type DBConfig, type ModuleLock } from \"@sfmc-bds/sdk/node/config\";\nimport {\n isDevAccentModuleSub,\n listVisibleModuleSubs,\n type CommandMode,\n} from \"./command-surface.js\";\nimport { failResult, okResult, type CliResult } from \"./cli-result.js\";\nimport { t } from \"./i18n/index.js\";\nimport { c } from \"./theme.js\";\nimport { ROOT, resolveFetchModule } from \"./runtime.js\";\nimport { dirFingerprint } from \"./module-fingerprint.js\";\nimport {\n DEFAULT_REGISTRY_REPO,\n DEFAULT_REGISTRY_TAG,\n findUnknownModules,\n resolveRegistryIndex,\n} from \"./registry.js\";\n\n/** \u9876\u5C42\u547D\u4EE4\u540D(\u4E3B\u540D + \u77ED\u522B\u540D),\u4F9B HELP / \u8865\u5168 / \u5206\u53D1\u5171\u7528\u3002 */\nexport const MODULE_CMD_NAMES = [\"module\", \"mod\"] as const;\n\nexport type ModuleCmdName = (typeof MODULE_CMD_NAMES)[number];\n\n/** \u5224\u65AD\u662F\u5426\u4E3A module \u9876\u5C42\u547D\u4EE4(\u542B\u522B\u540D);\u907F\u514D main/repl \u518D\u786C\u7F16\u7801 case\u3002 */\nexport function isModuleCommand(cmd: string | undefined): cmd is ModuleCmdName {\n return !!cmd && (MODULE_CMD_NAMES as readonly string[]).includes(cmd);\n}\n\n/** \u67D3\u8272\u540E\u7684 HELP \u524D\u7F00,\u907F\u514D HELP \u786C\u7F16\u7801 module/mod\u3002 */\nexport function paintModuleCmdAlias(paint: (name: string) => string): string {\n return MODULE_CMD_NAMES.map((name) => paint(name)).join(\"/\");\n}\n\n/** @deprecated \u4F7F\u7528 listVisibleModuleSubs(mode)\uFF1B\u4FDD\u7559\u5168\u96C6\u4F9B\u8C03\u8BD5\u3002 */\nexport const ALL_MODULE_SUBCOMMANDS = [\n \"list\",\n \"search\",\n \"install\",\n \"uninstall\",\n \"verify\",\n \"info\",\n \"enable\",\n \"disable\",\n \"build\",\n \"reload\",\n] as const;\n\n/** \u5F00\u53D1\u8005\u6837\u5F0F\u5B50\u547D\u4EE4\uFF08\u84DD\u6807\uFF0C\u975E\u95E8\u7981\uFF09\u3002 */\nexport const DEV_ACCENT_MODULE_SUBCOMMANDS = [\"build\", \"reload\"] as const;\n\n/** @deprecated \u4F7F\u7528 ALL_MODULE_SUBCOMMANDS \u6216 listVisibleModuleSubs\u3002 */\nexport const MODULE_SUBCOMMANDS = ALL_MODULE_SUBCOMMANDS;\n\n/** @deprecated \u4F7F\u7528 DEV_ACCENT_MODULE_SUBCOMMANDS / isDevAccentModuleSub\u3002 */\nexport const DEV_MODULE_SUBCOMMANDS = DEV_ACCENT_MODULE_SUBCOMMANDS;\n\nexport type ModuleSubcommand = (typeof ALL_MODULE_SUBCOMMANDS)[number];\n\n/** \u5F53\u524D\u901A\u9053\u4E0B\u53EF\u89C1\u7684 module \u5B50\u547D\u4EE4\uFF08\u81EA\u52A8\u8865\u5168 / usage\uFF09\u3002 */\nexport function getVisibleModuleSubcommands(mode: CommandMode): readonly string[] {\n return listVisibleModuleSubs(mode);\n}\n\n/** sub \u662F\u5426\u4E3A\u5F00\u53D1\u8005\u84DD\u6807\uFF08help \u7740\u8272\uFF09\u3002 */\nexport function isDeveloperSubcommand(sub: string | undefined): boolean {\n return isDevAccentModuleSub(sub);\n}\n\n/** Usage \u884C\u4E3B\u540D|\u522B\u540D(\u4E0E MODULE_CMD_NAMES \u540C\u6E90,\u907F\u514D\u4E0E HELP \u6F02\u79FB)\u3002 */\nexport function moduleUsage(mode: CommandMode = \"argv\"): string {\n return t(\"mod.usage\", {\n cmds: MODULE_CMD_NAMES.join(\"|\"),\n subs: getVisibleModuleSubcommands(mode).join(\"|\"),\n });\n}\n\n/** Where modules live on disk. */\nfunction modulesDir(): string {\n return path.join(ROOT, \"modules\", \"packages\");\n}\n\nfunction fmtBytes(n: number): string {\n if (n < 1024) return `${n} B`;\n if (n < 1024 * 1024) return `${(n / 1024).toFixed(1)} KB`;\n return `${(n / 1024 / 1024).toFixed(2)} MB`;\n}\n\nfunction shortHash(h: string): string {\n return h.slice(0, 8) + \"\u2026\" + h.slice(-8);\n}\n\ninterface ModuleManifest {\n schemaVersion?: number;\n id?: string;\n handlers?: string[];\n routes?: Array<{ method: string; path: string; handler: string }>;\n migrations?: Array<{ name: string; version: number }>;\n notes?: string;\n}\n\ninterface InstalledModule {\n id: string;\n path: string;\n manifest: ModuleManifest | null;\n totalBytes: number;\n fileCount: number;\n fingerprint: string;\n}\n\n/** Enumerate every installed module by scanning `modules/packages/<id>/`. */\nasync function scanInstalled(): Promise<InstalledModule[]> {\n const dir = modulesDir();\n if (!existsSync(dir)) return [];\n const entries = await fs.readdir(dir, { withFileTypes: true });\n const out: InstalledModule[] = [];\n for (const e of entries) {\n if (!e.isDirectory()) continue;\n const id = e.name;\n const modPath = path.join(dir, id);\n const manifestPath = path.join(modPath, \"sapi\", \"manifest.json\");\n let manifest: ModuleManifest | null = null;\n if (existsSync(manifestPath)) {\n try {\n manifest = JSON.parse(await fs.readFile(manifestPath, \"utf8\")) as ModuleManifest;\n } catch {\n /* corrupt manifest is not fatal \u2014 just skip its fields */\n }\n }\n const { totalBytes, fileCount } = await dirSize(modPath);\n const fingerprint = await dirFingerprint(modPath);\n out.push({ id, path: modPath, manifest, totalBytes, fileCount, fingerprint });\n }\n out.sort((a, b) => a.id.localeCompare(b.id));\n return out;\n}\n\nasync function dirSize(dir: string): Promise<{ totalBytes: number; fileCount: number }> {\n let totalBytes = 0;\n let fileCount = 0;\n async function walk(p: string): Promise<void> {\n for (const e of await fs.readdir(p, { withFileTypes: true })) {\n const child = path.join(p, e.name);\n if (e.isDirectory()) await walk(child);\n else if (e.isFile()) {\n const s = await fs.stat(child);\n totalBytes += s.size;\n fileCount++;\n }\n }\n }\n await walk(dir);\n return { totalBytes, fileCount };\n}\n\n/* \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n * list\n * \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\nexport async function cmdModuleList(_args: string[]): Promise<string> {\n const installed = await scanInstalled();\n if (installed.length === 0) {\n return c.dim(t(\"mod.noneInstalled\", { dir: modulesDir() }));\n }\n const lock =\n (readJson<ModuleLock>(modulePath(path.join(ROOT, \"modules\"), \"module-lock.json\")) ?? {\n version: 1,\n modules: {},\n }) as ModuleLock;\n const ids = installed.map((m) => m.id);\n const unknown = new Set(await findUnknownModules(ids));\n const lines: string[] = [c.bold(`\\n${t(\"mod.list.title\")}`), c.dim(` ${modulesDir()}`)];\n const header = ` ${\"id\".padEnd(24)}${\"state\".padEnd(8)}${\"files\".padEnd(8)}${\"size\".padEnd(10)}${\"fingerprint\"}`;\n lines.push(c.dim(header));\n for (const m of installed) {\n const logicalId = typeof m.manifest?.id === \"string\" && m.manifest.id ? m.manifest.id : m.id;\n const enabled = lock.modules?.[logicalId]?.enabled === true;\n const stateCol = (enabled ? c.green(\"on\") : c.dim(\"off\")).padEnd(8);\n let mark: string;\n if (!m.manifest) {\n mark = c.yellow(\"\u25CB\");\n } else if (unknown.has(m.id)) {\n mark = c.yellow(\"?\");\n } else {\n mark = enabled ? c.green(\"\u25CF\") : c.dim(\"\u25CB\");\n }\n const idLabel = logicalId !== m.id ? `${m.id}(${logicalId})` : m.id;\n lines.push(\n ` ${mark} ${idLabel.padEnd(22)}${stateCol}${String(m.fileCount).padEnd(8)}${fmtBytes(m.totalBytes).padEnd(10)}${shortHash(m.fingerprint)}`\n );\n }\n lines.push(c.dim(`\\n tip: ${MODULE_CMD_NAMES[1] ?? \"mod\"} enable|disable <logicalId>`));\n return lines.join(\"\\n\") + \"\\n\";\n}\n\n/**\n * Walk `modules/packages/<id>/` and print a one-line yellow warning for each\n * id that isn't in the first-party registry. Intended for the REPL startup\n * hook so users immediately see modules they installed from somewhere else.\n *\n * Best-effort: registry unreachable \u2192 no warning (no false positives).\n */\nexport async function scanAndWarnUnknown(): Promise<string> {\n const installed = await scanInstalled();\n if (installed.length === 0) return \"\";\n const unknown = await findUnknownModules(installed.map((m) => m.id));\n if (unknown.length === 0) return \"\";\n const list = unknown.map((id) => ` ${c.yellow(\"?\")} ${id}`).join(\"\\n\");\n return `${c.yellow(\"[sfmc] modules installed from unknown publisher \u2014 verify before use:\")}\\n${list}\\n`;\n}\n\n/* \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n * search \u2014 \u62C9\u53D6 first-party registry;\u5E26 id \u67E5\u5355\u6761 registry info\n * \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n/**\n * \u62C9\u53D6 first-party registry \u6A21\u5757\u5217\u8868;\u5E26 id \u65F6\u5C55\u793A\u8BE5\u6761\u76EE\u7684 registry info\u3002\n * \u4E0E\u672C\u5730 `info`(\u5DF2\u5B89\u88C5\u78C1\u76D8\u8BE6\u60C5)\u533A\u5206:`search` \u770B registry,`info` \u770B\u672C\u673A packages\u3002\n */\nexport async function cmdModuleSearch(args: string[]): Promise<string> {\n const query = args[0];\n const { index, stale } = await resolveRegistryIndex({ force: true });\n const ids = Object.keys(index).sort((a, b) => a.localeCompare(b));\n\n if (ids.length === 0) {\n return c.red(\n `\\nRegistry empty or unreachable (${DEFAULT_REGISTRY_REPO}@${DEFAULT_REGISTRY_TAG}).\\n` +\n `Check network, or: mod install <id> --from github:owner/repo@tag\\n`\n );\n }\n\n const staleNote = stale ? c.yellow(\" (offline \u2014 showing cached index)\\n\") : \"\";\n\n /* \u65E0\u53C2\u6570:\u5217\u51FA\u5168\u90E8 */\n if (!query) {\n const installed = new Set(listInstalledModuleIdsSync());\n const lines: string[] = [\n c.bold(`\\nFirst-party registry (${DEFAULT_REGISTRY_REPO}@${DEFAULT_REGISTRY_TAG}) \u2014 ${ids.length} modules`),\n ];\n if (staleNote) lines.push(staleNote.trimEnd());\n lines.push(c.dim(` ${\"id\".padEnd(28)}${\"source\".padEnd(40)}local`));\n for (const id of ids) {\n const e = index[id]!;\n const src = `${e.repo}@${e.tag}`;\n const local = installed.has(id) ? c.green(\"\u25CF\") : c.dim(\"\u25CB\");\n lines.push(` ${local} ${id.padEnd(26)}${src.padEnd(40)}${installed.has(id) ? \"installed\" : \"\"}`);\n }\n lines.push(c.dim(`\\n tip: sfmc mod search <id> \u2192 registry info`));\n lines.push(c.dim(` sfmc mod install <id> \u2192 download + catalog sync`));\n return lines.join(\"\\n\") + \"\\n\";\n }\n\n /* \u5E26 id:\u67E5\u5355\u6761 registry info */\n const entry = index[query];\n if (!entry) {\n const hints = ids.filter((id) => id.includes(query) || query.includes(id)).slice(0, 8);\n const hintBlock =\n hints.length > 0\n ? c.dim(`\\n Did you mean:\\n`) + hints.map((h) => ` ${h}`).join(\"\\n\")\n : c.dim(`\\n Known ids: ${ids.slice(0, 12).join(\", \")}${ids.length > 12 ? \", \u2026\" : \"\"}`);\n return c.red(t(\"mod.notInRegistry\", { query })) + hintBlock + \"\\n\";\n }\n\n const installedPath = path.join(modulesDir(), query);\n const isInstalled = existsSync(installedPath);\n const lines: string[] = [c.bold(`\\n${query}`)];\n if (staleNote) lines.push(staleNote.trimEnd());\n lines.push(` registry : ${DEFAULT_REGISTRY_REPO}@${DEFAULT_REGISTRY_TAG}`);\n lines.push(` repo : ${entry.repo}`);\n lines.push(` tag : ${entry.tag}`);\n lines.push(` source : github:${entry.repo}@${entry.tag}`);\n lines.push(` github : https://github.com/${entry.repo}/tree/${entry.tag}`);\n lines.push(\n ` local : ${isInstalled ? c.green(`installed @ ${installedPath}`) : c.dim(\"not installed\")}`\n );\n\n if (!isInstalled) {\n lines.push(c.dim(`\\n install: sfmc mod install ${query}`));\n } else {\n lines.push(c.dim(`\\n details: sfmc mod info ${query}`));\n }\n return lines.join(\"\\n\") + \"\\n\";\n}\n\n/* \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n * info\n * \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\nexport async function cmdModuleInfo(args: string[]): Promise<string> {\n const id = args[0];\n if (!id) return c.yellow(t(\"mod.info.usage\"));\n const all = await scanInstalled();\n const m = all.find((x) => x.id === id);\n if (!m) return c.red(t(\"mod.notInstalledAt\", { id, path: path.join(modulesDir(), id) }));\n const lines: string[] = [c.bold(`\\n${id}`)];\n lines.push(` path : ${m.path}`);\n lines.push(` files : ${m.fileCount}`);\n lines.push(` size : ${fmtBytes(m.totalBytes)}`);\n lines.push(` fingerprint : ${m.fingerprint}`);\n if (m.manifest) {\n lines.push(` schemaVer : ${m.manifest.schemaVersion ?? \"(none)\"}`);\n lines.push(` routes : ${m.manifest.routes?.length ?? 0}`);\n if (m.manifest.routes?.length) {\n for (const r of m.manifest.routes) lines.push(c.dim(` ${r.method.padEnd(7)} ${r.path.padEnd(36)} ${r.handler}`));\n }\n lines.push(` migrations : ${m.manifest.migrations?.length ?? 0}`);\n if (m.manifest.migrations?.length) {\n for (const mg of m.manifest.migrations) lines.push(c.dim(` v${mg.version} ${mg.name}`));\n }\n if (m.manifest.notes) lines.push(` notes : ${c.dim(m.manifest.notes)}`);\n } else {\n lines.push(c.yellow(` manifest : (missing or unreadable)`));\n }\n return lines.join(\"\\n\") + \"\\n\";\n}\n\n/* \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n * verify\n * \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\nexport async function cmdModuleVerify(args: string[]): Promise<string> {\n const id = args[0];\n if (id) {\n const all = await scanInstalled();\n const m = all.find((x) => x.id === id);\n if (!m) return c.red(t(\"mod.notInstalled\", { id }));\n return c.green(t(\"mod.verifyOk\", { id, fp: m.fingerprint }));\n }\n const all = await scanInstalled();\n const lines = [c.bold(\"\\nVerifying installed modules\")];\n for (const m of all) {\n lines.push(` ${m.id.padEnd(28)} ${shortHash(m.fingerprint)}`);\n }\n if (all.length === 0) lines.push(c.dim(\" (none)\"));\n return lines.join(\"\\n\") + \"\\n\";\n}\n\n/* \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n * install \u2014 shells out to tools/fetch-module.mjs\n * \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n/* \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n * enable / disable \u2014 talk to db-server over loopback HTTP\n * \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\nfunction readDbConfig(): DBConfig {\n return (readJson<DBConfig>(configPath(ROOT, \"db_config.json\")) ?? {}) as DBConfig;\n}\n\nasync function postModuleToggle(id: string, action: \"enable\" | \"disable\"): Promise<CliResult> {\n const cfg = readDbConfig();\n const port = cfg.db_port ?? 3001;\n const token = cfg.http_auth || \"\";\n const url = `http://127.0.0.1:${port}/api/sfmc/modules/${encodeURIComponent(id)}/${action}`;\n let res: Response;\n try {\n res = await fetch(url, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n ...(token ? { Authorization: `Bearer ${token}` } : {}),\n },\n });\n } catch (err) {\n return failResult(\n c.red(t(\"mod.dbUnreachable\", { url, message: (err as Error).message }))\n );\n }\n const text = await res.text();\n let body: unknown;\n try {\n body = JSON.parse(text);\n } catch {\n body = text;\n }\n if (!res.ok) {\n const err = (body as { error?: string })?.error ?? `HTTP ${res.status}`;\n return failResult(c.red(t(\"mod.toggleFailed\", { action, id, err })));\n }\n const ok = (body as { success?: boolean })?.success !== false;\n if (ok) {\n const label = action === \"enable\" ? t(\"mod.action.enabled\") : t(\"mod.action.disabled\");\n return okResult(c.green(t(\"mod.toggleOk\", { label, id })));\n }\n return failResult(c.red(t(\"mod.toggleBadBody\", { action, id, text })));\n}\n\nexport async function cmdModuleEnable(args: string[]): Promise<CliResult> {\n const id = args[0];\n if (!id) return failResult(c.yellow(t(\"mod.enable.usage\")));\n return postModuleToggle(id, \"enable\");\n}\n\nexport async function cmdModuleDisable(args: string[]): Promise<CliResult> {\n const id = args[0];\n if (!id) return failResult(c.yellow(t(\"mod.disable.usage\")));\n return postModuleToggle(id, \"disable\");\n}\n\n/* \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n * install \u2014 shells out to tools/fetch-module.mjs\n * \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n/**\n * \u9884\u68C0 --from \u53D6\u503C\u662F\u5426\u662F\u5408\u6CD5 scheme\uFF1A\n * - npm:@scope/name / npm:<name>\n * - local[:<path>] / local\n * - tgz:<path>\n * - zip:<path>\n * - dir:<abs path>\n * - github:<owner>/<repo>[@tag]\n * - \u88F8\u8DEF\u5F84\uFF1A\u5FC5\u987B\u5B58\u5728\u4E14\u4E3A\u76EE\u5F55\uFF08\u88F8\u6587\u4EF6\u5E94\u8F6C tgz:/zip:\uFF09\n * \u8FD4\u56DE null \u8868\u793A\u5408\u6CD5\uFF1B\u5426\u5219\u8FD4\u56DE\u7528\u6237\u53EF\u8BFB\u7684\u9519\u8BEF\u6587\u6848\u3002\n */\nfunction validateFromScheme(from: string): string | null {\n if (\n from === \"local\" ||\n from.startsWith(\"local:\") ||\n from.startsWith(\"dir:\") ||\n from.startsWith(\"npm:\") ||\n from.startsWith(\"tgz:\") ||\n from.startsWith(\"zip:\") ||\n from.startsWith(\"github:\")\n ) {\n return null;\n }\n if (existsSync(from)) {\n const st = lstatSync(from);\n if (st.isDirectory()) return null;\n return `--from \u88F8\u8DEF\u5F84\u987B\u4E3A\u76EE\u5F55\uFF08\u6587\u4EF6\u8BF7\u7528 --from local:<tgz|zip>\uFF09: ${from}`;\n }\n return t(\"mod.fromUnknown\", { value: from });\n}\n\nexport async function cmdModuleInstall(args: string[]): Promise<string> {\n // \u652F\u6301: install <id> [id2 ...] [--from ...] [--link] [--sha256 ...]\n const flags = parseFlags(args);\n const positional: string[] = [];\n for (let i = 0; i < args.length; i++) {\n if (args[i] === \"--from\" || args[i] === \"--sha256\") {\n i++;\n continue;\n }\n if (args[i]?.startsWith(\"--from=\") || args[i]?.startsWith(\"--sha256=\")) continue;\n if (args[i]?.startsWith(\"--\")) continue;\n positional.push(args[i]!);\n }\n if (positional.length === 0) {\n return c.yellow(t(\"mod.install.usage\"));\n }\n\n /* scheme \u9884\u68C0\uFF1A\u907F\u514D\u62FC\u5199\u9519\u8BEF\u5EF6\u8FDF\u5230\u5B50\u8FDB\u7A0B\u62A5\u9519 */\n if (flags.from) {\n const err = validateFromScheme(flags.from);\n if (err) return c.red(err);\n }\n\n const fetchScript = resolveFetchModule();\n if (!fetchScript) {\n return c.red(t(\"mod.fetchMissing\"));\n }\n const sub = [\"install\", ...positional];\n if (flags.from) sub.push(\"--from\", flags.from);\n if (flags.sha256) sub.push(\"--sha256\", flags.sha256);\n if (flags.link) sub.push(\"--link\");\n return new Promise<string>((resolve) => {\n const proc = spawn(process.execPath, [fetchScript, ...sub], {\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n env: { ...process.env, SFMC_ROOT: ROOT },\n });\n let out = \"\";\n proc.stdout?.on(\"data\", (d: Buffer) => {\n out += d.toString();\n });\n proc.stderr?.on(\"data\", (d: Buffer) => {\n out += d.toString();\n });\n proc.on(\"exit\", (code) => {\n resolve(out + (code === 0 ? \"\" : `\\n[exit ${code}]`));\n });\n proc.on(\"error\", (e) => resolve(c.red(`spawn failed: ${e.message}`)));\n });\n}\n\n/* \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n * uninstall\n * \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\nexport async function cmdModuleUninstall(args: string[]): Promise<string> {\n const id = args[0];\n if (!id) return c.yellow(t(\"mod.uninstall.usage\"));\n const fetchScript = resolveFetchModule();\n if (!fetchScript) {\n // \u56DE\u9000:\u4EC5\u5220\u76EE\u5F55(\u65E7\u884C\u4E3A)\n const target = path.join(modulesDir(), id);\n if (!existsSync(target)) return c.yellow(t(\"mod.notInstalledFolder\", { id, path: target }));\n await fs.rm(target, { recursive: true, force: true });\n return c.green(t(\"mod.removed\", { id, path: target }));\n }\n return new Promise<string>((resolve) => {\n const proc = spawn(process.execPath, [fetchScript, \"uninstall\", id], {\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n env: { ...process.env, SFMC_ROOT: ROOT },\n });\n let out = \"\";\n proc.stdout?.on(\"data\", (d: Buffer) => {\n out += d.toString();\n });\n proc.stderr?.on(\"data\", (d: Buffer) => {\n out += d.toString();\n });\n proc.on(\"exit\", (code) => {\n resolve(out + (code === 0 ? \"\" : `\\n[exit ${code}]`));\n });\n proc.on(\"error\", (e) => resolve(c.red(`spawn failed: ${e.message}`)));\n });\n}\n\n/* \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n * CLI flag parsing\n * \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\ninterface InstallFlags {\n from: string | null;\n sha256: string | null;\n link: boolean;\n}\n\nfunction parseFlags(args: string[]): InstallFlags {\n const flags: InstallFlags = { from: null, sha256: null, link: false };\n for (let i = 0; i < args.length; i++) {\n if (args[i] === \"--from\") flags.from = args[++i] ?? null;\n else if (args[i]?.startsWith(\"--from=\")) flags.from = args[i]!.slice(\"--from=\".length);\n else if (args[i] === \"--sha256\") flags.sha256 = args[++i] ?? null;\n else if (args[i]?.startsWith(\"--sha256=\")) flags.sha256 = args[i]!.slice(\"--sha256=\".length);\n else if (args[i] === \"--link\") flags.link = true;\n }\n return flags;\n}\n\n/**\n * `sfmc mod test` \u2014 \u59D4\u6258\u6A21\u5757\u4ED3\u7684 test runner\uFF08node --test + @sfmc-bds/sdk/testing\uFF09\u3002\n * \u89E3\u6790 --from local[:path] \u89C4\u5219\u4E0E watch \u4E00\u81F4\uFF1B\u7F3A\u7701 cwd\u3002\n * \u900F\u4F20 npm test\uFF1A\u8BA9\u6A21\u5757\u4ED3\u7684 `scripts.test` \u81EA\u5DF1\u51B3\u5B9A\u600E\u4E48\u8DD1\uFF08node --test / tsx / vitest \u7B49\uFF09\u3002\n */\nexport async function cmdModuleTest(args: string[]): Promise<string> {\n let fromRaw: string | null = null;\n const passthrough: string[] = [];\n for (let i = 0; i < args.length; i++) {\n const a = args[i];\n if (a === \"--from\") {\n fromRaw = args[++i] ?? null;\n } else if (a?.startsWith(\"--from=\")) {\n fromRaw = a.slice(\"--from=\".length);\n } else if (a === \"--help\" || a === \"-h\") {\n return c.dim(\"\u7528\u6CD5: mod test [--from local[:<path>]] [-- <args>]\\n \u900F\u4F20\u7ED9\u6A21\u5757\u4ED3\u7684 npm test\u3002\");\n } else {\n passthrough.push(a!);\n }\n }\n\n /* \u89E3\u6790 cwd\uFF08\u4E0E watch \u5171\u7528 resolveLocalModuleRoot \u89C4\u5219\uFF09\u3002 */\n const { resolveLocalModuleRoot } = await import(\"./module-watch.js\");\n const cwd = resolveLocalModuleRoot({ from: fromRaw, cwd: process.cwd() });\n\n if (!existsSync(cwd)) {\n return c.red(`[mod test] \u8DEF\u5F84\u4E0D\u5B58\u5728: ${cwd}`);\n }\n if (!existsSync(path.join(cwd, \"package.json\"))) {\n return c.yellow(`[mod test] \u672A\u627E\u5230 package.json: ${cwd}\\n \u63D0\u793A\uFF1A\u8FDB\u5165\u6A21\u5757\u4ED3\u6839\u76EE\u5F55\uFF0C\u6216\u7528 --from local:<path> \u6307\u5411\u3002`);\n }\n\n /* Windows \u7528 cmd /c npm \u900F\u4F20 npm.cmd\uFF08\u907F\u514D shell:true \u7684 DEP0190 \u5B89\u5168\u8B66\u544A\uFF09\u3002 */\n const isWin = process.platform === \"win32\";\n const cmd = isWin ? \"cmd.exe\" : \"npm\";\n const subArgs = isWin ? [\"/c\", \"npm\", \"test\", \"--\", ...passthrough] : [\"test\", \"--\", ...passthrough];\n\n return new Promise<string>((resolve) => {\n const proc = spawn(cmd, subArgs, {\n cwd,\n stdio: \"inherit\",\n env: process.env,\n });\n proc.on(\"exit\", (code) => {\n resolve(code === 0 ? \"\" : `\\n[mod test] exit ${code}`);\n });\n proc.on(\"error\", (e) => resolve(c.red(`[mod test] spawn failed: ${e.message}`)));\n });\n}\n\n/**\n * \u7EDF\u4E00\u5206\u53D1 module/mod \u5B50\u547D\u4EE4 \u2014\u2014 CLI(`main.ts`)\u4E0E REPL(`repl.ts`)\u5171\u7528,\n * \u907F\u514D\u4E24\u5904 switch \u6F02\u79FB\u3002\n *\n * \u901A\u9053\u95E8\u7981\uFF08external/repl\uFF09\u7531\u8C03\u7528\u65B9\u5728 dispatch \u524D\u7ECF command-surface \u5224\u5B9A\uFF1B\n * \u672C\u51FD\u6570\u53EA\u8D1F\u8D23\u5B50\u547D\u4EE4\u8DEF\u7531\u3002`remove` \u4F5C\u4E3A uninstall \u7684\u540C\u4E49\u522B\u540D\u4FDD\u7559\u3002\n */\nexport async function dispatchModuleCommand(sub: string | undefined, args: string[]): Promise<string> {\n switch (sub) {\n case \"list\":\n return cmdModuleList(args);\n case \"search\":\n return cmdModuleSearch(args);\n case \"install\":\n return cmdModuleInstall(args);\n case \"uninstall\":\n case \"remove\":\n return cmdModuleUninstall(args);\n case \"verify\":\n return cmdModuleVerify(args);\n case \"info\":\n return cmdModuleInfo(args);\n case \"enable\":\n return (await cmdModuleEnable(args)).message;\n case \"disable\":\n return (await cmdModuleDisable(args)).message;\n case \"build\": {\n const { cmdModuleBuild } = await import(\"./module-pack-build.js\");\n return cmdModuleBuild(args);\n }\n case \"reload\": {\n const { cmdModuleReload } = await import(\"./module-pack-build.js\");\n return cmdModuleReload(args);\n }\n case \"watch\": {\n const { cmdModuleWatch } = await import(\"./module-watch.js\");\n return cmdModuleWatch(args);\n }\n case \"test\": {\n return cmdModuleTest(args);\n }\n case \"publish\": {\n const { cmdModulePublish } = await import(\"./module-publish.js\");\n return cmdModulePublish(args);\n }\n default:\n return c.yellow(moduleUsage());\n }\n}\n\n/** \u540C\u6B65\u679A\u4E3E\u5DF2\u5B89\u88C5\u6A21\u5757 id,\u4F9B REPL Tab \u8865\u5168(\u4E0D\u8BFB fingerprint,\u5C3D\u91CF\u8F7B\u91CF)\u3002 */\nexport function listInstalledModuleIdsSync(): string[] {\n const dir = modulesDir();\n if (!existsSync(dir)) return [];\n try {\n return readdirSync(dir, { withFileTypes: true })\n .filter((e) => e.isDirectory())\n .map((e) => e.name)\n .sort((a, b) => a.localeCompare(b));\n } catch {\n return [];\n }\n}"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * sfmc module-commands \u2014 runtime CLI for inspecting and managing modules\n * already on disk under `modules/packages/<id>/`.\n *\n * \u9876\u5C42\u547D\u4EE4\u522B\u540D:`module` / `mod`(\u7531 main.ts / repl.ts \u5171\u540C\u8BC6\u522B)\u3002\n * \u5B50\u547D\u4EE4\u901A\u9053\u95E8\u7981\u89C1 command-surface.ts\uFF08dispatch \u524D\u7531 main/repl \u5224\u5B9A\uFF09\u3002\n */\n\nimport fs from \"node:fs/promises\";\nimport { existsSync, lstatSync, readdirSync } from \"node:fs\";\nimport path from \"node:path\";\nimport { spawn } from \"node:child_process\";\nimport {\n configPath,\n modulePath,\n readJson,\n writeJson,\n type Catalog,\n type DBConfig,\n type ModuleLock,\n} from \"@sfmc-bds/sdk/node/config\";\nimport {\n isDevAccentModuleSub,\n listVisibleModuleSubs,\n type CommandMode,\n} from \"./command-surface.js\";\nimport { failResult, okResult, type CliResult } from \"./cli-result.js\";\nimport { t } from \"./i18n/index.js\";\nimport { c } from \"./theme.js\";\nimport { ROOT, resolveFetchModule } from \"./runtime.js\";\nimport { dirFingerprint } from \"./module-fingerprint.js\";\nimport {\n applyLockEnabled,\n finalizeToggle,\n resolveToggleTarget,\n type ToggleCandidate,\n type ToggleNotify,\n} from \"./module-toggle.js\";\nimport {\n DEFAULT_REGISTRY_REPO,\n DEFAULT_REGISTRY_TAG,\n findUnknownModules,\n resolveRegistryIndex,\n} from \"./registry.js\";\n\n/** \u9876\u5C42\u547D\u4EE4\u540D(\u4E3B\u540D + \u77ED\u522B\u540D),\u4F9B\u5E2E\u52A9 / \u8865\u5168 / \u5206\u53D1\u5171\u7528\u3002 */\nexport const MODULE_CMD_NAMES = [\"module\", \"mod\"] as const;\n\nexport type ModuleCmdName = (typeof MODULE_CMD_NAMES)[number];\n\n/** \u5224\u65AD\u662F\u5426\u4E3A module \u9876\u5C42\u547D\u4EE4(\u542B\u522B\u540D);\u907F\u514D main/repl \u518D\u786C\u7F16\u7801 case\u3002 */\nexport function isModuleCommand(cmd: string | undefined): cmd is ModuleCmdName {\n return !!cmd && (MODULE_CMD_NAMES as readonly string[]).includes(cmd);\n}\n\n/** \u5F00\u53D1\u8005\u6837\u5F0F\u5B50\u547D\u4EE4\uFF08\u84DD\u6807\uFF0C\u975E\u95E8\u7981\uFF09\u3002 */\nexport const DEV_ACCENT_MODULE_SUBCOMMANDS = [\"build\", \"reload\"] as const;\n\n/** \u5F53\u524D\u901A\u9053\u4E0B\u53EF\u89C1\u7684 module \u5B50\u547D\u4EE4\uFF08\u81EA\u52A8\u8865\u5168 / usage\uFF09\u3002 */\nexport function getVisibleModuleSubcommands(mode: CommandMode): readonly string[] {\n return listVisibleModuleSubs(mode);\n}\n\n/** sub \u662F\u5426\u4E3A\u5F00\u53D1\u8005\u84DD\u6807\uFF08help \u7740\u8272\uFF09\u3002 */\nexport function isDeveloperSubcommand(sub: string | undefined): boolean {\n return isDevAccentModuleSub(sub);\n}\n\n/** Usage \u884C\u4E3B\u540D|\u522B\u540D(\u4E0E MODULE_CMD_NAMES \u540C\u6E90,\u907F\u514D\u4E0E\u5E2E\u52A9\u6587\u6848\u6F02\u79FB)\u3002 */\nexport function moduleUsage(mode: CommandMode = \"argv\"): string {\n return t(\"mod.usage\", {\n cmds: MODULE_CMD_NAMES.join(\"|\"),\n subs: getVisibleModuleSubcommands(mode).join(\"|\"),\n });\n}\n\n/** Where modules live on disk. */\nfunction modulesDir(): string {\n return path.join(ROOT, \"modules\", \"packages\");\n}\n\nfunction fmtBytes(n: number): string {\n if (n < 1024) return `${n} B`;\n if (n < 1024 * 1024) return `${(n / 1024).toFixed(1)} KB`;\n return `${(n / 1024 / 1024).toFixed(2)} MB`;\n}\n\nfunction shortHash(h: string): string {\n return h.slice(0, 8) + \"\u2026\" + h.slice(-8);\n}\n\ninterface ModuleManifest {\n schemaVersion?: number;\n id?: string;\n handlers?: string[];\n routes?: Array<{ method: string; path: string; handler: string }>;\n migrations?: Array<{ name: string; version: number }>;\n notes?: string;\n}\n\ninterface InstalledModule {\n id: string;\n path: string;\n manifest: ModuleManifest | null;\n totalBytes: number;\n fileCount: number;\n fingerprint: string;\n}\n\n/** Enumerate every installed module by scanning `modules/packages/<id>/`. */\nasync function scanInstalled(): Promise<InstalledModule[]> {\n const dir = modulesDir();\n if (!existsSync(dir)) return [];\n const entries = await fs.readdir(dir, { withFileTypes: true });\n const out: InstalledModule[] = [];\n for (const e of entries) {\n if (!e.isDirectory()) continue;\n const id = e.name;\n const modPath = path.join(dir, id);\n const manifestPath = path.join(modPath, \"sapi\", \"manifest.json\");\n let manifest: ModuleManifest | null = null;\n if (existsSync(manifestPath)) {\n try {\n manifest = JSON.parse(await fs.readFile(manifestPath, \"utf8\")) as ModuleManifest;\n } catch {\n /* corrupt manifest is not fatal \u2014 just skip its fields */\n }\n }\n const { totalBytes, fileCount } = await dirSize(modPath);\n const fingerprint = await dirFingerprint(modPath);\n out.push({ id, path: modPath, manifest, totalBytes, fileCount, fingerprint });\n }\n out.sort((a, b) => a.id.localeCompare(b.id));\n return out;\n}\n\nasync function dirSize(dir: string): Promise<{ totalBytes: number; fileCount: number }> {\n let totalBytes = 0;\n let fileCount = 0;\n async function walk(p: string): Promise<void> {\n for (const e of await fs.readdir(p, { withFileTypes: true })) {\n const child = path.join(p, e.name);\n if (e.isDirectory()) await walk(child);\n else if (e.isFile()) {\n const s = await fs.stat(child);\n totalBytes += s.size;\n fileCount++;\n }\n }\n }\n await walk(dir);\n return { totalBytes, fileCount };\n}\n\n/* \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n * list\n * \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\nexport async function cmdModuleList(_args: string[]): Promise<string> {\n const installed = await scanInstalled();\n if (installed.length === 0) {\n return c.dim(t(\"mod.noneInstalled\", { dir: modulesDir() }));\n }\n const lock =\n (readJson<ModuleLock>(modulePath(path.join(ROOT, \"modules\"), \"module-lock.json\")) ?? {\n version: 1,\n modules: {},\n }) as ModuleLock;\n const ids = installed.map((m) => m.id);\n const unknown = new Set(await findUnknownModules(ids));\n const lines: string[] = [c.bold(`\\n${t(\"mod.list.title\")}`), c.dim(` ${modulesDir()}`)];\n const header = ` ${\"id\".padEnd(24)}${\"state\".padEnd(8)}${\"files\".padEnd(8)}${\"size\".padEnd(10)}${\"fingerprint\"}`;\n lines.push(c.dim(header));\n for (const m of installed) {\n const logicalId = typeof m.manifest?.id === \"string\" && m.manifest.id ? m.manifest.id : m.id;\n const enabled = lock.modules?.[logicalId]?.enabled === true;\n const stateCol = (enabled ? c.green(\"on\") : c.dim(\"off\")).padEnd(8);\n let mark: string;\n if (!m.manifest) {\n mark = c.yellow(\"\u25CB\");\n } else if (unknown.has(m.id)) {\n mark = c.yellow(\"?\");\n } else {\n mark = enabled ? c.green(\"\u25CF\") : c.dim(\"\u25CB\");\n }\n const idLabel = logicalId !== m.id ? `${m.id}(${logicalId})` : m.id;\n lines.push(\n ` ${mark} ${idLabel.padEnd(22)}${stateCol}${String(m.fileCount).padEnd(8)}${fmtBytes(m.totalBytes).padEnd(10)}${shortHash(m.fingerprint)}`\n );\n }\n lines.push(c.dim(`\\n tip: ${MODULE_CMD_NAMES[1] ?? \"mod\"} enable|disable <logicalId>`));\n return lines.join(\"\\n\") + \"\\n\";\n}\n\n/**\n * Walk `modules/packages/<id>/` and print a one-line yellow warning for each\n * id that isn't in the first-party registry. Intended for the REPL startup\n * hook so users immediately see modules they installed from somewhere else.\n *\n * Best-effort: registry unreachable \u2192 no warning (no false positives).\n */\nexport async function scanAndWarnUnknown(): Promise<string> {\n const installed = await scanInstalled();\n if (installed.length === 0) return \"\";\n const unknown = await findUnknownModules(installed.map((m) => m.id));\n if (unknown.length === 0) return \"\";\n const list = unknown.map((id) => ` ${c.yellow(\"?\")} ${id}`).join(\"\\n\");\n return `${c.yellow(\"[sfmc] modules installed from unknown publisher \u2014 verify before use:\")}\\n${list}\\n`;\n}\n\n/* \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n * search \u2014 \u62C9\u53D6 first-party registry;\u5E26 id \u67E5\u5355\u6761 registry info\n * \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n/**\n * \u62C9\u53D6 first-party registry \u6A21\u5757\u5217\u8868;\u5E26 id \u65F6\u5C55\u793A\u8BE5\u6761\u76EE\u7684 registry info\u3002\n * \u4E0E\u672C\u5730 `info`(\u5DF2\u5B89\u88C5\u78C1\u76D8\u8BE6\u60C5)\u533A\u5206:`search` \u770B registry,`info` \u770B\u672C\u673A packages\u3002\n */\nexport async function cmdModuleSearch(args: string[]): Promise<string> {\n const query = args[0];\n const { index, stale } = await resolveRegistryIndex({ force: true });\n const ids = Object.keys(index).sort((a, b) => a.localeCompare(b));\n\n if (ids.length === 0) {\n return c.red(\n `\\nRegistry empty or unreachable (${DEFAULT_REGISTRY_REPO}@${DEFAULT_REGISTRY_TAG}).\\n` +\n `Check network, or: mod install <id> --from github:owner/repo@tag\\n`\n );\n }\n\n const staleNote = stale ? c.yellow(\" (offline \u2014 showing cached index)\\n\") : \"\";\n\n /* \u65E0\u53C2\u6570:\u5217\u51FA\u5168\u90E8 */\n if (!query) {\n const installed = new Set(listInstalledModuleIdsSync());\n const lines: string[] = [\n c.bold(`\\nFirst-party registry (${DEFAULT_REGISTRY_REPO}@${DEFAULT_REGISTRY_TAG}) \u2014 ${ids.length} modules`),\n ];\n if (staleNote) lines.push(staleNote.trimEnd());\n lines.push(c.dim(` ${\"id\".padEnd(28)}${\"source\".padEnd(40)}local`));\n for (const id of ids) {\n const e = index[id]!;\n const src = `${e.repo}@${e.tag}`;\n const local = installed.has(id) ? c.green(\"\u25CF\") : c.dim(\"\u25CB\");\n lines.push(` ${local} ${id.padEnd(26)}${src.padEnd(40)}${installed.has(id) ? \"installed\" : \"\"}`);\n }\n lines.push(c.dim(`\\n tip: sfmc mod search <id> \u2192 registry info`));\n lines.push(c.dim(` sfmc mod install <id> \u2192 download + catalog sync`));\n return lines.join(\"\\n\") + \"\\n\";\n }\n\n /* \u5E26 id:\u67E5\u5355\u6761 registry info */\n const entry = index[query];\n if (!entry) {\n const hints = ids.filter((id) => id.includes(query) || query.includes(id)).slice(0, 8);\n const hintBlock =\n hints.length > 0\n ? c.dim(`\\n Did you mean:\\n`) + hints.map((h) => ` ${h}`).join(\"\\n\")\n : c.dim(`\\n Known ids: ${ids.slice(0, 12).join(\", \")}${ids.length > 12 ? \", \u2026\" : \"\"}`);\n return c.red(t(\"mod.notInRegistry\", { query })) + hintBlock + \"\\n\";\n }\n\n const installedPath = path.join(modulesDir(), query);\n const isInstalled = existsSync(installedPath);\n const lines: string[] = [c.bold(`\\n${query}`)];\n if (staleNote) lines.push(staleNote.trimEnd());\n lines.push(` registry : ${DEFAULT_REGISTRY_REPO}@${DEFAULT_REGISTRY_TAG}`);\n lines.push(` repo : ${entry.repo}`);\n lines.push(` tag : ${entry.tag}`);\n lines.push(` source : github:${entry.repo}@${entry.tag}`);\n lines.push(` github : https://github.com/${entry.repo}/tree/${entry.tag}`);\n lines.push(\n ` local : ${isInstalled ? c.green(`installed @ ${installedPath}`) : c.dim(\"not installed\")}`\n );\n\n if (!isInstalled) {\n lines.push(c.dim(`\\n install: sfmc mod install ${query}`));\n } else {\n lines.push(c.dim(`\\n details: sfmc mod info ${query}`));\n }\n return lines.join(\"\\n\") + \"\\n\";\n}\n\n/* \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n * info\n * \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\nexport async function cmdModuleInfo(args: string[]): Promise<string> {\n const id = args[0];\n if (!id) return c.yellow(t(\"mod.info.usage\"));\n const all = await scanInstalled();\n const m = all.find((x) => x.id === id);\n if (!m) return c.red(t(\"mod.notInstalledAt\", { id, path: path.join(modulesDir(), id) }));\n const lines: string[] = [c.bold(`\\n${id}`)];\n lines.push(` path : ${m.path}`);\n lines.push(` files : ${m.fileCount}`);\n lines.push(` size : ${fmtBytes(m.totalBytes)}`);\n lines.push(` fingerprint : ${m.fingerprint}`);\n if (m.manifest) {\n lines.push(` schemaVer : ${m.manifest.schemaVersion ?? \"(none)\"}`);\n lines.push(` routes : ${m.manifest.routes?.length ?? 0}`);\n if (m.manifest.routes?.length) {\n for (const r of m.manifest.routes) lines.push(c.dim(` ${r.method.padEnd(7)} ${r.path.padEnd(36)} ${r.handler}`));\n }\n lines.push(` migrations : ${m.manifest.migrations?.length ?? 0}`);\n if (m.manifest.migrations?.length) {\n for (const mg of m.manifest.migrations) lines.push(c.dim(` v${mg.version} ${mg.name}`));\n }\n if (m.manifest.notes) lines.push(` notes : ${c.dim(m.manifest.notes)}`);\n } else {\n lines.push(c.yellow(` manifest : (missing or unreadable)`));\n }\n return lines.join(\"\\n\") + \"\\n\";\n}\n\n/* \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n * verify\n * \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\nexport async function cmdModuleVerify(args: string[]): Promise<string> {\n const id = args[0];\n if (id) {\n const all = await scanInstalled();\n const m = all.find((x) => x.id === id);\n if (!m) return c.red(t(\"mod.notInstalled\", { id }));\n return c.green(t(\"mod.verifyOk\", { id, fp: m.fingerprint }));\n }\n const all = await scanInstalled();\n const lines = [c.bold(\"\\nVerifying installed modules\")];\n for (const m of all) {\n lines.push(` ${m.id.padEnd(28)} ${shortHash(m.fingerprint)}`);\n }\n if (all.length === 0) lines.push(c.dim(\" (none)\"));\n return lines.join(\"\\n\") + \"\\n\";\n}\n\n/* \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n * install \u2014 shells out to tools/fetch-module.mjs\n * \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n/* \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n * enable / disable \u2014 \u672C\u5730\u5199 module-lock.json\uFF1Bdb \u5728\u7EBF\u65F6 best-effort \u70ED\u540C\u6B65\n * \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\nfunction readDbConfig(): DBConfig {\n return (readJson<DBConfig>(configPath(ROOT, \"db_config.json\")) ?? {}) as DBConfig;\n}\n\nfunction moduleLockPath(): string {\n return modulePath(path.join(ROOT, \"modules\"), \"module-lock.json\");\n}\n\nfunction catalogPathOnDisk(): string {\n return modulePath(path.join(ROOT, \"modules\"), \"catalog.json\");\n}\n\n/** \u5DF2\u88C5\u5305 + catalog \u6295\u5F71 \u2192 \u542F\u505C\u5019\u9009\uFF08canDisable \u4E0E db \u540C\u6E90\uFF1A\u7701\u7565\u89C6\u4E3A\u53EF\u7981\u7528\uFF09\u3002 */\nfunction buildToggleCandidates(installed: InstalledModule[]): ToggleCandidate[] {\n const catalog = (readJson<Catalog>(catalogPathOnDisk()) ?? {}) as Catalog;\n const rows = Array.isArray(catalog.modules) ? catalog.modules : [];\n const byLogical = new Map<string, Record<string, unknown>>();\n for (const raw of rows) {\n if (!raw || typeof raw !== \"object\") continue;\n const id = String((raw as Record<string, unknown>).id || \"\").trim();\n if (id) byLogical.set(id, raw as Record<string, unknown>);\n }\n return installed.map((m) => {\n const logicalId = typeof m.manifest?.id === \"string\" && m.manifest.id ? m.manifest.id : m.id;\n const raw = byLogical.get(logicalId);\n const configKeyRaw = raw ? String(raw.configKey || raw.config_key || \"\").trim() : \"\";\n const canDisable = raw ? raw.canDisable !== false : true;\n const out: ToggleCandidate = { logicalId, folderId: m.id, canDisable };\n if (configKeyRaw) out.configKey = configKeyRaw;\n return out;\n });\n}\n\nfunction writeLocalModuleEnabled(logicalId: string, enabled: boolean): void {\n const lockPath = moduleLockPath();\n const lock =\n (readJson<ModuleLock>(lockPath) ?? {\n version: 1,\n modules: {},\n }) as ModuleLock;\n applyLockEnabled(lock, logicalId, enabled);\n writeJson(lockPath, lock);\n}\n\nasync function notifyDbToggle(logicalId: string, action: \"enable\" | \"disable\"): Promise<ToggleNotify> {\n const cfg = readDbConfig();\n const port = cfg.db_port ?? 3001;\n const token = cfg.http_auth || \"\";\n const url = `http://127.0.0.1:${port}/api/sfmc/modules/${encodeURIComponent(logicalId)}/${action}`;\n let res: Response;\n try {\n res = await fetch(url, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n ...(token ? { Authorization: `Bearer ${token}` } : {}),\n },\n });\n } catch (err) {\n return { ok: false, reason: \"unreachable\", detail: (err as Error).message };\n }\n const text = await res.text();\n let body: unknown;\n try {\n body = JSON.parse(text);\n } catch {\n body = text;\n }\n if (!res.ok) {\n const err = (body as { error?: string })?.error ?? `HTTP ${res.status}`;\n return { ok: false, reason: \"http\", detail: err };\n }\n if ((body as { success?: boolean })?.success === false) {\n return { ok: false, reason: \"http\", detail: text };\n }\n return { ok: true };\n}\n\nasync function cmdModuleToggle(query: string, action: \"enable\" | \"disable\"): Promise<CliResult> {\n const installed = await scanInstalled();\n const target = resolveToggleTarget(query, buildToggleCandidates(installed));\n if (!target) {\n return failResult(c.red(t(\"mod.notInstalled\", { id: query })));\n }\n if (action === \"disable\" && !target.canDisable) {\n return failResult(c.red(t(\"mod.cannotDisable\", { id: target.logicalId })));\n }\n\n const enabled = action === \"enable\";\n try {\n writeLocalModuleEnabled(target.logicalId, enabled);\n } catch (err) {\n return failResult(\n c.red(t(\"mod.toggleLockFailed\", { id: target.logicalId, message: (err as Error).message }))\n );\n }\n\n const notify = await notifyDbToggle(target.logicalId, action);\n const fin = finalizeToggle(true, notify);\n const label = action === \"enable\" ? t(\"mod.action.enabled\") : t(\"mod.action.disabled\");\n const head = c.green(t(\"mod.toggleOk\", { label, id: target.logicalId }));\n if (!fin.warnNotify) {\n return okResult(head);\n }\n const detail = notify.ok === false ? (notify.detail ?? notify.reason) : \"\";\n const warn = c.yellow(t(\"mod.toggleDbSkipped\", { detail }));\n return okResult(`${head}\\n${warn}`);\n}\n\nexport async function cmdModuleEnable(args: string[]): Promise<CliResult> {\n const id = args[0];\n if (!id) return failResult(c.yellow(t(\"mod.enable.usage\")));\n return cmdModuleToggle(id, \"enable\");\n}\n\nexport async function cmdModuleDisable(args: string[]): Promise<CliResult> {\n const id = args[0];\n if (!id) return failResult(c.yellow(t(\"mod.disable.usage\")));\n return cmdModuleToggle(id, \"disable\");\n}\n\n/* \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n * install \u2014 shells out to tools/fetch-module.mjs\n * \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n/**\n * \u9884\u68C0 --from \u53D6\u503C\u662F\u5426\u662F\u5408\u6CD5 scheme\uFF1A\n * - npm:@scope/name / npm:<name>\n * - local[:<path>] / local\n * - tgz:<path>\n * - zip:<path>\n * - dir:<abs path>\n * - github:<owner>/<repo>[@tag]\n * - \u88F8\u8DEF\u5F84\uFF1A\u5FC5\u987B\u5B58\u5728\u4E14\u4E3A\u76EE\u5F55\uFF08\u88F8\u6587\u4EF6\u5E94\u8F6C tgz:/zip:\uFF09\n * \u8FD4\u56DE null \u8868\u793A\u5408\u6CD5\uFF1B\u5426\u5219\u8FD4\u56DE\u7528\u6237\u53EF\u8BFB\u7684\u9519\u8BEF\u6587\u6848\u3002\n */\nfunction validateFromScheme(from: string): string | null {\n if (\n from === \"local\" ||\n from.startsWith(\"local:\") ||\n from.startsWith(\"dir:\") ||\n from.startsWith(\"npm:\") ||\n from.startsWith(\"tgz:\") ||\n from.startsWith(\"zip:\") ||\n from.startsWith(\"github:\")\n ) {\n return null;\n }\n if (existsSync(from)) {\n const st = lstatSync(from);\n if (st.isDirectory()) return null;\n return `--from \u88F8\u8DEF\u5F84\u987B\u4E3A\u76EE\u5F55\uFF08\u6587\u4EF6\u8BF7\u7528 --from local:<tgz|zip>\uFF09: ${from}`;\n }\n return t(\"mod.fromUnknown\", { value: from });\n}\n\nexport async function cmdModuleInstall(args: string[]): Promise<string> {\n // \u652F\u6301: install <id> [id2 ...] [--from ...] [--link] [--sha256 ...]\n const flags = parseFlags(args);\n const positional: string[] = [];\n for (let i = 0; i < args.length; i++) {\n if (args[i] === \"--from\" || args[i] === \"--sha256\") {\n i++;\n continue;\n }\n if (args[i]?.startsWith(\"--from=\") || args[i]?.startsWith(\"--sha256=\")) continue;\n if (args[i]?.startsWith(\"--\")) continue;\n positional.push(args[i]!);\n }\n if (positional.length === 0) {\n return c.yellow(t(\"mod.install.usage\"));\n }\n\n /* scheme \u9884\u68C0\uFF1A\u907F\u514D\u62FC\u5199\u9519\u8BEF\u5EF6\u8FDF\u5230\u5B50\u8FDB\u7A0B\u62A5\u9519 */\n if (flags.from) {\n const err = validateFromScheme(flags.from);\n if (err) return c.red(err);\n }\n\n const fetchScript = resolveFetchModule();\n if (!fetchScript) {\n return c.red(t(\"mod.fetchMissing\"));\n }\n const sub = [\"install\", ...positional];\n if (flags.from) sub.push(\"--from\", flags.from);\n if (flags.sha256) sub.push(\"--sha256\", flags.sha256);\n if (flags.link) sub.push(\"--link\");\n return new Promise<string>((resolve) => {\n const proc = spawn(process.execPath, [fetchScript, ...sub], {\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n env: { ...process.env, SFMC_ROOT: ROOT },\n });\n let out = \"\";\n proc.stdout?.on(\"data\", (d: Buffer) => {\n out += d.toString();\n });\n proc.stderr?.on(\"data\", (d: Buffer) => {\n out += d.toString();\n });\n proc.on(\"exit\", (code) => {\n resolve(out + (code === 0 ? \"\" : `\\n[exit ${code}]`));\n });\n proc.on(\"error\", (e) => resolve(c.red(`spawn failed: ${e.message}`)));\n });\n}\n\n/* \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n * uninstall\n * \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\nexport async function cmdModuleUninstall(args: string[]): Promise<string> {\n const id = args[0];\n if (!id) return c.yellow(t(\"mod.uninstall.usage\"));\n const fetchScript = resolveFetchModule();\n if (!fetchScript) {\n // \u56DE\u9000:\u4EC5\u5220\u76EE\u5F55(\u65E7\u884C\u4E3A)\n const target = path.join(modulesDir(), id);\n if (!existsSync(target)) return c.yellow(t(\"mod.notInstalledFolder\", { id, path: target }));\n await fs.rm(target, { recursive: true, force: true });\n return c.green(t(\"mod.removed\", { id, path: target }));\n }\n return new Promise<string>((resolve) => {\n const proc = spawn(process.execPath, [fetchScript, \"uninstall\", id], {\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n env: { ...process.env, SFMC_ROOT: ROOT },\n });\n let out = \"\";\n proc.stdout?.on(\"data\", (d: Buffer) => {\n out += d.toString();\n });\n proc.stderr?.on(\"data\", (d: Buffer) => {\n out += d.toString();\n });\n proc.on(\"exit\", (code) => {\n resolve(out + (code === 0 ? \"\" : `\\n[exit ${code}]`));\n });\n proc.on(\"error\", (e) => resolve(c.red(`spawn failed: ${e.message}`)));\n });\n}\n\n/* \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n * CLI flag parsing\n * \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\ninterface InstallFlags {\n from: string | null;\n sha256: string | null;\n link: boolean;\n}\n\nfunction parseFlags(args: string[]): InstallFlags {\n const flags: InstallFlags = { from: null, sha256: null, link: false };\n for (let i = 0; i < args.length; i++) {\n if (args[i] === \"--from\") flags.from = args[++i] ?? null;\n else if (args[i]?.startsWith(\"--from=\")) flags.from = args[i]!.slice(\"--from=\".length);\n else if (args[i] === \"--sha256\") flags.sha256 = args[++i] ?? null;\n else if (args[i]?.startsWith(\"--sha256=\")) flags.sha256 = args[i]!.slice(\"--sha256=\".length);\n else if (args[i] === \"--link\") flags.link = true;\n }\n return flags;\n}\n\n/**\n * \u7EDF\u4E00\u5206\u53D1 module/mod \u5B50\u547D\u4EE4 \u2014\u2014 CLI(`main.ts`)\u4E0E REPL(`repl.ts`)\u5171\u7528,\n * \u907F\u514D\u4E24\u5904 switch \u6F02\u79FB\u3002\n *\n * \u901A\u9053\u95E8\u7981\uFF08argv/repl\uFF09\u7531\u8C03\u7528\u65B9\u5728 dispatch \u524D\u7ECF command-surface \u5224\u5B9A\uFF1B\n * \u672C\u51FD\u6570\u53EA\u8D1F\u8D23\u5B50\u547D\u4EE4\u8DEF\u7531\u3002`remove` \u4F5C\u4E3A uninstall \u7684\u540C\u4E49\u522B\u540D\u4FDD\u7559\u3002\n *\n * \u4F5C\u8005\u5411 test/watch/publish \u5DF2\u8FC1\u81F3 VS Code \u6269\u5C55\u4E0E @sfmc-bds/devkit\u3002\n */\nexport async function dispatchModuleCommand(sub: string | undefined, args: string[]): Promise<string> {\n switch (sub) {\n case \"list\":\n return cmdModuleList(args);\n case \"search\":\n return cmdModuleSearch(args);\n case \"install\":\n return cmdModuleInstall(args);\n case \"uninstall\":\n case \"remove\":\n return cmdModuleUninstall(args);\n case \"verify\":\n return cmdModuleVerify(args);\n case \"info\":\n return cmdModuleInfo(args);\n case \"enable\":\n return (await cmdModuleEnable(args)).message;\n case \"disable\":\n return (await cmdModuleDisable(args)).message;\n case \"build\": {\n const { cmdModuleBuild } = await import(\"./module-pack-build.js\");\n return cmdModuleBuild(args);\n }\n case \"reload\": {\n const { cmdModuleReload } = await import(\"./module-pack-build.js\");\n return cmdModuleReload(args);\n }\n case \"test\":\n case \"watch\":\n case \"publish\":\n return c.yellow(\n `[mod ${sub}] \u5DF2\u79FB\u81F3 VS Code/Cursor \u6269\u5C55\u300CSFMC Module\u300D\u4E0E @sfmc-bds/devkit\uFF1B\u8FD0\u7EF4\u8BF7\u7528 mod build|reload|install\u3002`\n );\n default:\n return c.yellow(moduleUsage());\n }\n}\n\n/** \u540C\u6B65\u679A\u4E3E\u5DF2\u5B89\u88C5\u6A21\u5757 id,\u4F9B REPL Tab \u8865\u5168(\u4E0D\u8BFB fingerprint,\u5C3D\u91CF\u8F7B\u91CF)\u3002 */\nexport function listInstalledModuleIdsSync(): string[] {\n const dir = modulesDir();\n if (!existsSync(dir)) return [];\n try {\n return readdirSync(dir, { withFileTypes: true })\n .filter((e) => e.isDirectory())\n .map((e) => e.name)\n .sort((a, b) => a.localeCompare(b));\n } catch {\n return [];\n }\n}"],
5
+ "mappings": "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",
6
6
  "names": ["lines", "all"]
7
7
  }
@@ -1 +1 @@
1
- {"version":3,"file":"module-pack-build.d.ts","sourceRoot":"","sources":["../src/module-pack-build.ts"],"names":[],"mappings":"AA2YA;;;GAGG;AACH,wBAAsB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAwCrE;AAED;;GAEG;AACH,wBAAsB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAmDrE"}
1
+ {"version":3,"file":"module-pack-build.d.ts","sourceRoot":"","sources":["../src/module-pack-build.ts"],"names":[],"mappings":"AA+YA;;;GAGG;AACH,wBAAsB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAwCrE;AAED;;GAEG;AACH,wBAAsB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAmDrE"}
@@ -64,6 +64,10 @@ async function bundleBehaviorPackScript() {
64
64
  logLevel: "warning",
65
65
  sourcemap: false,
66
66
  external: ["@minecraft/*"],
67
+ // BDS host 启动:与 module-loader barrel 分离(DIP),须在模块 register 之前执行
68
+ banner: {
69
+ js: 'import { installHostBootstrap } from "@sfmc-bds/sdk/module-loader/install";\ninstallHostBootstrap();\n'
70
+ },
67
71
  tsconfigRaw: JSON.stringify({
68
72
  compilerOptions: {
69
73
  module: "ESNext",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/module-pack-build.ts"],
4
- "sourcesContent": ["/**\n * module-pack-build.ts \u2014 `mod build` / `mod reload` \u7684 spawn-based \u5B9E\u73B0\n *\n * CLI \u6D3E\u53D1\u7684 module build / reload \u5B50\u547D\u4EE4\u8D70\u8FD9\u91CC\uFF1Bpack-lifecycle.ts \u4FDD\u7559\n * ensurePacksReady \u542F\u52A8\u94A9\u5B50\u4E0E wizard \u5185\u90E8\u6D88\u8D39\u65B9\u7684 in-process \u5165\u53E3\u3002\n *\n * \u5B9E\u9645\u6587\u4EF6\u5199\u5165\uFF08assemble-bp / assemble-rp / deploy / enable-pack / disable-pack /\n * ensure-permission\uFF09\u901A\u8FC7 spawn bds-tools/cli-pack-manager.ts \u7684 verb \u6267\u884C\uFF1B\n * \u4E0E module install/uninstall\uFF08\u2192 tools/fetch-module.mjs\uFF09\u3001\u811A\u624B\u67B6\n * \uFF08\u2192 tools/new-module.mjs\uFF09\u4FDD\u6301\u540C\u4E00\u67B6\u6784\uFF1ACLI \u662F thin wrapper\uFF0C\u5DE5\u4F5C\u5728\u5916\u90E8\u5DE5\u5177\u3002\n *\n * \u552F\u4E00\u6743\u5A01\uFF1A\u672C\u6587\u4EF6 = `sfmc mod build|reload` \u7684\u6D3E\u53D1\u5165\u53E3\uFF1B\u5176\u4ED6\u6587\u4EF6\u4E0D\u5F97\u518D\n * \u76F4\u63A5 import pack-lifecycle \u7684 cmdPackBuild / deployPacks\uFF08\u786E\u4FDD\u53EA\u6709\u4E00\u4E2A spawn \u5165\u53E3\uFF09\u3002\n */\nimport { spawn } from \"node:child_process\";\nimport { existsSync, readFileSync } from \"node:fs\";\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport process from \"node:process\";\nimport { writeJson } from \"@sfmc-bds/sdk/node/config\";\nimport {\n BP_NAME,\n RP_NAME,\n DEPLOY_CATALOG_NAME,\n bpOut,\n bpSrc,\n rpOut,\n buildRoot,\n computeDesiredCatalog,\n readDeployedCatalog,\n catalogsEqual,\n resolveBdsContext,\n deployedBpDir,\n formatPackLoadInfo,\n scanLocalModules,\n type DeployCatalog,\n} from \"./pack-lifecycle.js\";\nimport { ROOT, resolveServiceScript } from \"./runtime.js\";\nimport { c } from \"./theme.js\";\nimport { t } from \"./i18n/index.js\";\nimport { pushLog } from \"./logs.js\";\n\ntype SpawnResult = { code: number | null; output: string };\n\n/** spawn bds-tools/cli-pack-manager.ts \u5B50\u8FDB\u7A0B\uFF1B\u6355\u83B7 stdout+stderr\u3002 */\nfunction spawnPackManager(args: string[]): Promise<SpawnResult> {\n return new Promise((resolve) => {\n const script = resolveServiceScript(\"pack-manager\");\n const proc = spawn(process.execPath, [script, ...args], {\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n env: { ...process.env, SFMC_ROOT: ROOT, SFMC_SERVICE: \"pack-manager\" },\n });\n let output = \"\";\n proc.stdout?.on(\"data\", (d: Buffer) => {\n output += d.toString();\n });\n proc.stderr?.on(\"data\", (d: Buffer) => {\n output += d.toString();\n });\n proc.on(\"exit\", (code) => resolve({ code, output }));\n proc.on(\"error\", (e) => resolve({ code: 1, output: `${output}${e.message}` }));\n });\n}\n\n/* esbuild bundle \u2014\u2014 JS bundler \u662F in-process \u5E93\uFF0C\u4E0D\u8D70 spawn\u3002 */\nasync function bundleBehaviorPackScript(): Promise<void> {\n const mods = await scanLocalModules();\n const entries = mods.filter((m) => m.enabled && m.entryPath).map((m) => m.entryPath!);\n const outFile = path.join(bpSrc(), \"scripts\", \"main.js\");\n await fs.mkdir(path.dirname(outFile), { recursive: true });\n\n if (entries.length === 0) {\n await fs.writeFile(outFile, \"/* no modules enabled */\\n\", \"utf8\");\n pushLog(\"no enabled SAPI modules \u2014 empty main.js\", \"pack\", \"warn\");\n return;\n }\n\n const { build } = await import(\"esbuild\");\n const sdkRoot = await resolveSdkRootForEsbuild();\n await build({\n entryPoints: entries,\n outfile: outFile,\n bundle: true,\n platform: \"neutral\",\n format: \"esm\",\n target: \"es2022\",\n logLevel: \"warning\",\n sourcemap: false,\n external: [\"@minecraft/*\"],\n tsconfigRaw: JSON.stringify({\n compilerOptions: {\n module: \"ESNext\",\n moduleResolution: \"bundler\",\n target: \"ES2022\",\n strict: true,\n skipLibCheck: true,\n },\n }),\n plugins: [createSdkResolvePlugin(sdkRoot)],\n });\n pushLog(`esbuild bundled ${entries.length} entr(y/ies)`, \"pack\", \"info\");\n}\n\nasync function resolveSdkRootForEsbuild(): Promise<string> {\n const { resolveSdkPackageRoot } = await import(\"./runtime.js\");\n return resolveSdkPackageRoot();\n}\n\n/** esbuild \u63D2\u4EF6\uFF1A\u89E3\u6790 @sfmc-bds/sdk \u7684 exports \u5B57\u6BB5\uFF08\u4E0E pack-lifecycle.ts \u5185\u90E8\u5B9E\u73B0\u540C\u6B65\uFF09\u3002 */\nfunction createSdkResolvePlugin(sdkRoot: string): import(\"esbuild\").Plugin {\n const pkg = JSON.parse(readFileSync(path.join(sdkRoot, \"package.json\"), \"utf8\")) as {\n exports?: Record<string, string | { import?: string; default?: string; types?: string }>;\n };\n const exportsMap = pkg.exports ?? {};\n\n function resolveExportSubpath(subpath: string): string | null {\n const key = subpath === \"\" ? \".\" : `./${subpath}`;\n const entry = exportsMap[key];\n if (!entry) return null;\n const rel = typeof entry === \"string\" ? entry : (entry.import ?? entry.default);\n if (!rel || typeof rel !== \"string\") return null;\n const abs = path.join(sdkRoot, rel);\n return existsSync(abs) ? abs : null;\n }\n\n return {\n name: \"sfmc-sdk-resolve\",\n setup(build) {\n build.onResolve({ filter: /^@sfmc(?:-bds)?\\/sdk(?:\\/|$)/ }, (args) => {\n const normalized = args.path.replace(/^@sfmc\\/sdk/, \"@sfmc-bds/sdk\");\n const sub = normalized === \"@sfmc-bds/sdk\" ? \"\" : normalized.slice(\"@sfmc-bds/sdk/\".length);\n const resolved = resolveExportSubpath(sub);\n if (!resolved) {\n return {\n errors: [\n {\n text: `Cannot resolve ${args.path} under SDK at ${sdkRoot} (export \"./${sub || \".\"}\" missing or file absent; run sdk:build?)`,\n },\n ],\n };\n }\n return { path: resolved };\n });\n },\n };\n}\n\n/** spawn assemble-bp verb\u3002 */\nasync function spawnAssembleBp(catalog: DeployCatalog): Promise<SpawnResult> {\n const args = [\n \"assemble-bp\",\n \"--src\",\n bpSrc(),\n \"--out\",\n bpOut(),\n \"--name\",\n BP_NAME,\n \"--uuid\",\n catalog.bpUuid,\n \"--version\",\n catalog.bpVersion.join(\",\"),\n ];\n if (catalog.bpModuleUuid) args.push(\"--module-uuid\", catalog.bpModuleUuid);\n const r = await spawnPackManager(args);\n if (r.code === 0) {\n pushLog(`assembled BP uuid=${catalog.bpUuid}`, \"pack\", \"info\");\n }\n return r;\n}\n\n/** spawn assemble-rp verb\uFF1B\u65E0 RP \u65F6\u6E05\u7406\u65E7\u4EA7\u7269\u3002 */\nasync function spawnAssembleRp(\n catalog: DeployCatalog,\n rpDirs: Record<string, string>\n): Promise<SpawnResult> {\n if (!catalog.rpUuid || Object.keys(rpDirs).length === 0) {\n await fs.rm(rpOut(), { recursive: true, force: true });\n pushLog(\"no enabled resource packs \u2014 RP skipped\", \"pack\", \"info\");\n return { code: 0, output: \"[pack-manager] no enabled resource packs \u2014 RP skipped\\n\" };\n }\n const mapFile = path.join(buildRoot(), \"rp-map.json\");\n await fs.mkdir(buildRoot(), { recursive: true });\n await fs.writeFile(mapFile, JSON.stringify(rpDirs), \"utf8\");\n const args = [\n \"assemble-rp\",\n \"--modules-json\",\n mapFile,\n \"--out\",\n rpOut(),\n \"--name\",\n RP_NAME,\n \"--uuid\",\n catalog.rpUuid,\n \"--version\",\n (catalog.rpVersion ?? [1, 0, 0]).join(\",\"),\n ];\n if (catalog.rpModuleUuid) args.push(\"--module-uuid\", catalog.rpModuleUuid);\n const r = await spawnPackManager(args);\n if (r.code === 0) {\n pushLog(\n `assembled RP uuid=${catalog.rpUuid} (${Object.keys(rpDirs).length} modules)`,\n \"pack\",\n \"info\"\n );\n }\n return r;\n}\n\n/** spawn deploy verb\uFF1B\u65E0 RP \u65F6\u5E26 --clear-rp\u3002 */\nasync function spawnDeploy(catalog: DeployCatalog): Promise<SpawnResult> {\n const { bdsRoot, levelName } = resolveBdsContext();\n const args = [\n \"deploy\",\n \"--bds-root\",\n bdsRoot,\n \"--level\",\n levelName,\n \"--bp-src\",\n bpOut(),\n \"--bp-name\",\n BP_NAME,\n \"--rp-name\",\n RP_NAME,\n ];\n if (catalog.rpUuid && existsSync(rpOut())) {\n args.push(\"--rp-src\", rpOut());\n } else {\n args.push(\"--clear-rp\");\n }\n const r = await spawnPackManager(args);\n if (r.code === 0) {\n pushLog(`deployed to worlds/${levelName}`, \"pack\", \"info\");\n }\n return r;\n}\n\n/** spawn enable-pack verb\uFF1ABP \u5FC5\u987B\uFF0CRP \u4EC5\u5728\u6709 UUID \u65F6\u3002 */\nasync function spawnEnablePacks(catalog: DeployCatalog): Promise<SpawnResult> {\n const { bdsRoot, levelName } = resolveBdsContext();\n const worldsDir = path.join(bdsRoot, \"worlds\");\n let output = \"\";\n const bpArgs = [\n \"enable-pack\",\n \"--worlds-dir\",\n worldsDir,\n \"--level\",\n levelName,\n \"--kind\",\n \"behavior\",\n \"--pack-id\",\n catalog.bpUuid,\n \"--version\",\n catalog.bpVersion.join(\",\"),\n ];\n const bpR = await spawnPackManager(bpArgs);\n output += bpR.output;\n if (bpR.code !== 0) return { code: bpR.code, output };\n pushLog(\n `enabled behavior pack ${catalog.bpUuid} in world list`,\n \"pack\",\n \"info\"\n );\n if (catalog.rpUuid && catalog.rpVersion) {\n const rpArgs = [\n \"enable-pack\",\n \"--worlds-dir\",\n worldsDir,\n \"--level\",\n levelName,\n \"--kind\",\n \"resource\",\n \"--pack-id\",\n catalog.rpUuid,\n \"--version\",\n catalog.rpVersion.join(\",\"),\n ];\n const rpR = await spawnPackManager(rpArgs);\n output += rpR.output;\n if (rpR.code !== 0) return { code: rpR.code, output };\n pushLog(\n `enabled resource pack ${catalog.rpUuid} in world list`,\n \"pack\",\n \"info\"\n );\n }\n return { code: 0, output };\n}\n\n/** spawn disable-pack verb\uFF1A\u6E05\u7406\u8FC7\u671F UUID\uFF08uuid \u8F6E\u6362 / \u4E0D\u518D\u63D0\u4F9B RP\uFF09\u3002 */\nasync function spawnDisableStale(\n current: DeployCatalog,\n bdsRoot: string,\n levelName: string\n): Promise<void> {\n const previous = await collectDeployedPackUuids(bdsRoot, levelName);\n const worldsDir = path.join(bdsRoot, \"worlds\");\n for (const staleRp of previous.rp) {\n if (staleRp === (current.rpUuid ?? null)) continue;\n const r = await spawnPackManager([\n \"disable-pack\",\n \"--worlds-dir\",\n worldsDir,\n \"--level\",\n levelName,\n \"--kind\",\n \"resource\",\n \"--pack-id\",\n staleRp,\n \"--version\",\n \"1,0,0\",\n ]);\n if (r.code === 0) {\n pushLog(`disabled stale resource pack ${staleRp}`, \"pack\", \"info\");\n } else {\n pushLog(\n `disable stale RP ${staleRp} failed: ${r.output.trim()}`,\n \"pack\",\n \"warn\"\n );\n }\n }\n for (const staleBp of previous.bp) {\n if (staleBp === current.bpUuid) continue;\n const r = await spawnPackManager([\n \"disable-pack\",\n \"--worlds-dir\",\n worldsDir,\n \"--level\",\n levelName,\n \"--kind\",\n \"behavior\",\n \"--pack-id\",\n staleBp,\n \"--version\",\n \"1,0,0\",\n ]);\n if (r.code === 0) {\n pushLog(`disabled stale behavior pack ${staleBp}`, \"pack\", \"info\");\n } else {\n pushLog(\n `disable stale BP ${staleBp} failed: ${r.output.trim()}`,\n \"pack\",\n \"warn\"\n );\n }\n }\n}\n\n/** \u901A\u8FC7 bds-tools \u7684 list-installed + read-manifest \u62FF\u5230 deployed UUID\uFF08spawn\uFF09\u3002 */\nasync function collectDeployedPackUuids(\n bdsRoot: string,\n levelName: string\n): Promise<{ bp: Set<string>; rp: Set<string> }> {\n const bp = new Set<string>();\n const rp = new Set<string>();\n const cat = readDeployedCatalog(bdsRoot, levelName);\n if (cat?.bpUuid) bp.add(cat.bpUuid);\n if (cat?.rpUuid) rp.add(cat.rpUuid);\n // \u901A\u8FC7 read-manifest \u770B\u4E16\u754C\u78C1\u76D8 BP/RP manifest \u7684 uuid\uFF0C\u4F5C\u4E3A catalog \u7F3A\u5931\u65F6\u7684\u515C\u5E95\u3002\n const bpDir = path.join(bdsRoot, \"worlds\", levelName, \"behavior_packs\", BP_NAME);\n const rpDir = path.join(bdsRoot, \"worlds\", levelName, \"resource_packs\", RP_NAME);\n const bpR = await spawnPackManager([\"read-manifest\", \"--pack-dir\", bpDir]);\n if (bpR.code === 0) {\n try {\n const j = JSON.parse(bpR.output.trim()) as { uuid?: string } | null;\n if (j?.uuid) bp.add(j.uuid);\n } catch {\n /* ignore */\n }\n }\n const rpR = await spawnPackManager([\"read-manifest\", \"--pack-dir\", rpDir]);\n if (rpR.code === 0) {\n try {\n const j = JSON.parse(rpR.output.trim()) as { uuid?: string } | null;\n if (j?.uuid) rp.add(j.uuid);\n } catch {\n /* ignore */\n }\n }\n return { bp, rp };\n}\n\n/** spawn ensure-permission verb\u3002 */\nasync function spawnEnsurePermission(catalog: DeployCatalog): Promise<SpawnResult> {\n const { bdsRoot } = resolveBdsContext();\n const r = await spawnPackManager([\n \"ensure-permission\",\n \"--bds-root\",\n bdsRoot,\n \"--pack-id\",\n catalog.bpUuid,\n ]);\n return r;\n}\n\n/**\n * `sfmc mod build` \u2014\u2014 \u7EC4\u88C5 BP + RP\uFF08\u4E0D\u90E8\u7F72\uFF09\u3002\n * \u4EC5\u5F53 catalog \u4E0E\u4E16\u754C\u5185\u5DF2\u90E8\u7F72\u4E0D\u4E00\u81F4\u65F6\u6267\u884C\uFF1B\u5426\u5219\u76F4\u63A5\u6253\"\u5DF2\u540C\u6B65\"\u3002\n */\nexport async function cmdModuleBuild(_args: string[]): Promise<string> {\n try {\n const { bdsRoot, levelName } = resolveBdsContext();\n const deployed = readDeployedCatalog(bdsRoot, levelName);\n const desired = await computeDesiredCatalog(deployed ? reusePackIds(deployed) : undefined);\n\n if (deployed && catalogsEqual(desired, deployed)) {\n return formatPackLoadInfo(desired, false);\n }\n\n pushLog(\n `building BP/RP (modules=${Object.keys(desired.modules).length})\u2026`,\n \"pack\",\n \"info\"\n );\n await bundleBehaviorPackScript();\n\n const mods = await scanLocalModules();\n const rpDirs: Record<string, string> = {};\n for (const m of mods) {\n if (!m.enabled || !m.hasResourcePack) continue;\n rpDirs[m.folderId] = path.join(\"modules\", \"packages\", m.folderId, \"resource_pack\");\n }\n\n const bpR = await spawnAssembleBp(desired);\n if (bpR.code !== 0) return c.red(bpR.output.trim() || `assemble-bp exit ${bpR.code}`);\n const rpR = await spawnAssembleRp(desired, rpDirs);\n if (rpR.code !== 0) return c.red(rpR.output.trim() || `assemble-rp exit ${rpR.code}`);\n\n desired.generatedAt = Date.now();\n if (Object.keys(rpDirs).length === 0) {\n desired.rpUuid = null;\n desired.rpVersion = null;\n }\n writeJson(path.join(bpOut(), DEPLOY_CATALOG_NAME), desired);\n\n return c.green(t(\"pack.built\", { path: bpOut() })) + \"\\n\" + formatPackLoadInfo(desired, true);\n } catch (e) {\n return c.red((e as Error).message);\n }\n}\n\n/**\n * `sfmc mod reload [--build-only]` \u2014\u2014 \u7EC4\u88C5 + \u90E8\u7F72 + \u6E05\u7406\u8FC7\u671F + \u5199\u6743\u9650 + \uFF08\u9ED8\u8BA4\uFF09\u53D1 reload \u5230 BDS\u3002\n */\nexport async function cmdModuleReload(args: string[]): Promise<string> {\n const buildOnly = args.includes(\"--build-only\");\n const parts: string[] = [];\n\n const buildMsg = await cmdModuleBuild([]);\n parts.push(buildMsg.trimEnd());\n if (buildMsg.startsWith(c.red(\"\"))) return parts.join(\"\\n\") + \"\\n\";\n\n try {\n const { bdsRoot, levelName } = resolveBdsContext();\n const desired = await computeDesiredCatalog();\n\n const depR = await spawnDeploy(desired);\n if (depR.code !== 0) {\n return parts.join(\"\\n\") + \"\\n\" + c.red(depR.output.trim() || `deploy exit ${depR.code}`);\n }\n parts.push(depR.output.trimEnd());\n\n writeJson(path.join(deployedBpDir(bdsRoot, levelName), DEPLOY_CATALOG_NAME), desired);\n\n await spawnDisableStale(desired, bdsRoot, levelName);\n\n const enR = await spawnEnablePacks(desired);\n if (enR.code !== 0) {\n return parts.join(\"\\n\") + \"\\n\" + c.red(enR.output.trim() || `enable-pack exit ${enR.code}`);\n }\n parts.push(enR.output.trimEnd());\n\n const perR = await spawnEnsurePermission(desired);\n if (perR.code !== 0) {\n return parts.join(\"\\n\") + \"\\n\" + c.red(perR.output.trim() || `ensure-permission exit ${perR.code}`);\n }\n parts.push(perR.output.trimEnd());\n } catch (e) {\n return parts.join(\"\\n\") + \"\\n\" + c.red((e as Error).message);\n }\n\n if (buildOnly) {\n parts.push(c.dim(t(\"reload.buildOnly\")));\n return parts.join(\"\\n\") + \"\\n\";\n }\n\n const { isServiceRunning } = await import(\"./services.js\");\n if (!(await isServiceRunning(\"bds\"))) {\n parts.push(c.yellow(t(\"reload.bdsNotRunning\")));\n return parts.join(\"\\n\") + \"\\n\";\n }\n const { cmdSend } = await import(\"./commands.js\");\n parts.push((await cmdSend(\"bds\", \"reload\")).trimEnd());\n parts.push(c.green(t(\"reload.sent\")));\n return parts.join(\"\\n\") + \"\\n\";\n}\n\nfunction reusePackIds(\n deployed: DeployCatalog\n): Parameters<typeof computeDesiredCatalog>[0] {\n return {\n bpUuid: deployed.bpUuid,\n rpUuid: deployed.rpUuid,\n bpVersion: deployed.bpVersion,\n rpVersion: deployed.rpVersion,\n ...(deployed.bpModuleUuid ? { bpModuleUuid: deployed.bpModuleUuid } : {}),\n ...(deployed.rpModuleUuid ? { rpModuleUuid: deployed.rpModuleUuid } : {}),\n };\n}"],
5
- "mappings": "AAcA,SAAS,aAAa;AACtB,SAAS,YAAY,oBAAoB;AACzC,OAAO,QAAQ;AACf,OAAO,UAAU;AACjB,OAAO,aAAa;AACpB,SAAS,iBAAiB;AAC1B;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAEK;AACP,SAAS,MAAM,4BAA4B;AAC3C,SAAS,SAAS;AAClB,SAAS,SAAS;AAClB,SAAS,eAAe;AAKxB,SAAS,iBAAiB,MAAsC;AAC9D,SAAO,IAAI,QAAQ,CAAC,YAAY;AAC9B,UAAM,SAAS,qBAAqB,cAAc;AAClD,UAAM,OAAO,MAAM,QAAQ,UAAU,CAAC,QAAQ,GAAG,IAAI,GAAG;AAAA,MACtD,OAAO,CAAC,UAAU,QAAQ,MAAM;AAAA,MAChC,KAAK,EAAE,GAAG,QAAQ,KAAK,WAAW,MAAM,cAAc,eAAe;AAAA,IACvE,CAAC;AACD,QAAI,SAAS;AACb,SAAK,QAAQ,GAAG,QAAQ,CAAC,MAAc;AACrC,gBAAU,EAAE,SAAS;AAAA,IACvB,CAAC;AACD,SAAK,QAAQ,GAAG,QAAQ,CAAC,MAAc;AACrC,gBAAU,EAAE,SAAS;AAAA,IACvB,CAAC;AACD,SAAK,GAAG,QAAQ,CAAC,SAAS,QAAQ,EAAE,MAAM,OAAO,CAAC,CAAC;AACnD,SAAK,GAAG,SAAS,CAAC,MAAM,QAAQ,EAAE,MAAM,GAAG,QAAQ,GAAG,MAAM,GAAG,EAAE,OAAO,GAAG,CAAC,CAAC;AAAA,EAC/E,CAAC;AACH;AAGA,eAAe,2BAA0C;AACvD,QAAM,OAAO,MAAM,iBAAiB;AACpC,QAAM,UAAU,KAAK,OAAO,CAAC,MAAM,EAAE,WAAW,EAAE,SAAS,EAAE,IAAI,CAAC,MAAM,EAAE,SAAU;AACpF,QAAM,UAAU,KAAK,KAAK,MAAM,GAAG,WAAW,SAAS;AACvD,QAAM,GAAG,MAAM,KAAK,QAAQ,OAAO,GAAG,EAAE,WAAW,KAAK,CAAC;AAEzD,MAAI,QAAQ,WAAW,GAAG;AACxB,UAAM,GAAG,UAAU,SAAS,8BAA8B,MAAM;AAChE,YAAQ,gDAA2C,QAAQ,MAAM;AACjE;AAAA,EACF;AAEA,QAAM,EAAE,MAAM,IAAI,MAAM,OAAO,SAAS;AACxC,QAAM,UAAU,MAAM,yBAAyB;AAC/C,QAAM,MAAM;AAAA,IACV,aAAa;AAAA,IACb,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,WAAW;AAAA,IACX,UAAU,CAAC,cAAc;AAAA,IACzB,aAAa,KAAK,UAAU;AAAA,MAC1B,iBAAiB;AAAA,QACf,QAAQ;AAAA,QACR,kBAAkB;AAAA,QAClB,QAAQ;AAAA,QACR,QAAQ;AAAA,QACR,cAAc;AAAA,MAChB;AAAA,IACF,CAAC;AAAA,IACD,SAAS,CAAC,uBAAuB,OAAO,CAAC;AAAA,EAC3C,CAAC;AACD,UAAQ,mBAAmB,QAAQ,MAAM,gBAAgB,QAAQ,MAAM;AACzE;AAEA,eAAe,2BAA4C;AACzD,QAAM,EAAE,sBAAsB,IAAI,MAAM,OAAO,cAAc;AAC7D,SAAO,sBAAsB;AAC/B;AAGA,SAAS,uBAAuB,SAA2C;AACzE,QAAM,MAAM,KAAK,MAAM,aAAa,KAAK,KAAK,SAAS,cAAc,GAAG,MAAM,CAAC;AAG/E,QAAM,aAAa,IAAI,WAAW,CAAC;AAEnC,WAAS,qBAAqB,SAAgC;AAC5D,UAAM,MAAM,YAAY,KAAK,MAAM,KAAK,OAAO;AAC/C,UAAM,QAAQ,WAAW,GAAG;AAC5B,QAAI,CAAC,MAAO,QAAO;AACnB,UAAM,MAAM,OAAO,UAAU,WAAW,QAAS,MAAM,UAAU,MAAM;AACvE,QAAI,CAAC,OAAO,OAAO,QAAQ,SAAU,QAAO;AAC5C,UAAM,MAAM,KAAK,KAAK,SAAS,GAAG;AAClC,WAAO,WAAW,GAAG,IAAI,MAAM;AAAA,EACjC;AAEA,SAAO;AAAA,IACL,MAAM;AAAA,IACN,MAAM,OAAO;AACX,YAAM,UAAU,EAAE,QAAQ,+BAA+B,GAAG,CAAC,SAAS;AACpE,cAAM,aAAa,KAAK,KAAK,QAAQ,eAAe,eAAe;AACnE,cAAM,MAAM,eAAe,kBAAkB,KAAK,WAAW,MAAM,iBAAiB,MAAM;AAC1F,cAAM,WAAW,qBAAqB,GAAG;AACzC,YAAI,CAAC,UAAU;AACb,iBAAO;AAAA,YACL,QAAQ;AAAA,cACN;AAAA,gBACE,MAAM,kBAAkB,KAAK,IAAI,iBAAiB,OAAO,eAAe,OAAO,GAAG;AAAA,cACpF;AAAA,YACF;AAAA,UACF;AAAA,QACF;AACA,eAAO,EAAE,MAAM,SAAS;AAAA,MAC1B,CAAC;AAAA,IACH;AAAA,EACF;AACF;AAGA,eAAe,gBAAgB,SAA8C;AAC3E,QAAM,OAAO;AAAA,IACX;AAAA,IACA;AAAA,IACA,MAAM;AAAA,IACN;AAAA,IACA,MAAM;AAAA,IACN;AAAA,IACA;AAAA,IACA;AAAA,IACA,QAAQ;AAAA,IACR;AAAA,IACA,QAAQ,UAAU,KAAK,GAAG;AAAA,EAC5B;AACA,MAAI,QAAQ,aAAc,MAAK,KAAK,iBAAiB,QAAQ,YAAY;AACzE,QAAM,IAAI,MAAM,iBAAiB,IAAI;AACrC,MAAI,EAAE,SAAS,GAAG;AAChB,YAAQ,qBAAqB,QAAQ,MAAM,IAAI,QAAQ,MAAM;AAAA,EAC/D;AACA,SAAO;AACT;AAGA,eAAe,gBACb,SACA,QACsB;AACtB,MAAI,CAAC,QAAQ,UAAU,OAAO,KAAK,MAAM,EAAE,WAAW,GAAG;AACvD,UAAM,GAAG,GAAG,MAAM,GAAG,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AACrD,YAAQ,+CAA0C,QAAQ,MAAM;AAChE,WAAO,EAAE,MAAM,GAAG,QAAQ,+DAA0D;AAAA,EACtF;AACA,QAAM,UAAU,KAAK,KAAK,UAAU,GAAG,aAAa;AACpD,QAAM,GAAG,MAAM,UAAU,GAAG,EAAE,WAAW,KAAK,CAAC;AAC/C,QAAM,GAAG,UAAU,SAAS,KAAK,UAAU,MAAM,GAAG,MAAM;AAC1D,QAAM,OAAO;AAAA,IACX;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,MAAM;AAAA,IACN;AAAA,IACA;AAAA,IACA;AAAA,IACA,QAAQ;AAAA,IACR;AAAA,KACC,QAAQ,aAAa,CAAC,GAAG,GAAG,CAAC,GAAG,KAAK,GAAG;AAAA,EAC3C;AACA,MAAI,QAAQ,aAAc,MAAK,KAAK,iBAAiB,QAAQ,YAAY;AACzE,QAAM,IAAI,MAAM,iBAAiB,IAAI;AACrC,MAAI,EAAE,SAAS,GAAG;AAChB;AAAA,MACE,qBAAqB,QAAQ,MAAM,KAAK,OAAO,KAAK,MAAM,EAAE,MAAM;AAAA,MAClE;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAGA,eAAe,YAAY,SAA8C;AACvE,QAAM,EAAE,SAAS,UAAU,IAAI,kBAAkB;AACjD,QAAM,OAAO;AAAA,IACX;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,MAAM;AAAA,IACN;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACA,MAAI,QAAQ,UAAU,WAAW,MAAM,CAAC,GAAG;AACzC,SAAK,KAAK,YAAY,MAAM,CAAC;AAAA,EAC/B,OAAO;AACL,SAAK,KAAK,YAAY;AAAA,EACxB;AACA,QAAM,IAAI,MAAM,iBAAiB,IAAI;AACrC,MAAI,EAAE,SAAS,GAAG;AAChB,YAAQ,sBAAsB,SAAS,IAAI,QAAQ,MAAM;AAAA,EAC3D;AACA,SAAO;AACT;AAGA,eAAe,iBAAiB,SAA8C;AAC5E,QAAM,EAAE,SAAS,UAAU,IAAI,kBAAkB;AACjD,QAAM,YAAY,KAAK,KAAK,SAAS,QAAQ;AAC7C,MAAI,SAAS;AACb,QAAM,SAAS;AAAA,IACb;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,QAAQ;AAAA,IACR;AAAA,IACA,QAAQ,UAAU,KAAK,GAAG;AAAA,EAC5B;AACA,QAAM,MAAM,MAAM,iBAAiB,MAAM;AACzC,YAAU,IAAI;AACd,MAAI,IAAI,SAAS,EAAG,QAAO,EAAE,MAAM,IAAI,MAAM,OAAO;AACpD;AAAA,IACE,yBAAyB,QAAQ,MAAM;AAAA,IACvC;AAAA,IACA;AAAA,EACF;AACA,MAAI,QAAQ,UAAU,QAAQ,WAAW;AACvC,UAAM,SAAS;AAAA,MACb;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,QAAQ;AAAA,MACR;AAAA,MACA,QAAQ,UAAU,KAAK,GAAG;AAAA,IAC5B;AACA,UAAM,MAAM,MAAM,iBAAiB,MAAM;AACzC,cAAU,IAAI;AACd,QAAI,IAAI,SAAS,EAAG,QAAO,EAAE,MAAM,IAAI,MAAM,OAAO;AACpD;AAAA,MACE,yBAAyB,QAAQ,MAAM;AAAA,MACvC;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACA,SAAO,EAAE,MAAM,GAAG,OAAO;AAC3B;AAGA,eAAe,kBACb,SACA,SACA,WACe;AACf,QAAM,WAAW,MAAM,yBAAyB,SAAS,SAAS;AAClE,QAAM,YAAY,KAAK,KAAK,SAAS,QAAQ;AAC7C,aAAW,WAAW,SAAS,IAAI;AACjC,QAAI,aAAa,QAAQ,UAAU,MAAO;AAC1C,UAAM,IAAI,MAAM,iBAAiB;AAAA,MAC/B;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AACD,QAAI,EAAE,SAAS,GAAG;AAChB,cAAQ,gCAAgC,OAAO,IAAI,QAAQ,MAAM;AAAA,IACnE,OAAO;AACL;AAAA,QACE,oBAAoB,OAAO,YAAY,EAAE,OAAO,KAAK,CAAC;AAAA,QACtD;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACA,aAAW,WAAW,SAAS,IAAI;AACjC,QAAI,YAAY,QAAQ,OAAQ;AAChC,UAAM,IAAI,MAAM,iBAAiB;AAAA,MAC/B;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AACD,QAAI,EAAE,SAAS,GAAG;AAChB,cAAQ,gCAAgC,OAAO,IAAI,QAAQ,MAAM;AAAA,IACnE,OAAO;AACL;AAAA,QACE,oBAAoB,OAAO,YAAY,EAAE,OAAO,KAAK,CAAC;AAAA,QACtD;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAGA,eAAe,yBACb,SACA,WAC+C;AAC/C,QAAM,KAAK,oBAAI,IAAY;AAC3B,QAAM,KAAK,oBAAI,IAAY;AAC3B,QAAM,MAAM,oBAAoB,SAAS,SAAS;AAClD,MAAI,KAAK,OAAQ,IAAG,IAAI,IAAI,MAAM;AAClC,MAAI,KAAK,OAAQ,IAAG,IAAI,IAAI,MAAM;AAElC,QAAM,QAAQ,KAAK,KAAK,SAAS,UAAU,WAAW,kBAAkB,OAAO;AAC/E,QAAM,QAAQ,KAAK,KAAK,SAAS,UAAU,WAAW,kBAAkB,OAAO;AAC/E,QAAM,MAAM,MAAM,iBAAiB,CAAC,iBAAiB,cAAc,KAAK,CAAC;AACzE,MAAI,IAAI,SAAS,GAAG;AAClB,QAAI;AACF,YAAM,IAAI,KAAK,MAAM,IAAI,OAAO,KAAK,CAAC;AACtC,UAAI,GAAG,KAAM,IAAG,IAAI,EAAE,IAAI;AAAA,IAC5B,QAAQ;AAAA,IAER;AAAA,EACF;AACA,QAAM,MAAM,MAAM,iBAAiB,CAAC,iBAAiB,cAAc,KAAK,CAAC;AACzE,MAAI,IAAI,SAAS,GAAG;AAClB,QAAI;AACF,YAAM,IAAI,KAAK,MAAM,IAAI,OAAO,KAAK,CAAC;AACtC,UAAI,GAAG,KAAM,IAAG,IAAI,EAAE,IAAI;AAAA,IAC5B,QAAQ;AAAA,IAER;AAAA,EACF;AACA,SAAO,EAAE,IAAI,GAAG;AAClB;AAGA,eAAe,sBAAsB,SAA8C;AACjF,QAAM,EAAE,QAAQ,IAAI,kBAAkB;AACtC,QAAM,IAAI,MAAM,iBAAiB;AAAA,IAC/B;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,QAAQ;AAAA,EACV,CAAC;AACD,SAAO;AACT;AAMA,eAAsB,eAAe,OAAkC;AACrE,MAAI;AACF,UAAM,EAAE,SAAS,UAAU,IAAI,kBAAkB;AACjD,UAAM,WAAW,oBAAoB,SAAS,SAAS;AACvD,UAAM,UAAU,MAAM,sBAAsB,WAAW,aAAa,QAAQ,IAAI,MAAS;AAEzF,QAAI,YAAY,cAAc,SAAS,QAAQ,GAAG;AAChD,aAAO,mBAAmB,SAAS,KAAK;AAAA,IAC1C;AAEA;AAAA,MACE,2BAA2B,OAAO,KAAK,QAAQ,OAAO,EAAE,MAAM;AAAA,MAC9D;AAAA,MACA;AAAA,IACF;AACA,UAAM,yBAAyB;AAE/B,UAAM,OAAO,MAAM,iBAAiB;AACpC,UAAM,SAAiC,CAAC;AACxC,eAAW,KAAK,MAAM;AACpB,UAAI,CAAC,EAAE,WAAW,CAAC,EAAE,gBAAiB;AACtC,aAAO,EAAE,QAAQ,IAAI,KAAK,KAAK,WAAW,YAAY,EAAE,UAAU,eAAe;AAAA,IACnF;AAEA,UAAM,MAAM,MAAM,gBAAgB,OAAO;AACzC,QAAI,IAAI,SAAS,EAAG,QAAO,EAAE,IAAI,IAAI,OAAO,KAAK,KAAK,oBAAoB,IAAI,IAAI,EAAE;AACpF,UAAM,MAAM,MAAM,gBAAgB,SAAS,MAAM;AACjD,QAAI,IAAI,SAAS,EAAG,QAAO,EAAE,IAAI,IAAI,OAAO,KAAK,KAAK,oBAAoB,IAAI,IAAI,EAAE;AAEpF,YAAQ,cAAc,KAAK,IAAI;AAC/B,QAAI,OAAO,KAAK,MAAM,EAAE,WAAW,GAAG;AACpC,cAAQ,SAAS;AACjB,cAAQ,YAAY;AAAA,IACtB;AACA,cAAU,KAAK,KAAK,MAAM,GAAG,mBAAmB,GAAG,OAAO;AAE1D,WAAO,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,MAAM,EAAE,CAAC,CAAC,IAAI,OAAO,mBAAmB,SAAS,IAAI;AAAA,EAC9F,SAAS,GAAG;AACV,WAAO,EAAE,IAAK,EAAY,OAAO;AAAA,EACnC;AACF;AAKA,eAAsB,gBAAgB,MAAiC;AACrE,QAAM,YAAY,KAAK,SAAS,cAAc;AAC9C,QAAM,QAAkB,CAAC;AAEzB,QAAM,WAAW,MAAM,eAAe,CAAC,CAAC;AACxC,QAAM,KAAK,SAAS,QAAQ,CAAC;AAC7B,MAAI,SAAS,WAAW,EAAE,IAAI,EAAE,CAAC,EAAG,QAAO,MAAM,KAAK,IAAI,IAAI;AAE9D,MAAI;AACF,UAAM,EAAE,SAAS,UAAU,IAAI,kBAAkB;AACjD,UAAM,UAAU,MAAM,sBAAsB;AAE5C,UAAM,OAAO,MAAM,YAAY,OAAO;AACtC,QAAI,KAAK,SAAS,GAAG;AACnB,aAAO,MAAM,KAAK,IAAI,IAAI,OAAO,EAAE,IAAI,KAAK,OAAO,KAAK,KAAK,eAAe,KAAK,IAAI,EAAE;AAAA,IACzF;AACA,UAAM,KAAK,KAAK,OAAO,QAAQ,CAAC;AAEhC,cAAU,KAAK,KAAK,cAAc,SAAS,SAAS,GAAG,mBAAmB,GAAG,OAAO;AAEpF,UAAM,kBAAkB,SAAS,SAAS,SAAS;AAEnD,UAAM,MAAM,MAAM,iBAAiB,OAAO;AAC1C,QAAI,IAAI,SAAS,GAAG;AAClB,aAAO,MAAM,KAAK,IAAI,IAAI,OAAO,EAAE,IAAI,IAAI,OAAO,KAAK,KAAK,oBAAoB,IAAI,IAAI,EAAE;AAAA,IAC5F;AACA,UAAM,KAAK,IAAI,OAAO,QAAQ,CAAC;AAE/B,UAAM,OAAO,MAAM,sBAAsB,OAAO;AAChD,QAAI,KAAK,SAAS,GAAG;AACnB,aAAO,MAAM,KAAK,IAAI,IAAI,OAAO,EAAE,IAAI,KAAK,OAAO,KAAK,KAAK,0BAA0B,KAAK,IAAI,EAAE;AAAA,IACpG;AACA,UAAM,KAAK,KAAK,OAAO,QAAQ,CAAC;AAAA,EAClC,SAAS,GAAG;AACV,WAAO,MAAM,KAAK,IAAI,IAAI,OAAO,EAAE,IAAK,EAAY,OAAO;AAAA,EAC7D;AAEA,MAAI,WAAW;AACb,UAAM,KAAK,EAAE,IAAI,EAAE,kBAAkB,CAAC,CAAC;AACvC,WAAO,MAAM,KAAK,IAAI,IAAI;AAAA,EAC5B;AAEA,QAAM,EAAE,iBAAiB,IAAI,MAAM,OAAO,eAAe;AACzD,MAAI,CAAE,MAAM,iBAAiB,KAAK,GAAI;AACpC,UAAM,KAAK,EAAE,OAAO,EAAE,sBAAsB,CAAC,CAAC;AAC9C,WAAO,MAAM,KAAK,IAAI,IAAI;AAAA,EAC5B;AACA,QAAM,EAAE,QAAQ,IAAI,MAAM,OAAO,eAAe;AAChD,QAAM,MAAM,MAAM,QAAQ,OAAO,QAAQ,GAAG,QAAQ,CAAC;AACrD,QAAM,KAAK,EAAE,MAAM,EAAE,aAAa,CAAC,CAAC;AACpC,SAAO,MAAM,KAAK,IAAI,IAAI;AAC5B;AAEA,SAAS,aACP,UAC6C;AAC7C,SAAO;AAAA,IACL,QAAQ,SAAS;AAAA,IACjB,QAAQ,SAAS;AAAA,IACjB,WAAW,SAAS;AAAA,IACpB,WAAW,SAAS;AAAA,IACpB,GAAI,SAAS,eAAe,EAAE,cAAc,SAAS,aAAa,IAAI,CAAC;AAAA,IACvE,GAAI,SAAS,eAAe,EAAE,cAAc,SAAS,aAAa,IAAI,CAAC;AAAA,EACzE;AACF;",
4
+ "sourcesContent": ["/**\n * module-pack-build.ts \u2014 `mod build` / `mod reload` \u7684 spawn-based \u5B9E\u73B0\n *\n * CLI \u6D3E\u53D1\u7684 module build / reload \u5B50\u547D\u4EE4\u8D70\u8FD9\u91CC\uFF1Bpack-lifecycle.ts \u4FDD\u7559\n * ensurePacksReady \u542F\u52A8\u94A9\u5B50\u4E0E wizard \u5185\u90E8\u6D88\u8D39\u65B9\u7684 in-process \u5165\u53E3\u3002\n *\n * \u5B9E\u9645\u6587\u4EF6\u5199\u5165\uFF08assemble-bp / assemble-rp / deploy / enable-pack / disable-pack /\n * ensure-permission\uFF09\u901A\u8FC7 spawn bds-tools/cli-pack-manager.ts \u7684 verb \u6267\u884C\uFF1B\n * \u4E0E module install/uninstall\uFF08\u2192 tools/fetch-module.mjs\uFF09\u3001\u811A\u624B\u67B6\n * \uFF08\u2192 tools/new-module.mjs\uFF09\u4FDD\u6301\u540C\u4E00\u67B6\u6784\uFF1ACLI \u662F thin wrapper\uFF0C\u5DE5\u4F5C\u5728\u5916\u90E8\u5DE5\u5177\u3002\n *\n * \u552F\u4E00\u6743\u5A01\uFF1A\u672C\u6587\u4EF6 = `sfmc mod build|reload` \u7684\u6D3E\u53D1\u5165\u53E3\uFF1B\u5176\u4ED6\u6587\u4EF6\u4E0D\u5F97\u518D\n * \u76F4\u63A5 import pack-lifecycle \u7684 cmdPackBuild / deployPacks\uFF08\u786E\u4FDD\u53EA\u6709\u4E00\u4E2A spawn \u5165\u53E3\uFF09\u3002\n */\nimport { spawn } from \"node:child_process\";\nimport { existsSync, readFileSync } from \"node:fs\";\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport process from \"node:process\";\nimport { writeJson } from \"@sfmc-bds/sdk/node/config\";\nimport {\n BP_NAME,\n RP_NAME,\n DEPLOY_CATALOG_NAME,\n bpOut,\n bpSrc,\n rpOut,\n buildRoot,\n computeDesiredCatalog,\n readDeployedCatalog,\n catalogsEqual,\n resolveBdsContext,\n deployedBpDir,\n formatPackLoadInfo,\n scanLocalModules,\n type DeployCatalog,\n} from \"./pack-lifecycle.js\";\nimport { ROOT, resolveServiceScript } from \"./runtime.js\";\nimport { c } from \"./theme.js\";\nimport { t } from \"./i18n/index.js\";\nimport { pushLog } from \"./logs.js\";\n\ntype SpawnResult = { code: number | null; output: string };\n\n/** spawn bds-tools/cli-pack-manager.ts \u5B50\u8FDB\u7A0B\uFF1B\u6355\u83B7 stdout+stderr\u3002 */\nfunction spawnPackManager(args: string[]): Promise<SpawnResult> {\n return new Promise((resolve) => {\n const script = resolveServiceScript(\"pack-manager\");\n const proc = spawn(process.execPath, [script, ...args], {\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n env: { ...process.env, SFMC_ROOT: ROOT, SFMC_SERVICE: \"pack-manager\" },\n });\n let output = \"\";\n proc.stdout?.on(\"data\", (d: Buffer) => {\n output += d.toString();\n });\n proc.stderr?.on(\"data\", (d: Buffer) => {\n output += d.toString();\n });\n proc.on(\"exit\", (code) => resolve({ code, output }));\n proc.on(\"error\", (e) => resolve({ code: 1, output: `${output}${e.message}` }));\n });\n}\n\n/* esbuild bundle \u2014\u2014 JS bundler \u662F in-process \u5E93\uFF0C\u4E0D\u8D70 spawn\u3002 */\nasync function bundleBehaviorPackScript(): Promise<void> {\n const mods = await scanLocalModules();\n const entries = mods.filter((m) => m.enabled && m.entryPath).map((m) => m.entryPath!);\n const outFile = path.join(bpSrc(), \"scripts\", \"main.js\");\n await fs.mkdir(path.dirname(outFile), { recursive: true });\n\n if (entries.length === 0) {\n await fs.writeFile(outFile, \"/* no modules enabled */\\n\", \"utf8\");\n pushLog(\"no enabled SAPI modules \u2014 empty main.js\", \"pack\", \"warn\");\n return;\n }\n\n const { build } = await import(\"esbuild\");\n const sdkRoot = await resolveSdkRootForEsbuild();\n await build({\n entryPoints: entries,\n outfile: outFile,\n bundle: true,\n platform: \"neutral\",\n format: \"esm\",\n target: \"es2022\",\n logLevel: \"warning\",\n sourcemap: false,\n external: [\"@minecraft/*\"],\n // BDS host \u542F\u52A8\uFF1A\u4E0E module-loader barrel \u5206\u79BB\uFF08DIP\uFF09\uFF0C\u987B\u5728\u6A21\u5757 register \u4E4B\u524D\u6267\u884C\n banner: {\n js: 'import { installHostBootstrap } from \"@sfmc-bds/sdk/module-loader/install\";\\ninstallHostBootstrap();\\n',\n },\n tsconfigRaw: JSON.stringify({\n compilerOptions: {\n module: \"ESNext\",\n moduleResolution: \"bundler\",\n target: \"ES2022\",\n strict: true,\n skipLibCheck: true,\n },\n }),\n plugins: [createSdkResolvePlugin(sdkRoot)],\n });\n pushLog(`esbuild bundled ${entries.length} entr(y/ies)`, \"pack\", \"info\");\n}\n\nasync function resolveSdkRootForEsbuild(): Promise<string> {\n const { resolveSdkPackageRoot } = await import(\"./runtime.js\");\n return resolveSdkPackageRoot();\n}\n\n/** esbuild \u63D2\u4EF6\uFF1A\u89E3\u6790 @sfmc-bds/sdk \u7684 exports \u5B57\u6BB5\uFF08\u4E0E pack-lifecycle.ts \u5185\u90E8\u5B9E\u73B0\u540C\u6B65\uFF09\u3002 */\nfunction createSdkResolvePlugin(sdkRoot: string): import(\"esbuild\").Plugin {\n const pkg = JSON.parse(readFileSync(path.join(sdkRoot, \"package.json\"), \"utf8\")) as {\n exports?: Record<string, string | { import?: string; default?: string; types?: string }>;\n };\n const exportsMap = pkg.exports ?? {};\n\n function resolveExportSubpath(subpath: string): string | null {\n const key = subpath === \"\" ? \".\" : `./${subpath}`;\n const entry = exportsMap[key];\n if (!entry) return null;\n const rel = typeof entry === \"string\" ? entry : (entry.import ?? entry.default);\n if (!rel || typeof rel !== \"string\") return null;\n const abs = path.join(sdkRoot, rel);\n return existsSync(abs) ? abs : null;\n }\n\n return {\n name: \"sfmc-sdk-resolve\",\n setup(build) {\n build.onResolve({ filter: /^@sfmc(?:-bds)?\\/sdk(?:\\/|$)/ }, (args) => {\n const normalized = args.path.replace(/^@sfmc\\/sdk/, \"@sfmc-bds/sdk\");\n const sub = normalized === \"@sfmc-bds/sdk\" ? \"\" : normalized.slice(\"@sfmc-bds/sdk/\".length);\n const resolved = resolveExportSubpath(sub);\n if (!resolved) {\n return {\n errors: [\n {\n text: `Cannot resolve ${args.path} under SDK at ${sdkRoot} (export \"./${sub || \".\"}\" missing or file absent; run sdk:build?)`,\n },\n ],\n };\n }\n return { path: resolved };\n });\n },\n };\n}\n\n/** spawn assemble-bp verb\u3002 */\nasync function spawnAssembleBp(catalog: DeployCatalog): Promise<SpawnResult> {\n const args = [\n \"assemble-bp\",\n \"--src\",\n bpSrc(),\n \"--out\",\n bpOut(),\n \"--name\",\n BP_NAME,\n \"--uuid\",\n catalog.bpUuid,\n \"--version\",\n catalog.bpVersion.join(\",\"),\n ];\n if (catalog.bpModuleUuid) args.push(\"--module-uuid\", catalog.bpModuleUuid);\n const r = await spawnPackManager(args);\n if (r.code === 0) {\n pushLog(`assembled BP uuid=${catalog.bpUuid}`, \"pack\", \"info\");\n }\n return r;\n}\n\n/** spawn assemble-rp verb\uFF1B\u65E0 RP \u65F6\u6E05\u7406\u65E7\u4EA7\u7269\u3002 */\nasync function spawnAssembleRp(\n catalog: DeployCatalog,\n rpDirs: Record<string, string>\n): Promise<SpawnResult> {\n if (!catalog.rpUuid || Object.keys(rpDirs).length === 0) {\n await fs.rm(rpOut(), { recursive: true, force: true });\n pushLog(\"no enabled resource packs \u2014 RP skipped\", \"pack\", \"info\");\n return { code: 0, output: \"[pack-manager] no enabled resource packs \u2014 RP skipped\\n\" };\n }\n const mapFile = path.join(buildRoot(), \"rp-map.json\");\n await fs.mkdir(buildRoot(), { recursive: true });\n await fs.writeFile(mapFile, JSON.stringify(rpDirs), \"utf8\");\n const args = [\n \"assemble-rp\",\n \"--modules-json\",\n mapFile,\n \"--out\",\n rpOut(),\n \"--name\",\n RP_NAME,\n \"--uuid\",\n catalog.rpUuid,\n \"--version\",\n (catalog.rpVersion ?? [1, 0, 0]).join(\",\"),\n ];\n if (catalog.rpModuleUuid) args.push(\"--module-uuid\", catalog.rpModuleUuid);\n const r = await spawnPackManager(args);\n if (r.code === 0) {\n pushLog(\n `assembled RP uuid=${catalog.rpUuid} (${Object.keys(rpDirs).length} modules)`,\n \"pack\",\n \"info\"\n );\n }\n return r;\n}\n\n/** spawn deploy verb\uFF1B\u65E0 RP \u65F6\u5E26 --clear-rp\u3002 */\nasync function spawnDeploy(catalog: DeployCatalog): Promise<SpawnResult> {\n const { bdsRoot, levelName } = resolveBdsContext();\n const args = [\n \"deploy\",\n \"--bds-root\",\n bdsRoot,\n \"--level\",\n levelName,\n \"--bp-src\",\n bpOut(),\n \"--bp-name\",\n BP_NAME,\n \"--rp-name\",\n RP_NAME,\n ];\n if (catalog.rpUuid && existsSync(rpOut())) {\n args.push(\"--rp-src\", rpOut());\n } else {\n args.push(\"--clear-rp\");\n }\n const r = await spawnPackManager(args);\n if (r.code === 0) {\n pushLog(`deployed to worlds/${levelName}`, \"pack\", \"info\");\n }\n return r;\n}\n\n/** spawn enable-pack verb\uFF1ABP \u5FC5\u987B\uFF0CRP \u4EC5\u5728\u6709 UUID \u65F6\u3002 */\nasync function spawnEnablePacks(catalog: DeployCatalog): Promise<SpawnResult> {\n const { bdsRoot, levelName } = resolveBdsContext();\n const worldsDir = path.join(bdsRoot, \"worlds\");\n let output = \"\";\n const bpArgs = [\n \"enable-pack\",\n \"--worlds-dir\",\n worldsDir,\n \"--level\",\n levelName,\n \"--kind\",\n \"behavior\",\n \"--pack-id\",\n catalog.bpUuid,\n \"--version\",\n catalog.bpVersion.join(\",\"),\n ];\n const bpR = await spawnPackManager(bpArgs);\n output += bpR.output;\n if (bpR.code !== 0) return { code: bpR.code, output };\n pushLog(\n `enabled behavior pack ${catalog.bpUuid} in world list`,\n \"pack\",\n \"info\"\n );\n if (catalog.rpUuid && catalog.rpVersion) {\n const rpArgs = [\n \"enable-pack\",\n \"--worlds-dir\",\n worldsDir,\n \"--level\",\n levelName,\n \"--kind\",\n \"resource\",\n \"--pack-id\",\n catalog.rpUuid,\n \"--version\",\n catalog.rpVersion.join(\",\"),\n ];\n const rpR = await spawnPackManager(rpArgs);\n output += rpR.output;\n if (rpR.code !== 0) return { code: rpR.code, output };\n pushLog(\n `enabled resource pack ${catalog.rpUuid} in world list`,\n \"pack\",\n \"info\"\n );\n }\n return { code: 0, output };\n}\n\n/** spawn disable-pack verb\uFF1A\u6E05\u7406\u8FC7\u671F UUID\uFF08uuid \u8F6E\u6362 / \u4E0D\u518D\u63D0\u4F9B RP\uFF09\u3002 */\nasync function spawnDisableStale(\n current: DeployCatalog,\n bdsRoot: string,\n levelName: string\n): Promise<void> {\n const previous = await collectDeployedPackUuids(bdsRoot, levelName);\n const worldsDir = path.join(bdsRoot, \"worlds\");\n for (const staleRp of previous.rp) {\n if (staleRp === (current.rpUuid ?? null)) continue;\n const r = await spawnPackManager([\n \"disable-pack\",\n \"--worlds-dir\",\n worldsDir,\n \"--level\",\n levelName,\n \"--kind\",\n \"resource\",\n \"--pack-id\",\n staleRp,\n \"--version\",\n \"1,0,0\",\n ]);\n if (r.code === 0) {\n pushLog(`disabled stale resource pack ${staleRp}`, \"pack\", \"info\");\n } else {\n pushLog(\n `disable stale RP ${staleRp} failed: ${r.output.trim()}`,\n \"pack\",\n \"warn\"\n );\n }\n }\n for (const staleBp of previous.bp) {\n if (staleBp === current.bpUuid) continue;\n const r = await spawnPackManager([\n \"disable-pack\",\n \"--worlds-dir\",\n worldsDir,\n \"--level\",\n levelName,\n \"--kind\",\n \"behavior\",\n \"--pack-id\",\n staleBp,\n \"--version\",\n \"1,0,0\",\n ]);\n if (r.code === 0) {\n pushLog(`disabled stale behavior pack ${staleBp}`, \"pack\", \"info\");\n } else {\n pushLog(\n `disable stale BP ${staleBp} failed: ${r.output.trim()}`,\n \"pack\",\n \"warn\"\n );\n }\n }\n}\n\n/** \u901A\u8FC7 bds-tools \u7684 list-installed + read-manifest \u62FF\u5230 deployed UUID\uFF08spawn\uFF09\u3002 */\nasync function collectDeployedPackUuids(\n bdsRoot: string,\n levelName: string\n): Promise<{ bp: Set<string>; rp: Set<string> }> {\n const bp = new Set<string>();\n const rp = new Set<string>();\n const cat = readDeployedCatalog(bdsRoot, levelName);\n if (cat?.bpUuid) bp.add(cat.bpUuid);\n if (cat?.rpUuid) rp.add(cat.rpUuid);\n // \u901A\u8FC7 read-manifest \u770B\u4E16\u754C\u78C1\u76D8 BP/RP manifest \u7684 uuid\uFF0C\u4F5C\u4E3A catalog \u7F3A\u5931\u65F6\u7684\u515C\u5E95\u3002\n const bpDir = path.join(bdsRoot, \"worlds\", levelName, \"behavior_packs\", BP_NAME);\n const rpDir = path.join(bdsRoot, \"worlds\", levelName, \"resource_packs\", RP_NAME);\n const bpR = await spawnPackManager([\"read-manifest\", \"--pack-dir\", bpDir]);\n if (bpR.code === 0) {\n try {\n const j = JSON.parse(bpR.output.trim()) as { uuid?: string } | null;\n if (j?.uuid) bp.add(j.uuid);\n } catch {\n /* ignore */\n }\n }\n const rpR = await spawnPackManager([\"read-manifest\", \"--pack-dir\", rpDir]);\n if (rpR.code === 0) {\n try {\n const j = JSON.parse(rpR.output.trim()) as { uuid?: string } | null;\n if (j?.uuid) rp.add(j.uuid);\n } catch {\n /* ignore */\n }\n }\n return { bp, rp };\n}\n\n/** spawn ensure-permission verb\u3002 */\nasync function spawnEnsurePermission(catalog: DeployCatalog): Promise<SpawnResult> {\n const { bdsRoot } = resolveBdsContext();\n const r = await spawnPackManager([\n \"ensure-permission\",\n \"--bds-root\",\n bdsRoot,\n \"--pack-id\",\n catalog.bpUuid,\n ]);\n return r;\n}\n\n/**\n * `sfmc mod build` \u2014\u2014 \u7EC4\u88C5 BP + RP\uFF08\u4E0D\u90E8\u7F72\uFF09\u3002\n * \u4EC5\u5F53 catalog \u4E0E\u4E16\u754C\u5185\u5DF2\u90E8\u7F72\u4E0D\u4E00\u81F4\u65F6\u6267\u884C\uFF1B\u5426\u5219\u76F4\u63A5\u6253\"\u5DF2\u540C\u6B65\"\u3002\n */\nexport async function cmdModuleBuild(_args: string[]): Promise<string> {\n try {\n const { bdsRoot, levelName } = resolveBdsContext();\n const deployed = readDeployedCatalog(bdsRoot, levelName);\n const desired = await computeDesiredCatalog(deployed ? reusePackIds(deployed) : undefined);\n\n if (deployed && catalogsEqual(desired, deployed)) {\n return formatPackLoadInfo(desired, false);\n }\n\n pushLog(\n `building BP/RP (modules=${Object.keys(desired.modules).length})\u2026`,\n \"pack\",\n \"info\"\n );\n await bundleBehaviorPackScript();\n\n const mods = await scanLocalModules();\n const rpDirs: Record<string, string> = {};\n for (const m of mods) {\n if (!m.enabled || !m.hasResourcePack) continue;\n rpDirs[m.folderId] = path.join(\"modules\", \"packages\", m.folderId, \"resource_pack\");\n }\n\n const bpR = await spawnAssembleBp(desired);\n if (bpR.code !== 0) return c.red(bpR.output.trim() || `assemble-bp exit ${bpR.code}`);\n const rpR = await spawnAssembleRp(desired, rpDirs);\n if (rpR.code !== 0) return c.red(rpR.output.trim() || `assemble-rp exit ${rpR.code}`);\n\n desired.generatedAt = Date.now();\n if (Object.keys(rpDirs).length === 0) {\n desired.rpUuid = null;\n desired.rpVersion = null;\n }\n writeJson(path.join(bpOut(), DEPLOY_CATALOG_NAME), desired);\n\n return c.green(t(\"pack.built\", { path: bpOut() })) + \"\\n\" + formatPackLoadInfo(desired, true);\n } catch (e) {\n return c.red((e as Error).message);\n }\n}\n\n/**\n * `sfmc mod reload [--build-only]` \u2014\u2014 \u7EC4\u88C5 + \u90E8\u7F72 + \u6E05\u7406\u8FC7\u671F + \u5199\u6743\u9650 + \uFF08\u9ED8\u8BA4\uFF09\u53D1 reload \u5230 BDS\u3002\n */\nexport async function cmdModuleReload(args: string[]): Promise<string> {\n const buildOnly = args.includes(\"--build-only\");\n const parts: string[] = [];\n\n const buildMsg = await cmdModuleBuild([]);\n parts.push(buildMsg.trimEnd());\n if (buildMsg.startsWith(c.red(\"\"))) return parts.join(\"\\n\") + \"\\n\";\n\n try {\n const { bdsRoot, levelName } = resolveBdsContext();\n const desired = await computeDesiredCatalog();\n\n const depR = await spawnDeploy(desired);\n if (depR.code !== 0) {\n return parts.join(\"\\n\") + \"\\n\" + c.red(depR.output.trim() || `deploy exit ${depR.code}`);\n }\n parts.push(depR.output.trimEnd());\n\n writeJson(path.join(deployedBpDir(bdsRoot, levelName), DEPLOY_CATALOG_NAME), desired);\n\n await spawnDisableStale(desired, bdsRoot, levelName);\n\n const enR = await spawnEnablePacks(desired);\n if (enR.code !== 0) {\n return parts.join(\"\\n\") + \"\\n\" + c.red(enR.output.trim() || `enable-pack exit ${enR.code}`);\n }\n parts.push(enR.output.trimEnd());\n\n const perR = await spawnEnsurePermission(desired);\n if (perR.code !== 0) {\n return parts.join(\"\\n\") + \"\\n\" + c.red(perR.output.trim() || `ensure-permission exit ${perR.code}`);\n }\n parts.push(perR.output.trimEnd());\n } catch (e) {\n return parts.join(\"\\n\") + \"\\n\" + c.red((e as Error).message);\n }\n\n if (buildOnly) {\n parts.push(c.dim(t(\"reload.buildOnly\")));\n return parts.join(\"\\n\") + \"\\n\";\n }\n\n const { isServiceRunning } = await import(\"./services.js\");\n if (!(await isServiceRunning(\"bds\"))) {\n parts.push(c.yellow(t(\"reload.bdsNotRunning\")));\n return parts.join(\"\\n\") + \"\\n\";\n }\n const { cmdSend } = await import(\"./commands.js\");\n parts.push((await cmdSend(\"bds\", \"reload\")).trimEnd());\n parts.push(c.green(t(\"reload.sent\")));\n return parts.join(\"\\n\") + \"\\n\";\n}\n\nfunction reusePackIds(\n deployed: DeployCatalog\n): Parameters<typeof computeDesiredCatalog>[0] {\n return {\n bpUuid: deployed.bpUuid,\n rpUuid: deployed.rpUuid,\n bpVersion: deployed.bpVersion,\n rpVersion: deployed.rpVersion,\n ...(deployed.bpModuleUuid ? { bpModuleUuid: deployed.bpModuleUuid } : {}),\n ...(deployed.rpModuleUuid ? { rpModuleUuid: deployed.rpModuleUuid } : {}),\n };\n}"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,33 @@
1
+ /**
2
+ * module-toggle.ts — 模块启停:本地 lock 权威 + 通知结果信封
3
+ *
4
+ * CLI 先写 module-lock.json;db 在线时再 best-effort HTTP 热同步。
5
+ * 纯函数与 IO 分离,供单测覆盖 resolve / lock patch / 结果判定。
6
+ */
7
+ import type { ModuleLock } from "@sfmc-bds/sdk/node/config";
8
+ export type ToggleCandidate = {
9
+ logicalId: string;
10
+ folderId: string;
11
+ configKey?: string;
12
+ canDisable: boolean;
13
+ };
14
+ export type ToggleNotify = {
15
+ ok: true;
16
+ } | {
17
+ ok: false;
18
+ reason: "unreachable" | "http";
19
+ detail?: string;
20
+ };
21
+ export type ToggleFinalize = {
22
+ ok: boolean;
23
+ warnNotify: boolean;
24
+ };
25
+ /** 按 folderId / logicalId / configKey 解析启停目标(与 db resolveModuleByKey 对齐)。 */
26
+ export declare function resolveToggleTarget(query: string, candidates: ToggleCandidate[]): ToggleCandidate | null;
27
+ /** 就地更新 lock 条目(键为 manifest.id / logicalId)。 */
28
+ export declare function applyLockEnabled(lock: ModuleLock, logicalId: string, enabled: boolean): ModuleLock;
29
+ /**
30
+ * 本地已落盘时,通知失败仍算成功(warnNotify);本地未写则失败。
31
+ */
32
+ export declare function finalizeToggle(localWritten: boolean, notify: ToggleNotify): ToggleFinalize;
33
+ //# sourceMappingURL=module-toggle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"module-toggle.d.ts","sourceRoot":"","sources":["../src/module-toggle.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAE5D,MAAM,MAAM,eAAe,GAAG;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,OAAO,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,YAAY,GACpB;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GACZ;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,aAAa,GAAG,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAEnE,MAAM,MAAM,cAAc,GAAG;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,UAAU,EAAE,OAAO,CAAA;CAAE,CAAC;AAElE,6EAA6E;AAC7E,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,eAAe,EAAE,GAAG,eAAe,GAAG,IAAI,CAQxG;AAED,gDAAgD;AAChD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,UAAU,CASlG;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,YAAY,EAAE,OAAO,EAAE,MAAM,EAAE,YAAY,GAAG,cAAc,CAI1F"}
@@ -0,0 +1,28 @@
1
+ function resolveToggleTarget(query, candidates) {
2
+ const k = String(query || "").trim();
3
+ if (!k) return null;
4
+ return candidates.find(
5
+ (c) => c.folderId === k || c.logicalId === k || c.configKey != null && c.configKey === k
6
+ ) ?? null;
7
+ }
8
+ function applyLockEnabled(lock, logicalId, enabled) {
9
+ const modules = lock.modules && typeof lock.modules === "object" ? lock.modules : {};
10
+ lock.modules = modules;
11
+ lock.version = typeof lock.version === "number" ? lock.version : 1;
12
+ modules[logicalId] = {
13
+ enabled: !!enabled,
14
+ updatedAt: Date.now()
15
+ };
16
+ return lock;
17
+ }
18
+ function finalizeToggle(localWritten, notify) {
19
+ if (!localWritten) return { ok: false, warnNotify: false };
20
+ if (notify.ok) return { ok: true, warnNotify: false };
21
+ return { ok: true, warnNotify: true };
22
+ }
23
+ export {
24
+ applyLockEnabled,
25
+ finalizeToggle,
26
+ resolveToggleTarget
27
+ };
28
+ //# sourceMappingURL=module-toggle.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/module-toggle.ts"],
4
+ "sourcesContent": ["/**\n * module-toggle.ts \u2014 \u6A21\u5757\u542F\u505C\uFF1A\u672C\u5730 lock \u6743\u5A01 + \u901A\u77E5\u7ED3\u679C\u4FE1\u5C01\n *\n * CLI \u5148\u5199 module-lock.json\uFF1Bdb \u5728\u7EBF\u65F6\u518D best-effort HTTP \u70ED\u540C\u6B65\u3002\n * \u7EAF\u51FD\u6570\u4E0E IO \u5206\u79BB\uFF0C\u4F9B\u5355\u6D4B\u8986\u76D6 resolve / lock patch / \u7ED3\u679C\u5224\u5B9A\u3002\n */\n\nimport type { ModuleLock } from \"@sfmc-bds/sdk/node/config\";\n\nexport type ToggleCandidate = {\n logicalId: string;\n folderId: string;\n configKey?: string;\n canDisable: boolean;\n};\n\nexport type ToggleNotify =\n | { ok: true }\n | { ok: false; reason: \"unreachable\" | \"http\"; detail?: string };\n\nexport type ToggleFinalize = { ok: boolean; warnNotify: boolean };\n\n/** \u6309 folderId / logicalId / configKey \u89E3\u6790\u542F\u505C\u76EE\u6807\uFF08\u4E0E db resolveModuleByKey \u5BF9\u9F50\uFF09\u3002 */\nexport function resolveToggleTarget(query: string, candidates: ToggleCandidate[]): ToggleCandidate | null {\n const k = String(query || \"\").trim();\n if (!k) return null;\n return (\n candidates.find(\n (c) => c.folderId === k || c.logicalId === k || (c.configKey != null && c.configKey === k)\n ) ?? null\n );\n}\n\n/** \u5C31\u5730\u66F4\u65B0 lock \u6761\u76EE\uFF08\u952E\u4E3A manifest.id / logicalId\uFF09\u3002 */\nexport function applyLockEnabled(lock: ModuleLock, logicalId: string, enabled: boolean): ModuleLock {\n const modules = lock.modules && typeof lock.modules === \"object\" ? lock.modules : {};\n lock.modules = modules;\n lock.version = typeof lock.version === \"number\" ? lock.version : 1;\n modules[logicalId] = {\n enabled: !!enabled,\n updatedAt: Date.now(),\n };\n return lock;\n}\n\n/**\n * \u672C\u5730\u5DF2\u843D\u76D8\u65F6\uFF0C\u901A\u77E5\u5931\u8D25\u4ECD\u7B97\u6210\u529F\uFF08warnNotify\uFF09\uFF1B\u672C\u5730\u672A\u5199\u5219\u5931\u8D25\u3002\n */\nexport function finalizeToggle(localWritten: boolean, notify: ToggleNotify): ToggleFinalize {\n if (!localWritten) return { ok: false, warnNotify: false };\n if (notify.ok) return { ok: true, warnNotify: false };\n return { ok: true, warnNotify: true };\n}\n"],
5
+ "mappings": "AAuBO,SAAS,oBAAoB,OAAe,YAAuD;AACxG,QAAM,IAAI,OAAO,SAAS,EAAE,EAAE,KAAK;AACnC,MAAI,CAAC,EAAG,QAAO;AACf,SACE,WAAW;AAAA,IACT,CAAC,MAAM,EAAE,aAAa,KAAK,EAAE,cAAc,KAAM,EAAE,aAAa,QAAQ,EAAE,cAAc;AAAA,EAC1F,KAAK;AAET;AAGO,SAAS,iBAAiB,MAAkB,WAAmB,SAA8B;AAClG,QAAM,UAAU,KAAK,WAAW,OAAO,KAAK,YAAY,WAAW,KAAK,UAAU,CAAC;AACnF,OAAK,UAAU;AACf,OAAK,UAAU,OAAO,KAAK,YAAY,WAAW,KAAK,UAAU;AACjE,UAAQ,SAAS,IAAI;AAAA,IACnB,SAAS,CAAC,CAAC;AAAA,IACX,WAAW,KAAK,IAAI;AAAA,EACtB;AACA,SAAO;AACT;AAKO,SAAS,eAAe,cAAuB,QAAsC;AAC1F,MAAI,CAAC,aAAc,QAAO,EAAE,IAAI,OAAO,YAAY,MAAM;AACzD,MAAI,OAAO,GAAI,QAAO,EAAE,IAAI,MAAM,YAAY,MAAM;AACpD,SAAO,EAAE,IAAI,MAAM,YAAY,KAAK;AACtC;",
6
+ "names": []
7
+ }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * node-service-probe.ts — 按入口脚本探测 / 终止「外部」node 服务(db / qq)
3
+ *
4
+ * CLI 未托管(无 ChildProcess 句柄)时,stop/restart 仍须能杀干净,避免双实例。
5
+ */
6
+ /** 可按脚本路径杀的 node 服务 */
7
+ export type NodeServiceName = "db" | "qq";
8
+ /** cmdline 匹配用稳定子串(跨 monorepo / npm 布局) */
9
+ export declare const SCRIPT_HINT: Record<NodeServiceName, string>;
10
+ /**
11
+ * 查找匹配入口脚本的存活 PID(不含当前 CLI 进程)。
12
+ */
13
+ export declare function findNodeServicePids(service: NodeServiceName): Promise<number[]>;
14
+ /**
15
+ * 终止匹配脚本的全部外部实例;返回尝试杀掉的 PID 列表。
16
+ */
17
+ export declare function killNodeServiceByScript(service: NodeServiceName): Promise<number[]>;
18
+ //# sourceMappingURL=node-service-probe.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"node-service-probe.d.ts","sourceRoot":"","sources":["../src/node-service-probe.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AASH,uBAAuB;AACvB,MAAM,MAAM,eAAe,GAAG,IAAI,GAAG,IAAI,CAAC;AAE1C,2CAA2C;AAC3C,eAAO,MAAM,WAAW,EAAE,MAAM,CAAC,eAAe,EAAE,MAAM,CAGvD,CAAC;AAuDF;;GAEG;AACH,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAOrF;AAUD;;GAEG;AACH,wBAAsB,uBAAuB,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAqBzF"}
@@ -0,0 +1,97 @@
1
+ import { execFile } from "node:child_process";
2
+ import { promisify } from "node:util";
3
+ import process from "node:process";
4
+ import { isProcessAlive } from "@sfmc-bds/bds-tools/process-probe";
5
+ const execFileAsync = promisify(execFile);
6
+ const SCRIPT_HINT = {
7
+ db: "db-server/dist/index.js",
8
+ qq: "qq-bridge/dist/index.js"
9
+ };
10
+ function normalizePath(p) {
11
+ return p.replace(/\\/g, "/").toLowerCase();
12
+ }
13
+ function matchesService(cmdline, service) {
14
+ const n = normalizePath(cmdline);
15
+ const hint = SCRIPT_HINT[service];
16
+ if (!n.includes(hint)) return false;
17
+ return /\bnode(?:\.exe)?\b/i.test(cmdline) || n.includes("node");
18
+ }
19
+ async function listCandidatePids(service) {
20
+ const hint = SCRIPT_HINT[service];
21
+ if (process.platform === "win32") {
22
+ try {
23
+ const { stdout } = await execFileAsync(
24
+ "wmic",
25
+ ["process", "where", "name='node.exe'", "get", "ProcessId,CommandLine", "/FORMAT:CSV"],
26
+ { windowsHide: true, timeout: 8e3 }
27
+ );
28
+ const pids = [];
29
+ for (const line of String(stdout).split(/\r?\n/)) {
30
+ if (!line.trim() || /^Node,/i.test(line.trim())) continue;
31
+ if (!matchesService(line, service)) continue;
32
+ const parts = line.split(",");
33
+ const pid = parseInt(parts[parts.length - 1]?.trim() || "", 10);
34
+ if (!pid || pid === process.pid) continue;
35
+ pids.push(pid);
36
+ }
37
+ return [...new Set(pids)];
38
+ } catch {
39
+ return [];
40
+ }
41
+ }
42
+ try {
43
+ const { stdout } = await execFileAsync("pgrep", ["-af", hint], { timeout: 5e3 });
44
+ const pids = [];
45
+ for (const line of String(stdout).split(/\n/)) {
46
+ if (!matchesService(line, service)) continue;
47
+ const pid = parseInt(line.trim().split(/\s+/)[0] || "", 10);
48
+ if (!pid || pid === process.pid) continue;
49
+ pids.push(pid);
50
+ }
51
+ return [...new Set(pids)];
52
+ } catch {
53
+ return [];
54
+ }
55
+ }
56
+ async function findNodeServicePids(service) {
57
+ const pids = await listCandidatePids(service);
58
+ const alive = [];
59
+ for (const pid of pids) {
60
+ if (await isProcessAlive(pid)) alive.push(pid);
61
+ }
62
+ return [...new Set(alive)];
63
+ }
64
+ function killPid(pid, sig) {
65
+ try {
66
+ process.kill(pid, sig);
67
+ } catch {
68
+ }
69
+ }
70
+ async function killNodeServiceByScript(service) {
71
+ const pids = await findNodeServicePids(service);
72
+ for (const pid of pids) {
73
+ killPid(pid, "SIGTERM");
74
+ }
75
+ const deadline = Date.now() + 8e3;
76
+ while (Date.now() < deadline) {
77
+ let any = false;
78
+ for (const pid of pids) {
79
+ if (await isProcessAlive(pid)) {
80
+ any = true;
81
+ break;
82
+ }
83
+ }
84
+ if (!any) return pids;
85
+ await new Promise((r) => setTimeout(r, 200));
86
+ }
87
+ for (const pid of pids) {
88
+ if (await isProcessAlive(pid)) killPid(pid, "SIGKILL");
89
+ }
90
+ return pids;
91
+ }
92
+ export {
93
+ SCRIPT_HINT,
94
+ findNodeServicePids,
95
+ killNodeServiceByScript
96
+ };
97
+ //# sourceMappingURL=node-service-probe.js.map