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

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 (128) hide show
  1. package/LICENSE +663 -0
  2. package/README.md +4 -5
  3. package/dist/bds-runtime-version.d.ts +3 -0
  4. package/dist/bds-runtime-version.d.ts.map +1 -0
  5. package/dist/bds-runtime-version.js +15 -0
  6. package/dist/bds-runtime-version.js.map +7 -0
  7. package/dist/command-surface.d.ts.map +1 -1
  8. package/dist/command-surface.js +3 -1
  9. package/dist/command-surface.js.map +2 -2
  10. package/dist/commands.d.ts +57 -4
  11. package/dist/commands.d.ts.map +1 -1
  12. package/dist/commands.js +78 -75
  13. package/dist/commands.js.map +2 -2
  14. package/dist/directory-picker.d.ts +27 -0
  15. package/dist/directory-picker.d.ts.map +1 -0
  16. package/dist/directory-picker.js +112 -0
  17. package/dist/directory-picker.js.map +7 -0
  18. package/dist/i18n/locales/en.d.ts +25 -1
  19. package/dist/i18n/locales/en.d.ts.map +1 -1
  20. package/dist/i18n/locales/en.js +25 -1
  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 +26 -2
  24. package/dist/i18n/locales/zh-CN.js.map +2 -2
  25. package/dist/interactive-prompts.d.ts +1 -2
  26. package/dist/interactive-prompts.d.ts.map +1 -1
  27. package/dist/interactive-prompts.js +12 -23
  28. package/dist/interactive-prompts.js.map +3 -3
  29. package/dist/llbot-launch.d.ts +3 -3
  30. package/dist/llbot-launch.js.map +1 -1
  31. package/dist/log-filter.d.ts +18 -2
  32. package/dist/log-filter.d.ts.map +1 -1
  33. package/dist/log-filter.js +54 -4
  34. package/dist/log-filter.js.map +2 -2
  35. package/dist/log-translator.d.ts +36 -0
  36. package/dist/log-translator.d.ts.map +1 -0
  37. package/dist/log-translator.js +279 -0
  38. package/dist/log-translator.js.map +7 -0
  39. package/dist/logs.d.ts +2 -0
  40. package/dist/logs.d.ts.map +1 -1
  41. package/dist/logs.js +24 -11
  42. package/dist/logs.js.map +2 -2
  43. package/dist/main.js +5 -0
  44. package/dist/main.js.map +2 -2
  45. package/dist/module-commands.d.ts.map +1 -1
  46. package/dist/module-commands.js +34 -13
  47. package/dist/module-commands.js.map +2 -2
  48. package/dist/module-fingerprint.d.ts.map +1 -1
  49. package/dist/module-fingerprint.js +1 -0
  50. package/dist/module-fingerprint.js.map +2 -2
  51. package/dist/module-pack-build.d.ts +14 -4
  52. package/dist/module-pack-build.d.ts.map +1 -1
  53. package/dist/module-pack-build.js +81 -108
  54. package/dist/module-pack-build.js.map +2 -2
  55. package/dist/module-toggle.d.ts +1 -1
  56. package/dist/module-toggle.d.ts.map +1 -1
  57. package/dist/module-toggle.js.map +1 -1
  58. package/dist/pack-lifecycle.d.ts +15 -1
  59. package/dist/pack-lifecycle.d.ts.map +1 -1
  60. package/dist/pack-lifecycle.js +242 -15
  61. package/dist/pack-lifecycle.js.map +2 -2
  62. package/dist/player-session.d.ts +13 -0
  63. package/dist/player-session.d.ts.map +1 -0
  64. package/dist/player-session.js +26 -0
  65. package/dist/player-session.js.map +7 -0
  66. package/dist/registry.d.ts +1 -1
  67. package/dist/registry.d.ts.map +1 -1
  68. package/dist/registry.js +4 -1
  69. package/dist/registry.js.map +2 -2
  70. package/dist/repl-windows/format-display.d.ts.map +1 -1
  71. package/dist/repl-windows/format-display.js +5 -1
  72. package/dist/repl-windows/format-display.js.map +2 -2
  73. package/dist/repl-windows/host.d.ts +6 -3
  74. package/dist/repl-windows/host.d.ts.map +1 -1
  75. package/dist/repl-windows/host.js +12 -6
  76. package/dist/repl-windows/host.js.map +2 -2
  77. package/dist/repl-windows/index.d.ts +1 -0
  78. package/dist/repl-windows/index.d.ts.map +1 -1
  79. package/dist/repl-windows/index.js +3 -0
  80. package/dist/repl-windows/index.js.map +2 -2
  81. package/dist/repl-windows/service-window.d.ts.map +1 -1
  82. package/dist/repl-windows/service-window.js +1 -0
  83. package/dist/repl-windows/service-window.js.map +2 -2
  84. package/dist/repl-windows/sfmc-window.d.ts +7 -0
  85. package/dist/repl-windows/sfmc-window.d.ts.map +1 -0
  86. package/dist/repl-windows/sfmc-window.js +28 -0
  87. package/dist/repl-windows/sfmc-window.js.map +7 -0
  88. package/dist/repl.d.ts.map +1 -1
  89. package/dist/repl.js +38 -13
  90. package/dist/repl.js.map +2 -2
  91. package/dist/runtime.d.ts +2 -2
  92. package/dist/runtime.d.ts.map +1 -1
  93. package/dist/runtime.js +15 -2
  94. package/dist/runtime.js.map +2 -2
  95. package/dist/send-target.d.ts +2 -0
  96. package/dist/send-target.d.ts.map +1 -1
  97. package/dist/send-target.js +6 -0
  98. package/dist/send-target.js.map +2 -2
  99. package/dist/services.d.ts +26 -1
  100. package/dist/services.d.ts.map +1 -1
  101. package/dist/services.js +179 -45
  102. package/dist/services.js.map +2 -2
  103. package/dist/sfmc-modules-root.d.ts.map +1 -1
  104. package/dist/sfmc-modules-root.js +6 -2
  105. package/dist/sfmc-modules-root.js.map +2 -2
  106. package/dist/ui-command.d.ts +6 -0
  107. package/dist/ui-command.d.ts.map +1 -0
  108. package/dist/ui-command.js +68 -0
  109. package/dist/ui-command.js.map +7 -0
  110. package/dist/wizard.d.ts.map +1 -1
  111. package/dist/wizard.js +36 -31
  112. package/dist/wizard.js.map +2 -2
  113. package/dist/world-packs.d.ts +2 -0
  114. package/dist/world-packs.d.ts.map +1 -1
  115. package/dist/world-packs.js +161 -18
  116. package/dist/world-packs.js.map +2 -2
  117. package/package.json +22 -15
  118. package/scripts/module-install/check-modules.mjs +178 -0
  119. package/scripts/module-install/fetch-module.mjs +1088 -0
  120. package/scripts/module-install/lib/catalog.mjs +96 -0
  121. package/scripts/module-install/lib/config-seeding.mjs +128 -0
  122. package/scripts/module-install/lib/io.mjs +37 -0
  123. package/scripts/module-install/lib/link-from.mjs +80 -0
  124. package/scripts/module-install/lib/lock.mjs +78 -0
  125. package/scripts/module-install/lib/npm-resolver.mjs +55 -0
  126. package/scripts/module-install/lib/packages.mjs +136 -0
  127. package/scripts/module-install/lib/paths.mjs +48 -0
  128. package/scripts/module-install/lib/registry-index.mjs +50 -0
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/pack-lifecycle.ts"],
4
- "sourcesContent": ["/**\n * pack-lifecycle.ts \u2014 \u884C\u4E3A\u5305/\u8D44\u6E90\u5305\u88C5\u8F7D\u751F\u547D\u5468\u671F\n *\n * \u804C\u8D23:\n * - \u8BA1\u7B97\u672C\u673A desired deploy-catalog(\u542F\u7528\u6A21\u5757 + fingerprint)\n * - \u4E0E\u4E16\u754C BP \u5185 sfmc-deploy-catalog.json \u6BD4\u5BF9\n * - \u4E0D\u4E00\u81F4\u5219\u6574\u5305 build + deploy + \u5199\u4E16\u754C\u6E05\u5355 + Script API permission\n * - \u542F\u52A8\u524D ensurePacksReady;\u65E5\u5FD7\u4E00\u5F8B\u8D70 source=`pack`\n */\n\nimport {\n configPath,\n modulePath,\n readJson,\n writeJson,\n type BdsUpdaterConfig,\n type Catalog,\n type ModuleLock,\n} from \"@sfmc-bds/sdk/node/config\";\nimport { existsSync, readFileSync } from \"node:fs\";\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { pushLog } from \"./logs.js\";\nimport { dirFingerprint } from \"./module-fingerprint.js\";\nimport { failResult, okResult, type CliResult } from \"./cli-result.js\";\nimport { t } from \"./i18n/index.js\";\nimport {\n assembleBehaviorPack,\n assembleResourcePack,\n bdsWorldLevelDir,\n bdsWorldsDir,\n configPermissionPath,\n deployToBDS,\n disablePackInWorld,\n enablePackInWorld,\n ensureConfigPermission,\n hasConfigPermission,\n readLevelNameSync,\n readPackManifestHeader,\n readWorldPackList,\n worldPackListHas as pmWorldPackListHas,\n} from \"@sfmc-bds/bds-tools/pack-manager-lib\";\nimport { ROOT, PACKAGES_DIR, resolveSdkPackageRoot, getRoot } from \"./runtime.js\";\nimport { c } from \"./theme.js\";\n\nexport const BP_NAME = \"sfmc-modules\";\nexport const RP_NAME = \"sfmc-modules-rp\";\nexport const DEPLOY_CATALOG_NAME = \"sfmc-deploy-catalog.json\";\nexport const DEFAULT_PACK_VERSION: [number, number, number] = [1, 0, 0];\n\n/** \u5C06 @sfmc/sdk \u4E0E @sfmc-bds/sdk \u5B50\u8DEF\u5F84\u89E3\u6790\u5230 SDK \u5305\u5185\u771F\u5B9E\u6587\u4EF6 */\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\nexport function buildRoot(): string {\n /* \u4E0E\u6536\u4EF6\u7BB1\u540C\u6811\uFF1Apacks/_build\uFF08_ \u524D\u7F00\u4E0D\u4F1A\u88AB inbox \u626B\u63CF\uFF09 */\n return path.join(ROOT, \"packs\", \"_build\");\n}\nexport function bpSrc(): string {\n return path.join(buildRoot(), `${BP_NAME}-bp`);\n}\nexport function bpOut(): string {\n return path.join(buildRoot(), BP_NAME);\n}\nexport function rpOut(): string {\n return path.join(buildRoot(), RP_NAME);\n}\n\nexport interface DeployCatalogModule {\n logicalId: string;\n enabled: boolean;\n version: string;\n fingerprint: string;\n hasResourcePack: boolean;\n}\n\nexport interface DeployCatalog {\n schemaVersion: 1;\n bpUuid: string;\n rpUuid: string | null;\n bpVersion: [number, number, number];\n rpVersion: [number, number, number] | null;\n bpModuleUuid?: string;\n rpModuleUuid?: string;\n generatedAt: number;\n modules: Record<string, DeployCatalogModule>;\n}\n\nexport interface PackEnsureResult {\n rebuilt: boolean;\n skipped: boolean;\n catalog: DeployCatalog;\n bdsRoot: string;\n levelName: string;\n summary: string;\n}\n\ninterface PackManifestLite {\n id?: string;\n version?: string;\n schemaVersion?: number;\n enabledByDefault?: boolean;\n name?: string;\n}\n\nfunction packLog(text: string, level: \"info\" | \"success\" | \"warn\" | \"error\" = \"info\"): void {\n pushLog(text, \"pack\", level);\n}\n\nfunction packagesDir(): string {\n return PACKAGES_DIR || path.join(ROOT, \"modules\", \"packages\");\n}\n\nfunction lockPath(): string {\n return modulePath(path.join(ROOT, \"modules\"), \"module-lock.json\");\n}\n\nfunction catalogPath(): string {\n return modulePath(path.join(ROOT, \"modules\"), \"catalog.json\");\n}\n\n/** \u8BFB BDS \u8DEF\u5F84\u4E0E level-name\uFF08level \u6743\u5A01\uFF1Apack-manager-lib.readLevelNameSync\uFF0CDIP\uFF09 */\nexport function resolveBdsContext(root: string = getRoot()): { bdsRoot: string; levelName: string } {\n const cfg = (readJson<BdsUpdaterConfig>(configPath(root, \"bds_updater.json\")) ?? {}) as BdsUpdaterConfig;\n const bdsRoot = cfg.bds_path;\n if (!bdsRoot) {\n throw new Error(\"bds_path not configured. Run `sfmc init` first.\");\n }\n return { bdsRoot, levelName: readLevelNameSync(bdsRoot) };\n}\n\nexport function deployedBpDir(bdsRoot: string, levelName: string): string {\n return path.join(bdsWorldLevelDir(bdsRoot, levelName), \"behavior_packs\", BP_NAME);\n}\n\nexport function deployedRpDir(bdsRoot: string, levelName: string): string {\n return path.join(bdsWorldLevelDir(bdsRoot, levelName), \"resource_packs\", RP_NAME);\n}\n\nexport function deployedCatalogPath(bdsRoot: string, levelName: string): string {\n return path.join(deployedBpDir(bdsRoot, levelName), DEPLOY_CATALOG_NAME);\n}\n\n/** \u89E3\u6790\u542F\u7528\u72B6\u6001:lock \u4F18\u5148,\u5426\u5219 catalog.enabledByDefault(\u7F3A\u7701 true\u2194!==false),\u672A\u6536\u5F55\u6A21\u5757 false */\nfunction isModuleEnabled(logicalId: string, lock: ModuleLock, catalogDefaults: Map<string, boolean>): boolean {\n const st = lock.modules?.[logicalId];\n if (st && typeof st.enabled === \"boolean\") return st.enabled;\n return catalogDefaults.get(logicalId) ?? false;\n}\n\n/**\n * \u90E8\u7F72\u524D\u6536\u96C6\u4E16\u754C\u5185\u5DF2\u51FA\u73B0\u7684 BP/RP uuid\u3002\n * \u540C\u65F6\u8BFB deploy-catalog \u4E0E\u78C1\u76D8 manifest \u2014 catalog \u7F3A\u5931\u65F6\u4ECD\u80FD\u5378\u8FC7\u671F\u6E05\u5355\u9879(Demeter/\u5B8C\u6574\u5951\u7EA6)\u3002\n */\nfunction collectDeployedPackUuids(\n bdsRoot: string,\n levelName: string\n): { 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 const liveBp = readPackManifestHeader(deployedBpDir(bdsRoot, levelName));\n const liveRp = readPackManifestHeader(deployedRpDir(bdsRoot, levelName));\n if (liveBp?.uuid) bp.add(liveBp.uuid);\n if (liveRp?.uuid) rp.add(liveRp.uuid);\n return { bp, rp };\n}\n\n/**\n * \u679A\u4E3E\u672C\u673A packages,\u8FD4\u56DE folderId \u2192 \u5143\u6570\u636E\u3002\n * \u4EC5\u542B\u6709 sapi/src/index.ts \u7684\u6A21\u5757\u4F1A\u8FDB\u5165 BP bundle \u5019\u9009\u3002\n */\nexport async function scanLocalModules(): Promise<\n Array<{\n folderId: string;\n logicalId: string;\n version: string;\n enabled: boolean;\n hasSapi: boolean;\n hasResourcePack: boolean;\n fingerprint: string;\n entryPath: string | null;\n }>\n> {\n const dir = packagesDir();\n if (!existsSync(dir)) return [];\n const lock = (readJson<ModuleLock>(lockPath()) ?? { version: 1, modules: {} }) as ModuleLock;\n const cat = (readJson<Catalog>(catalogPath()) ?? {}) as Catalog;\n const defaults = new Map<string, boolean>();\n if (Array.isArray(cat.modules)) {\n for (const m of cat.modules) {\n const id = typeof m.id === \"string\" ? m.id : \"\";\n if (!id) continue;\n /* \u4E0E db-server \u5951\u7EA6\u4E00\u81F4:enabledByDefault !== false(\u7F3A\u7701 true) \u2014 LSP */\n defaults.set(id, m.enabledByDefault !== false);\n }\n }\n\n const entries = await fs.readdir(dir, { withFileTypes: true });\n const out: Array<{\n folderId: string;\n logicalId: string;\n version: string;\n enabled: boolean;\n hasSapi: boolean;\n hasResourcePack: boolean;\n fingerprint: string;\n entryPath: string | null;\n }> = [];\n\n for (const e of entries) {\n if (e.name.startsWith(\".\")) continue;\n const folderId = e.name;\n const modPath = path.join(dir, folderId);\n // Dirent.isDirectory() \u5BF9\u300C\u6307\u5411\u76EE\u5F55\u7684 symlink\u300D\u5728 Linux \u4E3A false\uFF1B\u7528 stat \u8DDF\u968F\u94FE\u63A5\n try {\n const st = await fs.stat(modPath);\n if (!st.isDirectory()) continue;\n } catch {\n continue;\n }\n const manifestPath = path.join(modPath, \"sapi\", \"manifest.json\");\n const entryPath = path.join(modPath, \"sapi\", \"src\", \"index.ts\");\n let logicalId = folderId;\n let version = \"0.0.0\";\n if (existsSync(manifestPath)) {\n try {\n const man = JSON.parse(await fs.readFile(manifestPath, \"utf8\")) as PackManifestLite;\n if (typeof man.id === \"string\" && man.id) logicalId = man.id;\n if (typeof man.version === \"string\" && man.version) version = man.version;\n else if (typeof man.schemaVersion === \"number\") version = `schema-${man.schemaVersion}`;\n } catch {\n /* keep defaults */\n }\n }\n const hasSapi = existsSync(entryPath);\n const hasResourcePack = existsSync(path.join(modPath, \"resource_pack\"));\n const fingerprint = await dirFingerprint(modPath);\n const enabled = isModuleEnabled(logicalId, lock, defaults);\n out.push({\n folderId,\n logicalId,\n version,\n enabled,\n hasSapi,\n hasResourcePack,\n fingerprint,\n entryPath: hasSapi ? entryPath : null,\n });\n }\n out.sort((a, b) => a.folderId.localeCompare(b.folderId));\n return out;\n}\n\n/** \u4ECE\u672C\u673A\u72B6\u6001 + \u5DF2\u6709 UUID \u5408\u6210 desired catalog\u3002\n * UUID \u4F18\u5148:deployed catalog \u2192 \u672C\u5730 build manifest \u2192 \u65B0\u5EFA\u968F\u673A\u3002\n */\nexport async function computeDesiredCatalog(opts?: {\n bpUuid?: string;\n rpUuid?: string | null;\n bpVersion?: [number, number, number];\n rpVersion?: [number, number, number] | null;\n bpModuleUuid?: string;\n rpModuleUuid?: string;\n}): Promise<DeployCatalog> {\n const mods = await scanLocalModules();\n const modules: Record<string, DeployCatalogModule> = {};\n let anyRp = false;\n for (const m of mods) {\n /* catalog \u8BB0\u5F55\u5168\u90E8\u5DF2\u5B89\u88C5\u6A21\u5757\u7684\u542F\u505C\u4E0E\u6307\u7EB9,\u4FBF\u4E8E diff \u88C5\u5378/\u7981\u7528 */\n modules[m.folderId] = {\n logicalId: m.logicalId,\n enabled: m.enabled,\n version: m.version,\n fingerprint: m.fingerprint,\n hasResourcePack: m.hasResourcePack,\n };\n if (m.enabled && m.hasResourcePack) anyRp = true;\n }\n\n const localBp = readPackManifestHeader(bpOut());\n const localRp = readPackManifestHeader(rpOut());\n const bpUuid = opts?.bpUuid ?? localBp?.uuid ?? crypto.randomUUID();\n const bpVersion = opts?.bpVersion ?? localBp?.version ?? DEFAULT_PACK_VERSION;\n const bpModuleUuid = opts?.bpModuleUuid ?? localBp?.moduleUuid;\n let rpUuid: string | null = null;\n let rpVersion: [number, number, number] | null = null;\n let rpModuleUuid: string | undefined;\n if (anyRp) {\n rpUuid = opts?.rpUuid ?? localRp?.uuid ?? crypto.randomUUID();\n rpVersion = opts?.rpVersion ?? localRp?.version ?? DEFAULT_PACK_VERSION;\n rpModuleUuid = opts?.rpModuleUuid ?? localRp?.moduleUuid;\n }\n\n return {\n schemaVersion: 1,\n bpUuid,\n rpUuid,\n bpVersion,\n rpVersion,\n ...(bpModuleUuid ? { bpModuleUuid } : {}),\n ...(rpModuleUuid ? { rpModuleUuid } : {}),\n generatedAt: Date.now(),\n modules,\n };\n}\n\nexport function readDeployedCatalog(bdsRoot: string, levelName: string): DeployCatalog | null {\n const file = deployedCatalogPath(bdsRoot, levelName);\n if (!existsSync(file)) return null;\n try {\n return JSON.parse(readFileSync(file, \"utf8\")) as DeployCatalog;\n } catch {\n return null;\n }\n}\n\n/** \u6BD4\u8F83\u952E:\u6A21\u5757\u96C6\u5408 + enabled/version/fingerprint/hasRP + bp/rp uuid */\nexport function catalogsEqual(a: DeployCatalog, b: DeployCatalog): boolean {\n if (a.bpUuid !== b.bpUuid) return false;\n if ((a.rpUuid ?? null) !== (b.rpUuid ?? null)) return false;\n const aKeys = Object.keys(a.modules).sort();\n const bKeys = Object.keys(b.modules).sort();\n if (aKeys.length !== bKeys.length) return false;\n for (let i = 0; i < aKeys.length; i++) {\n if (aKeys[i] !== bKeys[i]) return false;\n }\n for (const k of aKeys) {\n const x = a.modules[k]!;\n const y = b.modules[k]!;\n if (\n x.logicalId !== y.logicalId ||\n x.enabled !== y.enabled ||\n x.version !== y.version ||\n x.fingerprint !== y.fingerprint ||\n x.hasResourcePack !== y.hasResourcePack\n ) {\n return false;\n }\n }\n /* \u4E16\u754C\u6E05\u5355\u662F\u5426\u4ECD\u542B uuid \u2014 \u8C03\u7528\u65B9\u989D\u5916\u68C0\u67E5 */\n return true;\n}\n\n/** \u4E16\u754C enable-list \u67E5\u8BE2 \u2014 \u76F4\u8FDE pack-manager-lib\uFF08DRY/DIP\uFF0C\u4E0E CLI has-pack \u540C\u5951\u7EA6\uFF09 */\nfunction worldPackListHas(bdsRoot: string, levelName: string, kind: \"behavior\" | \"resource\", uuid: string): boolean {\n return pmWorldPackListHas(bdsWorldsDir(bdsRoot), levelName, kind, uuid);\n}\n\n/** esbuild \u805A\u5408\u542F\u7528\u6A21\u5757 \u2192 assemble BP + RP(\u82E5\u6709) */\nexport async function buildPacks(desired?: DeployCatalog): Promise<DeployCatalog> {\n await fs.mkdir(buildRoot(), { recursive: true });\n const catalog = desired ?? (await computeDesiredCatalog());\n packLog(`building BP/RP (modules=${Object.keys(catalog.modules).length})\u2026`);\n\n /* \u5355\u6B21\u626B\u63CF:SAPI \u5165\u53E3 + RP \u76EE\u5F55(DRY,\u907F\u514D listEnabled* \u91CD\u590D fingerprint) */\n const mods = await scanLocalModules();\n const entries = mods.filter((m) => m.enabled && m.entryPath).map((m) => m.entryPath!);\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(packagesDir(), m.folderId, \"resource_pack\");\n }\n\n const { build } = await import(\"esbuild\");\n const outFile = path.join(bpSrc(), \"scripts\", \"main.js\");\n await fs.mkdir(path.dirname(outFile), { recursive: true });\n if (entries.length === 0) {\n await fs.writeFile(outFile, \"/* no modules enabled */\\n\", \"utf8\");\n packLog(\"no enabled SAPI modules \u2014 empty main.js\", \"warn\");\n } else {\n const sdkRoot = resolveSdkPackageRoot();\n packLog(`SDK root: ${sdkRoot}`);\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 // \u907F\u514D\u8BFB\u53D6\u6A21\u5757\u5185\u6B8B\u7F3A\u7684 extends\uFF08\u5982 ../../../sdk/@sfmc-sdk/tsconfig.json\uFF09\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 packLog(`esbuild bundled ${entries.length} entr(y/ies)`, \"success\");\n }\n\n try {\n await assembleBehaviorPack({\n srcDir: bpSrc(),\n outDir: bpOut(),\n projectName: BP_NAME,\n version: catalog.bpVersion,\n description: \"ScriptsForMinecraftServer aggregated behavior pack\",\n uuid: catalog.bpUuid,\n ...(catalog.bpModuleUuid ? { moduleUuid: catalog.bpModuleUuid } : {}),\n });\n } catch (e) {\n throw new Error(`assemble-bp failed: ${(e as Error).message}`);\n }\n packLog(`assembled BP uuid=${catalog.bpUuid}`, \"success\");\n\n if (Object.keys(rpDirs).length > 0 && catalog.rpUuid) {\n /* OCP:\u663E\u5F0F module\u2192rpDir map \u76F4\u4F20\u5E93\uFF0C\u4E0D\u518D\u4E34\u65F6\u955C\u50CF\u6574\u6811 / \u843D\u76D8 JSON */\n try {\n await assembleResourcePack({\n moduleResourceDirs: rpDirs,\n outDir: rpOut(),\n projectName: RP_NAME,\n version: catalog.rpVersion ?? DEFAULT_PACK_VERSION,\n description: \"ScriptsForMinecraftServer aggregated resource pack\",\n uuid: catalog.rpUuid,\n ...(catalog.rpModuleUuid ? { moduleUuid: catalog.rpModuleUuid } : {}),\n });\n } catch (e) {\n throw new Error(`assemble-rp failed: ${(e as Error).message}`);\n }\n packLog(`assembled RP uuid=${catalog.rpUuid} (${Object.keys(rpDirs).length} modules)`, \"success\");\n } else {\n /* \u65E0 RP:\u6E05\u7406\u65E7\u4EA7\u7269,catalog.rpUuid \u7F6E\u7A7A */\n await fs.rm(rpOut(), { recursive: true, force: true });\n catalog.rpUuid = null;\n catalog.rpVersion = null;\n packLog(\"no enabled resource packs \u2014 RP skipped\");\n }\n\n /* \u628A catalog \u5199\u5230\u672C\u5730 BP \u4EA7\u7269,deploy \u65F6\u4E00\u5E76\u62F7\u8D70 */\n catalog.generatedAt = Date.now();\n writeJson(path.join(bpOut(), DEPLOY_CATALOG_NAME), catalog);\n return catalog;\n}\n\n/** \u90E8\u7F72\u5230\u4E16\u754C + enable \u6E05\u5355 + Script API permission */\nexport async function deployPacks(catalog: DeployCatalog): Promise<void> {\n const { bdsRoot, levelName } = resolveBdsContext();\n if (!existsSync(bpOut())) {\n throw new Error(`BP not built at ${bpOut()}. Run build first.`);\n }\n\n /* \u5FC5\u987B\u5728 deploy/clear-rp \u4E4B\u524D\u91C7\u96C6 \u2014 \u6E05\u76EE\u5F55\u540E\u65E0\u6CD5\u518D\u8BFB manifest */\n const previous = collectDeployedPackUuids(bdsRoot, levelName);\n try {\n await deployToBDS({\n bdsRoot,\n levelName,\n behaviorPackSrc: bpOut(),\n bpName: BP_NAME,\n rpName: RP_NAME,\n ...(catalog.rpUuid && existsSync(rpOut())\n ? { resourcePackSrc: rpOut() }\n : { clearResourcePack: true }),\n });\n } catch (e) {\n throw new Error(`deploy failed: ${(e as Error).message}`);\n }\n packLog(`deployed to worlds/${levelName}`, \"success\");\n\n /* \u786E\u4FDD catalog \u5728\u90E8\u7F72\u540E\u7684 BP \u5185(deploy \u4F1A\u62F7\u8D1D\u6574\u4E2A\u76EE\u5F55) */\n writeJson(path.join(deployedBpDir(bdsRoot, levelName), DEPLOY_CATALOG_NAME), catalog);\n\n const worldsDir = bdsWorldsDir(bdsRoot);\n try {\n await enablePackInWorld({\n worldsDir,\n levelName,\n kind: \"behavior\",\n packUuid: catalog.bpUuid,\n version: catalog.bpVersion,\n });\n } catch (e) {\n throw new Error(`enable BP failed: ${(e as Error).message}`);\n }\n packLog(`enabled behavior pack ${catalog.bpUuid} in world list`, \"success\");\n\n if (catalog.rpUuid && catalog.rpVersion) {\n try {\n await enablePackInWorld({\n worldsDir,\n levelName,\n kind: \"resource\",\n packUuid: catalog.rpUuid,\n version: catalog.rpVersion,\n });\n } catch (e) {\n throw new Error(`enable RP failed: ${(e as Error).message}`);\n }\n packLog(`enabled resource pack ${catalog.rpUuid} in world list`, \"success\");\n }\n\n /* \u5378\u6389\u8FC7\u671F RP:UUID \u8F6E\u6362 / \u4E0D\u518D\u63D0\u4F9B RP / catalog \u7F3A\u5931\u4F46\u78C1\u76D8\u4ECD\u6709\u65E7\u5305 */\n for (const staleRp of previous.rp) {\n if (staleRp === (catalog.rpUuid ?? null)) continue;\n try {\n await disablePackInWorld({\n worldsDir,\n levelName,\n kind: \"resource\",\n packUuid: staleRp,\n version: DEFAULT_PACK_VERSION,\n });\n packLog(`disabled stale resource pack ${staleRp}`, \"success\");\n } catch (e) {\n packLog(`disable stale RP ${staleRp} failed: ${(e as Error).message}`, \"warn\");\n }\n }\n\n /* \u5378\u6389\u8FC7\u671F BP(uuid \u8F6E\u6362) */\n for (const staleBp of previous.bp) {\n if (staleBp === catalog.bpUuid) continue;\n try {\n await disablePackInWorld({\n worldsDir,\n levelName,\n kind: \"behavior\",\n packUuid: staleBp,\n version: DEFAULT_PACK_VERSION,\n });\n packLog(`disabled stale behavior pack ${staleBp}`, \"success\");\n } catch (e) {\n packLog(`disable stale BP ${staleBp} failed: ${(e as Error).message}`, \"warn\");\n }\n }\n\n try {\n const wrote = await ensureConfigPermission(bdsRoot, catalog.bpUuid);\n const permRel = path.relative(bdsRoot, configPermissionPath(bdsRoot, catalog.bpUuid));\n packLog(wrote ? `wrote ${permRel}` : `${permRel} already exists \u2014 skipped`);\n } catch (e) {\n throw new Error(`ensure-permission failed: ${(e as Error).message}`);\n }\n}\n\nexport function formatPackLoadInfo(catalog: DeployCatalog, rebuilt: boolean): string {\n const mods = Object.entries(catalog.modules);\n const enabled = mods.filter(([, m]) => m.enabled);\n const disabled = mods.filter(([, m]) => !m.enabled);\n const lines = [\n `pack load ${rebuilt ? \"(rebuilt)\" : \"(catalog match \u2014 skip rebuild)\"}`,\n ` BP ${catalog.bpUuid} v${catalog.bpVersion.join(\".\")}`,\n catalog.rpUuid\n ? ` RP ${catalog.rpUuid} v${(catalog.rpVersion ?? DEFAULT_PACK_VERSION).join(\".\")}`\n : ` RP (none)`,\n ` modules: ${enabled.length} enabled / ${disabled.length} disabled / ${mods.length} installed`,\n ];\n for (const [folderId, m] of enabled.sort((a, b) => a[0].localeCompare(b[0]))) {\n lines.push(` \u25CF ${folderId} (${m.logicalId}) ${m.version}${m.hasResourcePack ? \" +rp\" : \"\"}`);\n }\n for (const [folderId, m] of disabled.sort((a, b) => a[0].localeCompare(b[0]))) {\n lines.push(` \u25CB ${folderId} (${m.logicalId}) disabled`);\n }\n return lines.join(\"\\n\");\n}\n\nfunction reusePackIds(deployed: DeployCatalog): {\n bpUuid?: string;\n rpUuid?: string | null;\n bpVersion?: [number, number, number];\n rpVersion?: [number, number, number] | null;\n bpModuleUuid?: string;\n rpModuleUuid?: string;\n} {\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}\n\n/**\n * BDS \u542F\u52A8\u524D\u95F8\u95E8:catalog \u4E0D\u4E00\u81F4\u5219\u6574\u5305\u91CD\u7F16\u90E8\u7F72;\u5931\u8D25\u629B\u9519,\u7981\u6B62\u542F\u52A8\u3002\n */\nexport async function ensurePacksReady(): Promise<PackEnsureResult> {\n const { bdsRoot, levelName } = resolveBdsContext();\n packLog(`preflight: checking packs for ${bdsRoot} / ${levelName}`);\n\n const deployed = readDeployedCatalog(bdsRoot, levelName);\n /* \u590D\u7528\u5DF2\u90E8\u7F72 UUID,\u907F\u514D\u65E0\u8C13\u8F6E\u6362 */\n let desired = await computeDesiredCatalog(deployed ? reusePackIds(deployed) : undefined);\n\n /* \u82E5 desired \u9700\u8981 RP \u4F46\u590D\u7528\u4E86\u65E7 null rpUuid,\u8865\u4E00\u4E2A */\n const needsRp = Object.values(desired.modules).some((m) => m.enabled && m.hasResourcePack);\n if (needsRp && !desired.rpUuid) {\n desired = await computeDesiredCatalog({\n bpUuid: desired.bpUuid,\n bpVersion: desired.bpVersion,\n ...(desired.bpModuleUuid ? { bpModuleUuid: desired.bpModuleUuid } : {}),\n rpUuid: crypto.randomUUID(),\n rpVersion: DEFAULT_PACK_VERSION,\n });\n }\n if (!needsRp) {\n desired.rpUuid = null;\n desired.rpVersion = null;\n }\n\n let needRebuild = !deployed || !catalogsEqual(desired, deployed);\n if (!needRebuild && deployed) {\n if (!worldPackListHas(bdsRoot, levelName, \"behavior\", deployed.bpUuid)) needRebuild = true;\n if (deployed.rpUuid && !worldPackListHas(bdsRoot, levelName, \"resource\", deployed.rpUuid)) {\n needRebuild = true;\n }\n if (!hasConfigPermission(bdsRoot, deployed.bpUuid)) {\n /* permission \u7F3A\u5931\u53EA\u8865\u5199,\u4E0D\u5F3A\u5236\u6574\u5305\u91CD\u7F16 */\n try {\n const wrote = await ensureConfigPermission(bdsRoot, deployed.bpUuid);\n const permRel = path.relative(bdsRoot, configPermissionPath(bdsRoot, deployed.bpUuid));\n packLog(wrote ? `wrote ${permRel}` : `${permRel} already exists \u2014 skipped`);\n } catch (e) {\n throw new Error(`ensure-permission failed: ${(e as Error).message}`);\n }\n }\n }\n\n let rebuilt = false;\n if (needRebuild) {\n packLog(\"catalog mismatch \u2014 rebuilding packs\u2026\", \"warn\");\n desired = await buildPacks(desired);\n await deployPacks(desired);\n rebuilt = true;\n } else {\n packLog(\"catalog match \u2014 skip rebuild\", \"success\");\n }\n\n const summary = formatPackLoadInfo(desired, rebuilt);\n for (const line of summary.split(\"\\n\")) packLog(line, rebuilt ? \"success\" : \"info\");\n\n return {\n rebuilt,\n skipped: !rebuilt,\n catalog: desired,\n bdsRoot,\n levelName,\n summary,\n };\n}\n\n/* \u2500\u2500 CLI \u547D\u4EE4\u5B9E\u73B0 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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\nexport async function cmdPackBuild(_args: string[]): Promise<CliResult> {\n try {\n const cat = await buildPacks();\n return okResult(c.green(t(\"pack.built\", { path: bpOut() })) + `\\n` + formatPackLoadInfo(cat, true) + \"\\n\");\n } catch (e) {\n packLog((e as Error).message, \"error\");\n return failResult(c.red(t(\"pack.buildFailed\", { message: (e as Error).message })));\n }\n}\n\nexport async function cmdPackDeploy(_args: string[]): Promise<CliResult> {\n try {\n const localCatFile = path.join(bpOut(), DEPLOY_CATALOG_NAME);\n let cat: DeployCatalog;\n if (existsSync(localCatFile)) {\n cat = JSON.parse(await fs.readFile(localCatFile, \"utf8\")) as DeployCatalog;\n } else {\n cat = await buildPacks();\n }\n await deployPacks(cat);\n return okResult(c.green(t(\"pack.deployed\")) + \"\\n\" + formatPackLoadInfo(cat, true) + \"\\n\");\n } catch (e) {\n packLog((e as Error).message, \"error\");\n return failResult(c.red(t(\"pack.deployFailed\", { message: (e as Error).message })));\n }\n}\n\nexport async function cmdPackStatus(_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 const match = deployed ? catalogsEqual(desired, deployed) : false;\n const permPath = deployed ? configPermissionPath(bdsRoot, deployed.bpUuid) : null;\n const lines = [\n c.bold(\"\\nPack status\"),\n ` bds : ${bdsRoot}`,\n ` level : ${levelName}`,\n ` catalog : ${match ? c.green(\"in sync\") : c.yellow(deployed ? \"mismatch \u2014 will rebuild on start\" : \"missing\")}`,\n ` BP dir : ${deployedBpDir(bdsRoot, levelName)} ${existsSync(deployedBpDir(bdsRoot, levelName)) ? c.green(\"\u2713\") : c.red(\"\u2717\")}`,\n ` RP dir : ${deployedRpDir(bdsRoot, levelName)} ${existsSync(deployedRpDir(bdsRoot, levelName)) ? c.green(\"\u2713\") : c.dim(\"\u2014\")}`,\n ` permission : ${permPath ? (existsSync(permPath) ? c.green(permPath) : c.yellow(\"missing\")) : c.dim(\"n/a\")}`,\n ];\n if (deployed) {\n lines.push(` BP uuid : ${deployed.bpUuid}`);\n if (deployed.rpUuid) lines.push(` RP uuid : ${deployed.rpUuid}`);\n lines.push(\n ` world BP : ${worldPackListHas(bdsRoot, levelName, \"behavior\", deployed.bpUuid) ? c.green(\"listed\") : c.red(\"not listed\")}`\n );\n if (deployed.rpUuid) {\n lines.push(\n ` world RP : ${worldPackListHas(bdsRoot, levelName, \"resource\", deployed.rpUuid) ? c.green(\"listed\") : c.red(\"not listed\")}`\n );\n }\n }\n lines.push(formatPackLoadInfo(desired, false));\n return lines.join(\"\\n\") + \"\\n\";\n } catch (e) {\n return c.red(t(\"pack.statusFailed\", { message: (e as Error).message }));\n }\n}\n\nexport async function cmdPackList(_args: string[]): Promise<string> {\n try {\n const { bdsRoot, levelName } = resolveBdsContext();\n const mods = await scanLocalModules();\n const lines = [c.bold(\"\\nModules / resource packs\"), c.dim(` ${packagesDir()}`)];\n for (const m of mods) {\n const mark = m.enabled ? c.green(\"\u25CF\") : c.dim(\"\u25CB\");\n lines.push(\n ` ${mark} ${m.folderId.padEnd(24)} ${m.logicalId.padEnd(24)} ${m.enabled ? \"on \" : \"off\"} ${m.hasResourcePack ? \"+rp\" : \" \"} ${m.version}`\n );\n }\n const worldsDir = bdsWorldsDir(bdsRoot);\n lines.push(c.bold(\"\\nWorld enable lists\"));\n for (const kind of [\"behavior\", \"resource\"] as const) {\n const arr = readWorldPackList(worldsDir, levelName, kind);\n if (!arr.length) lines.push(c.dim(` ${kind}: (empty)`));\n for (const e of arr) {\n lines.push(` ${kind}: ${e.pack_id} v${(e.version ?? []).join(\".\")}`);\n }\n }\n return lines.join(\"\\n\") + \"\\n\";\n } catch (e) {\n return c.red(t(\"pack.listFailed\", { message: (e as Error).message }));\n }\n}\n\nexport async function cmdPackEnableDisable(action: \"enable\" | \"disable\", args: string[]): Promise<string> {\n try {\n const kind = (args[0] === \"resource\" || args[0] === \"rp\" ? \"resource\" : \"behavior\") as \"behavior\" | \"resource\";\n const { bdsRoot, levelName } = resolveBdsContext();\n const deployed = readDeployedCatalog(bdsRoot, levelName);\n if (!deployed) return c.red(t(\"pack.noCatalog\"));\n const uuid = kind === \"behavior\" ? deployed.bpUuid : deployed.rpUuid;\n const version = kind === \"behavior\" ? deployed.bpVersion : deployed.rpVersion;\n if (!uuid || !version) return c.red(t(\"pack.noUuid\", { kind }));\n const worldsDir = bdsWorldsDir(bdsRoot);\n try {\n const opts = { worldsDir, levelName, kind, packUuid: uuid, version };\n if (action === \"enable\") await enablePackInWorld(opts);\n else await disablePackInWorld(opts);\n } catch (e) {\n return c.red(t(\"pack.actionFailed\", { action, detail: (e as Error).message }));\n }\n packLog(`${action}d ${kind} pack ${uuid}`, \"success\");\n return c.green(\n action === \"enable\"\n ? t(\"pack.enabledOk\", { kind, uuid })\n : t(\"pack.disabledOk\", { kind, uuid })\n );\n } catch (e) {\n return c.red(t(\"pack.actionErr\", { action, message: (e as Error).message }));\n }\n}\n\n/* CLI \u8868\u9762\u5DF2\u6536\u655B\uFF1A\u6A21\u5757\u7528 mod build/reload\uFF1B\u7B2C\u4E09\u65B9\u5305\u542F\u505C\u7528 addon/packs\u3002\n * \u6B64\u5904\u4FDD\u7559 cmdPackBuild / cmdPackDeploy \u4F9B ensurePacksReady \u4E0E mod reload \u8C03\u7528\u3002 */\n\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * pack-lifecycle.ts \u2014 \u884C\u4E3A\u5305/\u8D44\u6E90\u5305\u88C5\u8F7D\u751F\u547D\u5468\u671F\n *\n * \u804C\u8D23:\n * - \u8BA1\u7B97\u672C\u673A desired deploy-catalog(\u542F\u7528\u6A21\u5757 + fingerprint)\n * - \u4E0E\u4E16\u754C BP \u5185 sfmc-deploy-catalog.json \u6BD4\u5BF9\n * - \u4E0D\u4E00\u81F4\u5219\u6574\u5305 build + deploy + \u5199\u4E16\u754C\u6E05\u5355 + Script API permission\n * - \u542F\u52A8\u524D ensurePacksReady;\u65E5\u5FD7\u4E00\u5F8B\u8D70 source=`pack`\n */\n\nimport {\n configPath,\n DEFAULT_DB_CONFIG,\n modulePath,\n readJson,\n writeJson,\n type BdsUpdaterConfig,\n type Catalog,\n type DBConfig,\n type ModuleLock,\n} from \"@sfmc-bds/sdk/node/config\";\nimport { existsSync, readFileSync } from \"node:fs\";\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { pushLog } from \"./logs.js\";\nimport { dirFingerprint } from \"./module-fingerprint.js\";\nimport { failResult, okResult, type CliResult } from \"./cli-result.js\";\nimport { t } from \"./i18n/index.js\";\nimport {\n assembleBehaviorPack,\n assembleResourcePack,\n bdsWorldLevelDir,\n bdsWorldsDir,\n configPermissionPath,\n deployToBDS,\n disablePackInWorld,\n enablePackInWorld,\n ensureConfigPermission,\n hasConfigPermission,\n readLevelNameSync,\n readPackManifestHeader,\n readWorldPackList,\n worldPackListHas as pmWorldPackListHas,\n BASELINE_BEDROCK_DEPENDENCIES,\n negotiateBedrockDependencies,\n NATIVE_BEDROCK_SCRIPT_MODULES,\n type PackManifestDependency,\n} from \"@sfmc-bds/bds-tools/pack-manager-lib\";\nimport { ROOT, PACKAGES_DIR, resolveSdkPackageRoot, getRoot } from \"./runtime.js\";\nimport { c } from \"./theme.js\";\n\nexport const BP_NAME = \"sfmc-modules\";\nexport const RP_NAME = \"sfmc-modules-rp\";\nexport const DEPLOY_CATALOG_NAME = \"sfmc-deploy-catalog.json\";\nexport const DEFAULT_PACK_VERSION: [number, number, number] = [1, 0, 0];\n\n/** \u5C06 @sfmc/sdk \u4E0E @sfmc-bds/sdk \u5B50\u8DEF\u5F84\u89E3\u6790\u5230 SDK \u5305\u5185\u771F\u5B9E\u6587\u4EF6\uFF0C\u5E76\u6CE8\u5165 sfmc:host \u5F15\u5BFC\u5165\u53E3 */\nexport function createSdkResolvePlugin(sdkRoot: string, dbPort: number): 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:host$/ }, () => ({\n path: \"sfmc:host\",\n namespace: \"sfmc-host\",\n }));\n build.onLoad({ filter: /.*/, namespace: \"sfmc-host\" }, () => ({\n contents: [\n 'import { installHostBootstrap } from \"@sfmc-bds/sdk/module-loader/install\";',\n `installHostBootstrap({ dbServerUrl: ${JSON.stringify(`http://127.0.0.1:${dbPort}`)} });`,\n ].join(\"\\n\"),\n loader: \"ts\",\n }));\n\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\n const importerNorm = (args.importer || \"\").replace(/\\\\/g, \"/\");\n const sapiIdx = importerNorm.indexOf(\"/sapi/\");\n if (sapiIdx !== -1 && !importerNorm.includes(\"@sfmc-sdk\") && !importerNorm.includes(\"@sfmc/sdk\")) {\n const sapiDir = importerNorm.slice(0, sapiIdx + \"/sapi\".length);\n const manifestFile = path.join(sapiDir, \"manifest.json\");\n let logicalId = \"\";\n let configKey = \"\";\n if (existsSync(manifestFile)) {\n try {\n const man = JSON.parse(readFileSync(manifestFile, \"utf8\")) as { id?: string; configKey?: string };\n if (man.id) logicalId = man.id;\n if (man.configKey) configKey = man.configKey;\n } catch {}\n }\n if (!logicalId) {\n const rootDir = importerNorm.slice(0, sapiIdx);\n logicalId = path.basename(rootDir).replace(/^sfmc-module-/, \"\");\n configKey = logicalId;\n }\n if (sub === \"sapi/db\") {\n return {\n path: `sfmc-scoped:db?mod=${encodeURIComponent(logicalId)}`,\n namespace: \"sfmc-scoped-db\",\n };\n }\n if (sub === \"sapi/config\") {\n return {\n path: `sfmc-scoped:config?cfg=${encodeURIComponent(configKey)}`,\n namespace: \"sfmc-scoped-config\",\n };\n }\n if (sub === \"sapi/service\") {\n return {\n path: `sfmc-scoped:service?mod=${encodeURIComponent(logicalId)}`,\n namespace: \"sfmc-scoped-service\",\n };\n }\n }\n\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 // \u865A\u62DF\u5BBF\u4E3B\u4E2D\u7684 SDK \u5BFC\u5165\u4E5F\u6536\u655B\u5230\u6807\u51C6\u6587\u4EF6\u547D\u540D\u7A7A\u95F4\u3002\n return { path: resolved, namespace: \"file\" };\n });\n\n build.onLoad({ filter: /.*/, namespace: \"sfmc-scoped-db\" }, (args) => {\n const u = new URL(args.path);\n const mod = u.searchParams.get(\"mod\") || \"\";\n return {\n contents: [\n 'import { getDbClient } from \"@sfmc-bds/sdk/sapi/db\";',\n 'export * from \"@sfmc-bds/sdk/sapi/db\";',\n 'export const db = new Proxy({}, {',\n ' get(_t, prop) {',\n ` const c = getDbClient(${JSON.stringify(mod)});`,\n ' const val = (c as any)[prop];',\n ' return typeof val === \"function\" ? val.bind(c) : val;',\n ' }',\n '});',\n ].join(\"\\n\"),\n loader: \"ts\",\n resolveDir: sdkRoot,\n };\n });\n\n build.onLoad({ filter: /.*/, namespace: \"sfmc-scoped-config\" }, (args) => {\n const u = new URL(args.path);\n const cfg = u.searchParams.get(\"cfg\") || \"\";\n return {\n contents: [\n 'import { getConfigClient } from \"@sfmc-bds/sdk/sapi/config\";',\n 'export * from \"@sfmc-bds/sdk/sapi/config\";',\n 'export const config = new Proxy({}, {',\n ' get(_t, prop) {',\n ` const c = getConfigClient(${JSON.stringify(cfg)});`,\n ' const val = (c as any)[prop];',\n ' return typeof val === \"function\" ? val.bind(c) : val;',\n ' }',\n '});',\n ].join(\"\\n\"),\n loader: \"ts\",\n resolveDir: sdkRoot,\n };\n });\n\n build.onLoad({ filter: /.*/, namespace: \"sfmc-scoped-service\" }, (args) => {\n const u = new URL(args.path);\n const mod = u.searchParams.get(\"mod\") || \"\";\n return {\n contents: [\n 'import { getServiceClient } from \"@sfmc-bds/sdk/sapi/service\";',\n 'export * from \"@sfmc-bds/sdk/sapi/service\";',\n 'export const service = new Proxy({}, {',\n ' get(_t, prop) {',\n ` const c = getServiceClient(${JSON.stringify(mod)});`,\n ' const val = (c as any)[prop];',\n ' return typeof val === \"function\" ? val.bind(c) : val;',\n ' }',\n '});',\n ].join(\"\\n\"),\n loader: \"ts\",\n resolveDir: sdkRoot,\n };\n });\n },\n };\n}\n\nexport function buildRoot(): string {\n /* \u4E0E\u6536\u4EF6\u7BB1\u540C\u6811\uFF1Apacks/_build\uFF08_ \u524D\u7F00\u4E0D\u4F1A\u88AB inbox \u626B\u63CF\uFF09 */\n return path.join(ROOT, \"packs\", \"_build\");\n}\nexport function bpSrc(): string {\n return path.join(buildRoot(), `${BP_NAME}-bp`);\n}\nexport function bpOut(): string {\n return path.join(buildRoot(), BP_NAME);\n}\nexport function rpOut(): string {\n return path.join(buildRoot(), RP_NAME);\n}\n\nexport interface DeployCatalogModule {\n logicalId: string;\n enabled: boolean;\n version: string;\n fingerprint: string;\n hasResourcePack: boolean;\n}\n\nexport interface DeployCatalog {\n schemaVersion: 1;\n dbPort: number;\n bpUuid: string;\n rpUuid: string | null;\n bpVersion: [number, number, number];\n rpVersion: [number, number, number] | null;\n bpModuleUuid?: string;\n rpModuleUuid?: string;\n generatedAt: number;\n sdkVersion?: string;\n dependencies?: PackManifestDependency[];\n modules: Record<string, DeployCatalogModule>;\n}\n\nexport interface PackEnsureResult {\n rebuilt: boolean;\n skipped: boolean;\n catalog: DeployCatalog;\n bdsRoot: string;\n levelName: string;\n summary: string;\n}\n\ninterface PackManifestLite {\n id?: string;\n version?: string;\n schemaVersion?: number;\n enabledByDefault?: boolean;\n name?: string;\n}\n\nfunction packLog(text: string, level: \"info\" | \"success\" | \"warn\" | \"error\" = \"info\"): void {\n pushLog(text, \"pack\", level);\n}\n\nfunction packagesDir(): string {\n return PACKAGES_DIR || path.join(ROOT, \"modules\", \"packages\");\n}\n\nfunction lockPath(): string {\n return modulePath(path.join(ROOT, \"modules\"), \"module-lock.json\");\n}\n\nfunction catalogPath(): string {\n return modulePath(path.join(ROOT, \"modules\"), \"catalog.json\");\n}\n\nfunction configuredDbPort(root: string): number {\n const configured = readJson<DBConfig>(configPath(root, \"db_config.json\"));\n const port = configured?.db_port ?? DEFAULT_DB_CONFIG.db_port ?? 3001;\n if (!Number.isInteger(port) || port < 1 || port > 65535) {\n throw new Error(`configs/db_config.json: db_port \u5FC5\u987B\u662F 1\u201365535 \u7684\u6574\u6570 (\u5F53\u524D ${port})`);\n }\n return port;\n}\n\n/** \u8BFB BDS \u8DEF\u5F84\u4E0E level-name\uFF08level \u6743\u5A01\uFF1Apack-manager-lib.readLevelNameSync\uFF0CDIP\uFF09 */\nexport function resolveBdsContext(root: string = getRoot()): { bdsRoot: string; levelName: string } {\n const cfg = (readJson<BdsUpdaterConfig>(configPath(root, \"bds_updater.json\")) ?? {}) as BdsUpdaterConfig;\n const rawBds = cfg.bds_path;\n if (!rawBds) {\n throw new Error(\"bds_path not configured. Run `sfmc init` first.\");\n }\n const bdsRoot = path.isAbsolute(rawBds) ? rawBds : path.resolve(root, rawBds);\n return { bdsRoot, levelName: readLevelNameSync(bdsRoot) };\n}\n\nexport function deployedBpDir(bdsRoot: string, levelName: string): string {\n return path.join(bdsWorldLevelDir(bdsRoot, levelName), \"behavior_packs\", BP_NAME);\n}\n\nexport function deployedRpDir(bdsRoot: string, levelName: string): string {\n return path.join(bdsWorldLevelDir(bdsRoot, levelName), \"resource_packs\", RP_NAME);\n}\n\nexport function deployedCatalogPath(bdsRoot: string, levelName: string): string {\n return path.join(deployedBpDir(bdsRoot, levelName), DEPLOY_CATALOG_NAME);\n}\n\n/** \u89E3\u6790\u542F\u7528\u72B6\u6001:lock \u4F18\u5148,\u5426\u5219 catalog.enabledByDefault(\u7F3A\u7701 true\u2194!==false),\u672A\u6536\u5F55\u6A21\u5757 false */\nfunction isModuleEnabled(logicalId: string, lock: ModuleLock, catalogDefaults: Map<string, boolean>): boolean {\n const st = lock.modules?.[logicalId];\n if (st && typeof st.enabled === \"boolean\") return st.enabled;\n return catalogDefaults.get(logicalId) ?? false;\n}\n\n/**\n * \u90E8\u7F72\u524D\u6536\u96C6\u4E16\u754C\u5185\u5DF2\u51FA\u73B0\u7684 BP/RP uuid\u3002\n * \u540C\u65F6\u8BFB deploy-catalog \u4E0E\u78C1\u76D8 manifest \u2014 catalog \u7F3A\u5931\u65F6\u4ECD\u80FD\u5378\u8FC7\u671F\u6E05\u5355\u9879(Demeter/\u5B8C\u6574\u5951\u7EA6)\u3002\n */\nfunction collectDeployedPackUuids(\n bdsRoot: string,\n levelName: string\n): { 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 const liveBp = readPackManifestHeader(deployedBpDir(bdsRoot, levelName));\n const liveRp = readPackManifestHeader(deployedRpDir(bdsRoot, levelName));\n if (liveBp?.uuid) bp.add(liveBp.uuid);\n if (liveRp?.uuid) rp.add(liveRp.uuid);\n return { bp, rp };\n}\n\n/**\n * \u4ECE\u6A21\u5757\u76EE\u5F55\u63D0\u53D6\u58F0\u660E\u7684 @minecraft/* \u539F\u751F\u4F9D\u8D56\u3002\n * \u4F18\u5148\u7EA7\uFF1A\n * 1. sapi/manifest.json \u7684 dependencies\uFF08\u6807\u51C6\u57FA\u5CA9\u6570\u7EC4\u6216\u952E\u503C\u5BF9\u6620\u5C04\uFF09\u4E0E minecraft \u5B57\u6BB5\uFF1B\n * 2. package.json \u7684 peerDependencies \u4E0E dependencies\uFF08\u4E0D\u542B devDependencies\uFF0C\u907F\u514D\u7C7B\u578B\u5305\u8BEF\u4F24\uFF09\u3002\n */\nexport async function extractModuleBedrockDependencies(modPath: string): Promise<PackManifestDependency[]> {\n const deps: PackManifestDependency[] = [];\n const seen = new Set<string>();\n\n const manifestPath = path.join(modPath, \"sapi\", \"manifest.json\");\n if (existsSync(manifestPath)) {\n try {\n const raw = JSON.parse(await fs.readFile(manifestPath, \"utf8\")) as Record<string, unknown>;\n if (Array.isArray(raw.dependencies)) {\n for (const d of raw.dependencies) {\n if (\n d &&\n typeof d === \"object\" &&\n typeof (d as { module_name?: unknown }).module_name === \"string\" &&\n (d as { module_name: string }).module_name.startsWith(\"@minecraft/\") &&\n NATIVE_BEDROCK_SCRIPT_MODULES.has((d as { module_name: string }).module_name)\n ) {\n const modName = (d as { module_name: string }).module_name;\n const ver = String((d as { version?: unknown }).version ?? \"1.0.0\");\n const uuid = typeof (d as { uuid?: unknown }).uuid === \"string\" ? (d as { uuid: string }).uuid : undefined;\n deps.push({ module_name: modName, version: ver, ...(uuid ? { uuid } : {}) });\n seen.add(modName);\n }\n }\n } else if (raw.dependencies && typeof raw.dependencies === \"object\") {\n for (const [modName, ver] of Object.entries(raw.dependencies as Record<string, unknown>)) {\n if (modName.startsWith(\"@minecraft/\") && !seen.has(modName) && NATIVE_BEDROCK_SCRIPT_MODULES.has(modName)) {\n deps.push({ module_name: modName, version: String(ver ?? \"1.0.0\") });\n seen.add(modName);\n }\n }\n }\n\n if (raw.minecraft && typeof raw.minecraft === \"object\") {\n const mc = raw.minecraft as Record<string, unknown>;\n const mcDeps = (Array.isArray(mc.dependencies) ? mc.dependencies : mc) as Record<string, unknown>;\n if (typeof mcDeps === \"object\" && !Array.isArray(mcDeps)) {\n for (const [modName, ver] of Object.entries(mcDeps)) {\n if (modName.startsWith(\"@minecraft/\") && !seen.has(modName) && NATIVE_BEDROCK_SCRIPT_MODULES.has(modName)) {\n deps.push({ module_name: modName, version: String(ver ?? \"1.0.0\") });\n seen.add(modName);\n }\n }\n }\n }\n } catch {\n /* ignore parse error */\n }\n }\n\n const pkgPath = path.join(modPath, \"package.json\");\n if (existsSync(pkgPath)) {\n try {\n const pkg = JSON.parse(await fs.readFile(pkgPath, \"utf8\")) as {\n peerDependencies?: Record<string, string>;\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n };\n const candidateMap = {\n ...(pkg.devDependencies ?? {}),\n ...(pkg.dependencies ?? {}),\n ...(pkg.peerDependencies ?? {}),\n };\n for (const [modName, ver] of Object.entries(candidateMap)) {\n if (modName.startsWith(\"@minecraft/\") && !seen.has(modName) && NATIVE_BEDROCK_SCRIPT_MODULES.has(modName)) {\n deps.push({ module_name: modName, version: ver });\n seen.add(modName);\n }\n }\n } catch {\n /* ignore */\n }\n }\n\n return deps;\n}\n\n/**\n * \u679A\u4E3E\u672C\u673A packages,\u8FD4\u56DE folderId \u2192 \u5143\u6570\u636E\u3002\n * \u4EC5\u542B\u6709 sapi/src/index.ts \u7684\u6A21\u5757\u4F1A\u8FDB\u5165 BP bundle \u5019\u9009\u3002\n */\nexport async function scanLocalModules(): Promise<\n Array<{\n folderId: string;\n logicalId: string;\n version: string;\n enabled: boolean;\n hasSapi: boolean;\n hasResourcePack: boolean;\n fingerprint: string;\n entryPath: string | null;\n declaredDependencies: PackManifestDependency[];\n }>\n> {\n const dir = packagesDir();\n if (!existsSync(dir)) return [];\n const lock = (readJson<ModuleLock>(lockPath()) ?? { version: 1, modules: {} }) as ModuleLock;\n const cat = (readJson<Catalog>(catalogPath()) ?? { version: 1, modules: [] }) as Catalog;\n const defaults = new Map<string, boolean>();\n if (Array.isArray(cat.modules)) {\n for (const m of cat.modules) {\n const id = typeof m.id === \"string\" ? m.id : \"\";\n if (!id) continue;\n /* \u4E0E db-server \u5951\u7EA6\u4E00\u81F4:enabledByDefault !== false(\u7F3A\u7701 true) \u2014 LSP */\n defaults.set(id, m.enabledByDefault !== false);\n }\n }\n\n const entries = await fs.readdir(dir, { withFileTypes: true });\n const out: Array<{\n folderId: string;\n logicalId: string;\n version: string;\n enabled: boolean;\n hasSapi: boolean;\n hasResourcePack: boolean;\n fingerprint: string;\n entryPath: string | null;\n declaredDependencies: PackManifestDependency[];\n }> = [];\n\n for (const e of entries) {\n if (e.name.startsWith(\".\")) continue;\n const folderId = e.name;\n const modPath = path.join(dir, folderId);\n // Dirent.isDirectory() \u5BF9\u300C\u6307\u5411\u76EE\u5F55\u7684 symlink\u300D\u5728 Linux \u4E3A false\uFF1B\u7528 stat \u8DDF\u968F\u94FE\u63A5\n try {\n const st = await fs.stat(modPath);\n if (!st.isDirectory()) continue;\n } catch {\n continue;\n }\n const manifestPath = path.join(modPath, \"sapi\", \"manifest.json\");\n const entryPath = path.join(modPath, \"sapi\", \"src\", \"index.ts\");\n let logicalId = folderId;\n let version = \"0.0.0\";\n if (existsSync(manifestPath)) {\n try {\n const man = JSON.parse(await fs.readFile(manifestPath, \"utf8\")) as PackManifestLite;\n if (typeof man.id === \"string\" && man.id) logicalId = man.id;\n if (typeof man.version === \"string\" && man.version) version = man.version;\n else if (typeof man.schemaVersion === \"number\") version = `schema-${man.schemaVersion}`;\n } catch {\n /* keep defaults */\n }\n }\n const hasSapi = existsSync(entryPath);\n const hasResourcePack = existsSync(path.join(modPath, \"resource_pack\"));\n const fingerprint = await dirFingerprint(modPath);\n const enabled = isModuleEnabled(logicalId, lock, defaults);\n const declaredDependencies = await extractModuleBedrockDependencies(modPath);\n out.push({\n folderId,\n logicalId,\n version,\n enabled,\n hasSapi,\n hasResourcePack,\n fingerprint,\n entryPath: hasSapi ? entryPath : null,\n declaredDependencies,\n });\n }\n out.sort((a, b) => a.folderId.localeCompare(b.folderId));\n return out;\n}\n\n/** \u4ECE\u672C\u673A\u72B6\u6001 + \u5DF2\u6709 UUID \u5408\u6210 desired catalog\u3002\n * UUID \u4F18\u5148:deployed catalog \u2192 \u672C\u5730 build manifest \u2192 \u65B0\u5EFA\u968F\u673A\u3002\n */\nexport async function computeDesiredCatalog(opts?: {\n bpUuid?: string;\n rpUuid?: string | null;\n bpVersion?: [number, number, number];\n rpVersion?: [number, number, number] | null;\n bpModuleUuid?: string;\n rpModuleUuid?: string;\n}): Promise<DeployCatalog> {\n const mods = await scanLocalModules();\n const modules: Record<string, DeployCatalogModule> = {};\n let anyRp = false;\n for (const m of mods) {\n /* catalog \u8BB0\u5F55\u5168\u90E8\u5DF2\u5B89\u88C5\u6A21\u5757\u7684\u542F\u505C\u4E0E\u6307\u7EB9,\u4FBF\u4E8E diff \u88C5\u5378/\u7981\u7528 */\n modules[m.folderId] = {\n logicalId: m.logicalId,\n enabled: m.enabled,\n version: m.version,\n fingerprint: m.fingerprint,\n hasResourcePack: m.hasResourcePack,\n };\n if (m.enabled && m.hasResourcePack) anyRp = true;\n }\n\n const localBp = readPackManifestHeader(bpOut());\n const localRp = readPackManifestHeader(rpOut());\n const bpUuid = opts?.bpUuid ?? localBp?.uuid ?? crypto.randomUUID();\n const bpVersion = opts?.bpVersion ?? localBp?.version ?? DEFAULT_PACK_VERSION;\n const bpModuleUuid = opts?.bpModuleUuid ?? localBp?.moduleUuid;\n let rpUuid: string | null = null;\n let rpVersion: [number, number, number] | null = null;\n let rpModuleUuid: string | undefined;\n if (anyRp) {\n rpUuid = opts?.rpUuid ?? localRp?.uuid ?? crypto.randomUUID();\n rpVersion = opts?.rpVersion ?? localRp?.version ?? DEFAULT_PACK_VERSION;\n rpModuleUuid = opts?.rpModuleUuid ?? localRp?.moduleUuid;\n }\n\n let sdkVersion: string | undefined;\n try {\n const sdkRoot = resolveSdkPackageRoot();\n const pkg = JSON.parse(readFileSync(path.join(sdkRoot, \"package.json\"), \"utf8\")) as { version?: string };\n sdkVersion = pkg.version;\n } catch {\n /* ignore */\n }\n\n // \u4F9D\u8D56\u52A8\u6001\u534F\u5546\uFF1A\u6536\u96C6\u6240\u6709\u5DF2\u542F\u7528\u6A21\u5757\u7684 Minecraft \u4F9D\u8D56\u58F0\u660E\u5E76\u6309\u7248\u672C\u89C4\u5219\u63D0\u5347\n const enabledModuleReqs = mods\n .filter((m) => m.enabled && m.declaredDependencies.length > 0)\n .map((m) => ({ folderId: m.folderId, dependencies: m.declaredDependencies }));\n const negotiated = negotiateBedrockDependencies(BASELINE_BEDROCK_DEPENDENCIES, enabledModuleReqs);\n\n if (negotiated.promotions.length > 0) {\n for (const p of negotiated.promotions) {\n packLog(\n `promoted ${p.moduleName} ${p.from} -> ${p.to} (requested by: ${p.requestedBy.join(\", \")})`,\n \"info\"\n );\n }\n }\n\n return {\n schemaVersion: 1,\n dbPort: configuredDbPort(getRoot()),\n bpUuid,\n rpUuid,\n bpVersion,\n rpVersion,\n ...(bpModuleUuid ? { bpModuleUuid } : {}),\n ...(rpModuleUuid ? { rpModuleUuid } : {}),\n generatedAt: Date.now(),\n ...(sdkVersion ? { sdkVersion } : {}),\n dependencies: negotiated.dependencies,\n modules,\n };\n}\n\nexport function readDeployedCatalog(bdsRoot: string, levelName: string): DeployCatalog | null {\n const file = deployedCatalogPath(bdsRoot, levelName);\n if (!existsSync(file)) return null;\n try {\n return JSON.parse(readFileSync(file, \"utf8\")) as DeployCatalog;\n } catch {\n return null;\n }\n}\n\n/** \u6BD4\u8F83\u952E:\u6A21\u5757\u96C6\u5408 + enabled/version/fingerprint/hasRP + bp/rp uuid + sdkVersion + dependencies */\nexport function catalogsEqual(a: DeployCatalog, b: DeployCatalog): boolean {\n if (a.dbPort !== b.dbPort) return false;\n if (a.bpUuid !== b.bpUuid) return false;\n if ((a.rpUuid ?? null) !== (b.rpUuid ?? null)) return false;\n if ((a.sdkVersion ?? null) !== (b.sdkVersion ?? null)) return false;\n\n const depsA = a.dependencies ?? [];\n const depsB = b.dependencies ?? [];\n if (depsA.length !== depsB.length) return false;\n for (let i = 0; i < depsA.length; i++) {\n const da = depsA[i];\n const db = depsB[i];\n if (!da || !db || da.module_name !== db.module_name || da.version !== db.version) {\n return false;\n }\n }\n const aKeys = Object.keys(a.modules).sort();\n const bKeys = Object.keys(b.modules).sort();\n if (aKeys.length !== bKeys.length) return false;\n for (let i = 0; i < aKeys.length; i++) {\n if (aKeys[i] !== bKeys[i]) return false;\n }\n for (const k of aKeys) {\n const x = a.modules[k]!;\n const y = b.modules[k]!;\n if (\n x.logicalId !== y.logicalId ||\n x.enabled !== y.enabled ||\n x.version !== y.version ||\n x.fingerprint !== y.fingerprint ||\n x.hasResourcePack !== y.hasResourcePack\n ) {\n return false;\n }\n }\n /* \u4E16\u754C\u6E05\u5355\u662F\u5426\u4ECD\u542B uuid \u2014 \u8C03\u7528\u65B9\u989D\u5916\u68C0\u67E5 */\n return true;\n}\n\n/** \u4E16\u754C enable-list \u67E5\u8BE2 \u2014 \u76F4\u8FDE pack-manager-lib\uFF08DRY/DIP\uFF0C\u4E0E CLI has-pack \u540C\u5951\u7EA6\uFF09 */\nfunction worldPackListHas(bdsRoot: string, levelName: string, kind: \"behavior\" | \"resource\", uuid: string): boolean {\n return pmWorldPackListHas(bdsWorldsDir(bdsRoot), levelName, kind, uuid);\n}\n\n/** esbuild \u805A\u5408\u542F\u7528\u6A21\u5757 \u2192 assemble BP + RP(\u82E5\u6709) */\nexport async function buildPacks(desired?: DeployCatalog): Promise<DeployCatalog> {\n await fs.mkdir(buildRoot(), { recursive: true });\n const catalog = desired ?? (await computeDesiredCatalog());\n packLog(`building BP/RP (modules=${Object.keys(catalog.modules).length})\u2026`);\n\n /* \u5355\u6B21\u626B\u63CF:SAPI \u5165\u53E3 + RP \u76EE\u5F55(DRY,\u907F\u514D listEnabled* \u91CD\u590D fingerprint) */\n const mods = await scanLocalModules();\n const entries = mods.filter((m) => m.enabled && m.entryPath).map((m) => m.entryPath!);\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(packagesDir(), m.folderId, \"resource_pack\");\n }\n\n const { build } = await import(\"esbuild\");\n const outFile = path.join(bpSrc(), \"scripts\", \"main.js\");\n await fs.mkdir(path.dirname(outFile), { recursive: true });\n if (entries.length === 0) {\n await fs.writeFile(outFile, \"/* no modules enabled */\\n\", \"utf8\");\n packLog(\"no enabled SAPI modules \u2014 empty main.js\", \"warn\");\n } else {\n const sdkRoot = resolveSdkPackageRoot();\n packLog(`SDK root: ${sdkRoot}`);\n await build({\n stdin: {\n contents: [\n 'import \"sfmc:host\";',\n ...entries.map((e) => `import ${JSON.stringify(path.resolve(e).replace(/\\\\/g, \"/\"))};`),\n ].join(\"\\n\"),\n resolveDir: ROOT,\n sourcefile: \"bootstrap.ts\",\n loader: \"ts\",\n },\n outfile: outFile,\n bundle: true,\n platform: \"neutral\",\n format: \"esm\",\n target: \"es2022\",\n logLevel: \"warning\",\n sourcemap: true,\n external: [\"@minecraft/*\"],\n // \u907F\u514D\u8BFB\u53D6\u6A21\u5757\u5185\u6B8B\u7F3A\u7684 extends\uFF08\u5982 ../../../sdk/@sfmc-sdk/tsconfig.json\uFF09\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, catalog.dbPort)],\n });\n packLog(`esbuild bundled ${entries.length} entr(y/ies)`, \"success\");\n }\n\n try {\n await assembleBehaviorPack({\n srcDir: bpSrc(),\n outDir: bpOut(),\n projectName: BP_NAME,\n version: catalog.bpVersion,\n description: \"ScriptsForMinecraftServer aggregated behavior pack\",\n uuid: catalog.bpUuid,\n ...(catalog.bpModuleUuid ? { moduleUuid: catalog.bpModuleUuid } : {}),\n ...(catalog.dependencies ? { dependencies: catalog.dependencies } : {}),\n });\n } catch (e) {\n throw new Error(`assemble-bp failed: ${(e as Error).message}`);\n }\n packLog(`assembled BP uuid=${catalog.bpUuid}`, \"success\");\n\n if (Object.keys(rpDirs).length > 0 && catalog.rpUuid) {\n /* OCP:\u663E\u5F0F module\u2192rpDir map \u76F4\u4F20\u5E93\uFF0C\u4E0D\u518D\u4E34\u65F6\u955C\u50CF\u6574\u6811 / \u843D\u76D8 JSON */\n try {\n await assembleResourcePack({\n moduleResourceDirs: rpDirs,\n outDir: rpOut(),\n projectName: RP_NAME,\n version: catalog.rpVersion ?? DEFAULT_PACK_VERSION,\n description: \"ScriptsForMinecraftServer aggregated resource pack\",\n uuid: catalog.rpUuid,\n ...(catalog.rpModuleUuid ? { moduleUuid: catalog.rpModuleUuid } : {}),\n });\n } catch (e) {\n throw new Error(`assemble-rp failed: ${(e as Error).message}`);\n }\n packLog(`assembled RP uuid=${catalog.rpUuid} (${Object.keys(rpDirs).length} modules)`, \"success\");\n } else {\n /* \u65E0 RP:\u6E05\u7406\u65E7\u4EA7\u7269,catalog.rpUuid \u7F6E\u7A7A */\n await fs.rm(rpOut(), { recursive: true, force: true });\n catalog.rpUuid = null;\n catalog.rpVersion = null;\n packLog(\"no enabled resource packs \u2014 RP skipped\");\n }\n\n /* \u628A catalog \u5199\u5230\u672C\u5730 BP \u4EA7\u7269,deploy \u65F6\u4E00\u5E76\u62F7\u8D70 */\n catalog.generatedAt = Date.now();\n writeJson(path.join(bpOut(), DEPLOY_CATALOG_NAME), catalog);\n return catalog;\n}\n\n/** \u90E8\u7F72\u5230\u4E16\u754C + enable \u6E05\u5355 + Script API permission */\nexport async function deployPacks(catalog: DeployCatalog): Promise<void> {\n const { bdsRoot, levelName } = resolveBdsContext();\n if (!existsSync(bpOut())) {\n throw new Error(`BP not built at ${bpOut()}. Run build first.`);\n }\n\n /* \u5FC5\u987B\u5728 deploy/clear-rp \u4E4B\u524D\u91C7\u96C6 \u2014 \u6E05\u76EE\u5F55\u540E\u65E0\u6CD5\u518D\u8BFB manifest */\n const previous = collectDeployedPackUuids(bdsRoot, levelName);\n try {\n await deployToBDS({\n bdsRoot,\n levelName,\n behaviorPackSrc: bpOut(),\n bpName: BP_NAME,\n rpName: RP_NAME,\n ...(catalog.rpUuid && existsSync(rpOut())\n ? { resourcePackSrc: rpOut() }\n : { clearResourcePack: true }),\n });\n } catch (e) {\n throw new Error(`deploy failed: ${(e as Error).message}`);\n }\n packLog(`deployed to worlds/${levelName}`, \"success\");\n\n /* \u786E\u4FDD catalog \u5728\u90E8\u7F72\u540E\u7684 BP \u5185(deploy \u4F1A\u62F7\u8D1D\u6574\u4E2A\u76EE\u5F55) */\n writeJson(path.join(deployedBpDir(bdsRoot, levelName), DEPLOY_CATALOG_NAME), catalog);\n\n const worldsDir = bdsWorldsDir(bdsRoot);\n try {\n await enablePackInWorld({\n worldsDir,\n levelName,\n kind: \"behavior\",\n packUuid: catalog.bpUuid,\n version: catalog.bpVersion,\n });\n } catch (e) {\n throw new Error(`enable BP failed: ${(e as Error).message}`);\n }\n packLog(`enabled behavior pack ${catalog.bpUuid} in world list`, \"success\");\n\n if (catalog.rpUuid && catalog.rpVersion) {\n try {\n await enablePackInWorld({\n worldsDir,\n levelName,\n kind: \"resource\",\n packUuid: catalog.rpUuid,\n version: catalog.rpVersion,\n });\n } catch (e) {\n throw new Error(`enable RP failed: ${(e as Error).message}`);\n }\n packLog(`enabled resource pack ${catalog.rpUuid} in world list`, \"success\");\n }\n\n /* \u5378\u6389\u8FC7\u671F RP:UUID \u8F6E\u6362 / \u4E0D\u518D\u63D0\u4F9B RP / catalog \u7F3A\u5931\u4F46\u78C1\u76D8\u4ECD\u6709\u65E7\u5305 */\n for (const staleRp of previous.rp) {\n if (staleRp === (catalog.rpUuid ?? null)) continue;\n try {\n await disablePackInWorld({\n worldsDir,\n levelName,\n kind: \"resource\",\n packUuid: staleRp,\n version: DEFAULT_PACK_VERSION,\n });\n packLog(`disabled stale resource pack ${staleRp}`, \"success\");\n } catch (e) {\n packLog(`disable stale RP ${staleRp} failed: ${(e as Error).message}`, \"warn\");\n }\n }\n\n /* \u5378\u6389\u8FC7\u671F BP(uuid \u8F6E\u6362) */\n for (const staleBp of previous.bp) {\n if (staleBp === catalog.bpUuid) continue;\n try {\n await disablePackInWorld({\n worldsDir,\n levelName,\n kind: \"behavior\",\n packUuid: staleBp,\n version: DEFAULT_PACK_VERSION,\n });\n packLog(`disabled stale behavior pack ${staleBp}`, \"success\");\n } catch (e) {\n packLog(`disable stale BP ${staleBp} failed: ${(e as Error).message}`, \"warn\");\n }\n }\n\n try {\n const wrote = await ensureConfigPermission(bdsRoot, catalog.bpUuid);\n const permRel = path.relative(bdsRoot, configPermissionPath(bdsRoot, catalog.bpUuid));\n packLog(wrote ? `wrote ${permRel}` : `${permRel} already exists \u2014 skipped`);\n } catch (e) {\n throw new Error(`ensure-permission failed: ${(e as Error).message}`);\n }\n}\n\nexport function formatPackLoadInfo(catalog: DeployCatalog, rebuilt: boolean): string {\n const mods = Object.entries(catalog.modules);\n const enabled = mods.filter(([, m]) => m.enabled);\n const disabled = mods.filter(([, m]) => !m.enabled);\n const lines = [\n `pack load ${rebuilt ? \"(rebuilt)\" : \"(catalog match \u2014 skip rebuild)\"}`,\n ` BP ${catalog.bpUuid} v${catalog.bpVersion.join(\".\")}`,\n catalog.rpUuid\n ? ` RP ${catalog.rpUuid} v${(catalog.rpVersion ?? DEFAULT_PACK_VERSION).join(\".\")}`\n : ` RP (none)`,\n ` modules: ${enabled.length} enabled / ${disabled.length} disabled / ${mods.length} installed`,\n ];\n if (catalog.dependencies && catalog.dependencies.length > 0) {\n const depStr = catalog.dependencies.map((d) => `${d.module_name}@${d.version}`).join(\" \");\n lines.push(` dependencies: ${depStr}`);\n }\n for (const [folderId, m] of enabled.sort((a, b) => a[0].localeCompare(b[0]))) {\n lines.push(` \u25CF ${folderId} (${m.logicalId}) ${m.version}${m.hasResourcePack ? \" +rp\" : \"\"}`);\n }\n for (const [folderId, m] of disabled.sort((a, b) => a[0].localeCompare(b[0]))) {\n lines.push(` \u25CB ${folderId} (${m.logicalId}) disabled`);\n }\n return lines.join(\"\\n\");\n}\n\nfunction reusePackIds(deployed: DeployCatalog): {\n bpUuid?: string;\n rpUuid?: string | null;\n bpVersion?: [number, number, number];\n rpVersion?: [number, number, number] | null;\n bpModuleUuid?: string;\n rpModuleUuid?: string;\n} {\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}\n\n/**\n * BDS \u542F\u52A8\u524D\u95F8\u95E8:catalog \u4E0D\u4E00\u81F4\u5219\u6574\u5305\u91CD\u7F16\u90E8\u7F72;\u5931\u8D25\u629B\u9519,\u7981\u6B62\u542F\u52A8\u3002\n */\nexport async function ensurePacksReady(): Promise<PackEnsureResult> {\n const { bdsRoot, levelName } = resolveBdsContext();\n packLog(`preflight: checking packs for ${bdsRoot} / ${levelName}`);\n\n const deployed = readDeployedCatalog(bdsRoot, levelName);\n /* \u590D\u7528\u5DF2\u90E8\u7F72 UUID,\u907F\u514D\u65E0\u8C13\u8F6E\u6362 */\n let desired = await computeDesiredCatalog(deployed ? reusePackIds(deployed) : undefined);\n\n /* \u82E5 desired \u9700\u8981 RP \u4F46\u590D\u7528\u4E86\u65E7 null rpUuid,\u8865\u4E00\u4E2A */\n const needsRp = Object.values(desired.modules).some((m) => m.enabled && m.hasResourcePack);\n if (needsRp && !desired.rpUuid) {\n desired = await computeDesiredCatalog({\n bpUuid: desired.bpUuid,\n bpVersion: desired.bpVersion,\n ...(desired.bpModuleUuid ? { bpModuleUuid: desired.bpModuleUuid } : {}),\n rpUuid: crypto.randomUUID(),\n rpVersion: DEFAULT_PACK_VERSION,\n });\n }\n if (!needsRp) {\n desired.rpUuid = null;\n desired.rpVersion = null;\n }\n\n let needRebuild = !deployed || !catalogsEqual(desired, deployed);\n if (!needRebuild && deployed) {\n if (!worldPackListHas(bdsRoot, levelName, \"behavior\", deployed.bpUuid)) needRebuild = true;\n if (deployed.rpUuid && !worldPackListHas(bdsRoot, levelName, \"resource\", deployed.rpUuid)) {\n needRebuild = true;\n }\n const deployedMainJs = path.join(deployedBpDir(bdsRoot, levelName), \"scripts\", \"main.js\");\n if (!existsSync(deployedMainJs)) needRebuild = true;\n if (!hasConfigPermission(bdsRoot, deployed.bpUuid)) {\n /* permission \u7F3A\u5931\u53EA\u8865\u5199,\u4E0D\u5F3A\u5236\u6574\u5305\u91CD\u7F16 */\n try {\n const wrote = await ensureConfigPermission(bdsRoot, deployed.bpUuid);\n const permRel = path.relative(bdsRoot, configPermissionPath(bdsRoot, deployed.bpUuid));\n packLog(wrote ? `wrote ${permRel}` : `${permRel} already exists \u2014 skipped`);\n } catch (e) {\n throw new Error(`ensure-permission failed: ${(e as Error).message}`);\n }\n }\n }\n\n let rebuilt = false;\n if (needRebuild) {\n packLog(\"catalog mismatch \u2014 rebuilding packs\u2026\", \"warn\");\n desired = await buildPacks(desired);\n await deployPacks(desired);\n rebuilt = true;\n } else {\n packLog(\"catalog match \u2014 skip rebuild\", \"success\");\n }\n\n const summary = formatPackLoadInfo(desired, rebuilt);\n for (const line of summary.split(\"\\n\")) packLog(line, rebuilt ? \"success\" : \"info\");\n\n return {\n rebuilt,\n skipped: !rebuilt,\n catalog: desired,\n bdsRoot,\n levelName,\n summary,\n };\n}\n\n/* \u2500\u2500 CLI \u547D\u4EE4\u5B9E\u73B0 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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\nexport async function cmdPackBuild(_args: string[]): Promise<CliResult> {\n try {\n const cat = await buildPacks();\n return okResult(c.green(t(\"pack.built\", { path: bpOut() })) + `\\n` + formatPackLoadInfo(cat, true) + \"\\n\");\n } catch (e) {\n packLog((e as Error).message, \"error\");\n return failResult(c.red(t(\"pack.buildFailed\", { message: (e as Error).message })));\n }\n}\n\nexport async function cmdPackDeploy(_args: string[]): Promise<CliResult> {\n try {\n const localCatFile = path.join(bpOut(), DEPLOY_CATALOG_NAME);\n let cat: DeployCatalog;\n if (existsSync(localCatFile)) {\n cat = JSON.parse(await fs.readFile(localCatFile, \"utf8\")) as DeployCatalog;\n } else {\n cat = await buildPacks();\n }\n await deployPacks(cat);\n return okResult(c.green(t(\"pack.deployed\")) + \"\\n\" + formatPackLoadInfo(cat, true) + \"\\n\");\n } catch (e) {\n packLog((e as Error).message, \"error\");\n return failResult(c.red(t(\"pack.deployFailed\", { message: (e as Error).message })));\n }\n}\n\nexport async function cmdPackStatus(_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 const match = deployed ? catalogsEqual(desired, deployed) : false;\n const permPath = deployed ? configPermissionPath(bdsRoot, deployed.bpUuid) : null;\n const lines = [\n c.bold(\"\\nPack status\"),\n ` bds : ${bdsRoot}`,\n ` level : ${levelName}`,\n ` catalog : ${match ? c.green(\"in sync\") : c.yellow(deployed ? \"mismatch \u2014 will rebuild on start\" : \"missing\")}`,\n ` BP dir : ${deployedBpDir(bdsRoot, levelName)} ${existsSync(deployedBpDir(bdsRoot, levelName)) ? c.green(\"\u2713\") : c.red(\"\u2717\")}`,\n ` RP dir : ${deployedRpDir(bdsRoot, levelName)} ${existsSync(deployedRpDir(bdsRoot, levelName)) ? c.green(\"\u2713\") : c.dim(\"\u2014\")}`,\n ` permission : ${permPath ? (existsSync(permPath) ? c.green(permPath) : c.yellow(\"missing\")) : c.dim(\"n/a\")}`,\n ];\n if (deployed) {\n lines.push(` BP uuid : ${deployed.bpUuid}`);\n if (deployed.rpUuid) lines.push(` RP uuid : ${deployed.rpUuid}`);\n lines.push(\n ` world BP : ${worldPackListHas(bdsRoot, levelName, \"behavior\", deployed.bpUuid) ? c.green(\"listed\") : c.red(\"not listed\")}`\n );\n if (deployed.rpUuid) {\n lines.push(\n ` world RP : ${worldPackListHas(bdsRoot, levelName, \"resource\", deployed.rpUuid) ? c.green(\"listed\") : c.red(\"not listed\")}`\n );\n }\n }\n lines.push(formatPackLoadInfo(desired, false));\n return lines.join(\"\\n\") + \"\\n\";\n } catch (e) {\n return c.red(t(\"pack.statusFailed\", { message: (e as Error).message }));\n }\n}\n\nexport async function cmdPackList(_args: string[]): Promise<string> {\n try {\n const { bdsRoot, levelName } = resolveBdsContext();\n const mods = await scanLocalModules();\n const lines = [c.bold(\"\\nModules / resource packs\"), c.dim(` ${packagesDir()}`)];\n for (const m of mods) {\n const mark = m.enabled ? c.green(\"\u25CF\") : c.dim(\"\u25CB\");\n lines.push(\n ` ${mark} ${m.folderId.padEnd(24)} ${m.logicalId.padEnd(24)} ${m.enabled ? \"on \" : \"off\"} ${m.hasResourcePack ? \"+rp\" : \" \"} ${m.version}`\n );\n }\n const worldsDir = bdsWorldsDir(bdsRoot);\n lines.push(c.bold(\"\\nWorld enable lists\"));\n for (const kind of [\"behavior\", \"resource\"] as const) {\n const arr = readWorldPackList(worldsDir, levelName, kind);\n if (!arr.length) lines.push(c.dim(` ${kind}: (empty)`));\n for (const e of arr) {\n lines.push(` ${kind}: ${e.pack_id} v${(e.version ?? []).join(\".\")}`);\n }\n }\n return lines.join(\"\\n\") + \"\\n\";\n } catch (e) {\n return c.red(t(\"pack.listFailed\", { message: (e as Error).message }));\n }\n}\n\nexport async function cmdPackEnableDisable(action: \"enable\" | \"disable\", args: string[]): Promise<string> {\n try {\n const kind = (args[0] === \"resource\" || args[0] === \"rp\" ? \"resource\" : \"behavior\") as \"behavior\" | \"resource\";\n const { bdsRoot, levelName } = resolveBdsContext();\n const deployed = readDeployedCatalog(bdsRoot, levelName);\n if (!deployed) return c.red(t(\"pack.noCatalog\"));\n const uuid = kind === \"behavior\" ? deployed.bpUuid : deployed.rpUuid;\n const version = kind === \"behavior\" ? deployed.bpVersion : deployed.rpVersion;\n if (!uuid || !version) return c.red(t(\"pack.noUuid\", { kind }));\n const worldsDir = bdsWorldsDir(bdsRoot);\n try {\n const opts = { worldsDir, levelName, kind, packUuid: uuid, version };\n if (action === \"enable\") await enablePackInWorld(opts);\n else await disablePackInWorld(opts);\n } catch (e) {\n return c.red(t(\"pack.actionFailed\", { action, detail: (e as Error).message }));\n }\n packLog(`${action}d ${kind} pack ${uuid}`, \"success\");\n return c.green(\n action === \"enable\"\n ? t(\"pack.enabledOk\", { kind, uuid })\n : t(\"pack.disabledOk\", { kind, uuid })\n );\n } catch (e) {\n return c.red(t(\"pack.actionErr\", { action, message: (e as Error).message }));\n }\n}\n\n/* CLI \u8868\u9762\u5DF2\u6536\u655B\uFF1A\u6A21\u5757\u7528 mod build/reload\uFF1B\u7B2C\u4E09\u65B9\u5305\u542F\u505C\u7528 addon/packs\u3002\n * \u6B64\u5904\u4FDD\u7559 cmdPackBuild / cmdPackDeploy \u4F9B ensurePacksReady \u4E0E mod reload \u8C03\u7528\u3002 */\n\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,13 @@
1
+ export interface BdsPlayerSession {
2
+ connected: boolean;
3
+ playerName: string;
4
+ xuid: string;
5
+ }
6
+ /** 从 BDS 原生日志中提取玩家名与 XUID。 */
7
+ export declare function parseBdsPlayerSession(line: string): BdsPlayerSession | null;
8
+ /** 将玩家会话身份异步同步到本机 db-server。 */
9
+ export declare function reportBdsPlayerSession(line: string, options: {
10
+ port: number;
11
+ authToken?: string;
12
+ }): void;
13
+ //# sourceMappingURL=player-session.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"player-session.d.ts","sourceRoot":"","sources":["../src/player-session.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,8BAA8B;AAC9B,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB,GAAG,IAAI,CAO3E;AAED,gCAAgC;AAChC,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAaxG"}
@@ -0,0 +1,26 @@
1
+ function parseBdsPlayerSession(line) {
2
+ const match = /Player (connected|disconnected):\s*([^,]+),\s*xuid:\s*([^\s]+)/i.exec(line);
3
+ if (!match) return null;
4
+ const playerName = match[2]?.trim() ?? "";
5
+ const xuid = match[3]?.trim() ?? "";
6
+ if (!playerName || !xuid) return null;
7
+ return { connected: match[1]?.toLowerCase() === "connected", playerName, xuid };
8
+ }
9
+ function reportBdsPlayerSession(line, options) {
10
+ const session = parseBdsPlayerSession(line);
11
+ if (!session) return;
12
+ const headers = { "content-type": "application/json" };
13
+ if (options.authToken) headers.authorization = `Bearer ${options.authToken}`;
14
+ void fetch(`http://127.0.0.1:${options.port}/api/sfmc/player-session`, {
15
+ method: "POST",
16
+ headers,
17
+ body: JSON.stringify(session),
18
+ signal: AbortSignal.timeout(2e3)
19
+ }).catch(() => {
20
+ });
21
+ }
22
+ export {
23
+ parseBdsPlayerSession,
24
+ reportBdsPlayerSession
25
+ };
26
+ //# sourceMappingURL=player-session.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/player-session.ts"],
4
+ "sourcesContent": ["export interface BdsPlayerSession {\n connected: boolean;\n playerName: string;\n xuid: string;\n}\n\n/** \u4ECE BDS \u539F\u751F\u65E5\u5FD7\u4E2D\u63D0\u53D6\u73A9\u5BB6\u540D\u4E0E XUID\u3002 */\nexport function parseBdsPlayerSession(line: string): BdsPlayerSession | null {\n const match = /Player (connected|disconnected):\\s*([^,]+),\\s*xuid:\\s*([^\\s]+)/i.exec(line);\n if (!match) return null;\n const playerName = match[2]?.trim() ?? \"\";\n const xuid = match[3]?.trim() ?? \"\";\n if (!playerName || !xuid) return null;\n return { connected: match[1]?.toLowerCase() === \"connected\", playerName, xuid };\n}\n\n/** \u5C06\u73A9\u5BB6\u4F1A\u8BDD\u8EAB\u4EFD\u5F02\u6B65\u540C\u6B65\u5230\u672C\u673A db-server\u3002 */\nexport function reportBdsPlayerSession(line: string, options: { port: number; authToken?: string }): void {\n const session = parseBdsPlayerSession(line);\n if (!session) return;\n const headers: Record<string, string> = { \"content-type\": \"application/json\" };\n if (options.authToken) headers.authorization = `Bearer ${options.authToken}`;\n void fetch(`http://127.0.0.1:${options.port}/api/sfmc/player-session`, {\n method: \"POST\",\n headers,\n body: JSON.stringify(session),\n signal: AbortSignal.timeout(2_000),\n }).catch(() => {\n // \u8EAB\u4EFD\u540C\u6B65\u5931\u8D25\u4E0D\u5E94\u5E72\u6270 BDS \u65E5\u5FD7\u7BA1\u9053\uFF1B\u540E\u7EED\u8FDE\u63A5\u6216\u4F4E\u9891\u6821\u9A8C\u4F1A\u91CD\u8BD5\u3002\n });\n}\n"],
5
+ "mappings": "AAOO,SAAS,sBAAsB,MAAuC;AAC3E,QAAM,QAAQ,kEAAkE,KAAK,IAAI;AACzF,MAAI,CAAC,MAAO,QAAO;AACnB,QAAM,aAAa,MAAM,CAAC,GAAG,KAAK,KAAK;AACvC,QAAM,OAAO,MAAM,CAAC,GAAG,KAAK,KAAK;AACjC,MAAI,CAAC,cAAc,CAAC,KAAM,QAAO;AACjC,SAAO,EAAE,WAAW,MAAM,CAAC,GAAG,YAAY,MAAM,aAAa,YAAY,KAAK;AAChF;AAGO,SAAS,uBAAuB,MAAc,SAAqD;AACxG,QAAM,UAAU,sBAAsB,IAAI;AAC1C,MAAI,CAAC,QAAS;AACd,QAAM,UAAkC,EAAE,gBAAgB,mBAAmB;AAC7E,MAAI,QAAQ,UAAW,SAAQ,gBAAgB,UAAU,QAAQ,SAAS;AAC1E,OAAK,MAAM,oBAAoB,QAAQ,IAAI,4BAA4B;AAAA,IACrE,QAAQ;AAAA,IACR;AAAA,IACA,MAAM,KAAK,UAAU,OAAO;AAAA,IAC5B,QAAQ,YAAY,QAAQ,GAAK;AAAA,EACnC,CAAC,EAAE,MAAM,MAAM;AAAA,EAEf,CAAC;AACH;",
6
+ "names": []
7
+ }
@@ -23,7 +23,7 @@ export interface RegistryEntry {
23
23
  export type RegistryIndex = Record<string, RegistryEntry>;
24
24
  /**
25
25
  * 解析 first-party index.json。
26
- * 契约与 tools/lib/registry-index.mjs#parseRegistryIndex 保持一致:
26
+ * 契约与 scripts/module-install/lib/registry-index.mjs#parseRegistryIndex 保持一致:
27
27
  * `{ modules: { <id>: { npm? | repo+tag } } }`。忽略 `_` 前缀元数据键。
28
28
  */
29
29
  export declare function parseRegistryIndex(json: unknown): RegistryIndex;
@@ -1 +1 @@
1
- {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAWH,QAAA,MAAM,qBAAqB,yBAAyB,CAAC;AACrD,QAAA,MAAM,oBAAoB,SAAS,CAAC;AAGpC,MAAM,WAAW,aAAa;IAC5B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AACD,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;AAyB1D;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,OAAO,GAAG,aAAa,CA8B/D;AAQD,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,aAAa,CAAC;IACrB,iFAAiF;IACjF,KAAK,EAAE,OAAO,CAAC;CAChB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,oBAAoB,CAAC,IAAI,CAAC,EAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAAC,cAAc,CAAC,CAmB9F;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,IAAI,MAAM,EAAE,CAIpD;AAED;;;;;GAKG;AACH,wBAAsB,kBAAkB,CAAC,YAAY,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAQlF;AAED,OAAO,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,CAAC"}
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAWH,QAAA,MAAM,qBAAqB,yBAAyB,CAAC;AACrD,QAAA,MAAM,oBAAoB,SAAS,CAAC;AAGpC,MAAM,WAAW,aAAa;IAC5B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AACD,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;AAyB1D;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,OAAO,GAAG,aAAa,CA8B/D;AAWD,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,aAAa,CAAC;IACrB,iFAAiF;IACjF,KAAK,EAAE,OAAO,CAAC;CAChB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,oBAAoB,CAAC,IAAI,CAAC,EAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAAC,cAAc,CAAC,CAmB9F;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,IAAI,MAAM,EAAE,CAIpD;AAED;;;;;GAKG;AACH,wBAAsB,kBAAkB,CAAC,YAAY,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAQlF;AAED,OAAO,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,CAAC"}
package/dist/registry.js CHANGED
@@ -55,7 +55,10 @@ function parseRegistryIndex(json) {
55
55
  return filtered;
56
56
  }
57
57
  async function fetchFresh() {
58
- const res = await fetch(INDEX_URL, { headers: { "User-Agent": "sfmc-cli" } });
58
+ const res = await fetch(INDEX_URL, {
59
+ headers: { "User-Agent": "sfmc-cli" },
60
+ signal: AbortSignal.timeout(3e3)
61
+ });
59
62
  if (!res.ok) throw new Error(`HTTP ${res.status} for ${INDEX_URL}`);
60
63
  return parseRegistryIndex(await res.json());
61
64
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/registry.ts"],
4
- "sourcesContent": ["/**\n * registry.ts \u2014 first-party sfmc-modules index resolution, shared between\n * the module CLI and the startup unknown-source warning.\n *\n * Talks to https://raw.githubusercontent.com/Tanya7z/sfmc-modules/main/index.json\n * (the registry lives in a separate repo to keep this one free of \"what\n * modules exist\" governance). Caches to <sfmc/src/.sfmc-registry-cache.json>\n * with a 1h TTL so a brief network blip doesn't degrade the CLI.\n *\n * Both helpers are best-effort: failures are surfaced as `null` and a\n * console warning, never an exception, because the CLI must still boot\n * when the registry is unreachable.\n */\n\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport path from \"node:path\";\nimport process from \"node:process\";\nimport { fileURLToPath } from \"node:url\";\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\nconst CACHE_PATH = path.join(__dirname, \".sfmc-registry-cache.json\");\nconst TTL_MS = 60 * 60 * 1000;\n\nconst DEFAULT_REGISTRY_REPO = \"Tanya7z/sfmc-modules\";\nconst DEFAULT_REGISTRY_TAG = \"main\";\nconst INDEX_URL = `https://raw.githubusercontent.com/${DEFAULT_REGISTRY_REPO}/${DEFAULT_REGISTRY_TAG}/index.json`;\n\nexport interface RegistryEntry {\n npm?: string;\n version?: string;\n sdk?: string;\n repo?: string;\n tag?: string;\n}\nexport type RegistryIndex = Record<string, RegistryEntry>;\n\ninterface RegistryCache {\n fetchedAt: number;\n index: RegistryIndex;\n}\n\nfunction readCache(): RegistryCache | null {\n try {\n if (!existsSync(CACHE_PATH)) return null;\n return JSON.parse(readFileSync(CACHE_PATH, \"utf8\")) as RegistryCache;\n } catch {\n return null;\n }\n}\n\nfunction writeCache(cache: RegistryCache): void {\n try {\n mkdirSync(path.dirname(CACHE_PATH), { recursive: true });\n writeFileSync(CACHE_PATH, JSON.stringify(cache, null, 2));\n } catch {\n /* cache write is best-effort */\n }\n}\n\n/**\n * \u89E3\u6790 first-party index.json\u3002\n * \u5951\u7EA6\u4E0E tools/lib/registry-index.mjs#parseRegistryIndex \u4FDD\u6301\u4E00\u81F4\uFF1A\n * `{ modules: { <id>: { npm? | repo+tag } } }`\u3002\u5FFD\u7565 `_` \u524D\u7F00\u5143\u6570\u636E\u952E\u3002\n */\nexport function parseRegistryIndex(json: unknown): RegistryIndex {\n if (typeof json !== \"object\" || json === null || Array.isArray(json)) {\n throw new Error(\"registry index must be a JSON object with a 'modules' field\");\n }\n const root = json as Record<string, unknown>;\n const modulesRaw = root.modules;\n if (typeof modulesRaw !== \"object\" || modulesRaw === null || Array.isArray(modulesRaw)) {\n throw new Error(\"registry index must have a 'modules' object mapping id \u2192 entry\");\n }\n const filtered: RegistryIndex = {};\n for (const [k, v] of Object.entries(modulesRaw as Record<string, unknown>)) {\n if (k.startsWith(\"_\")) continue;\n if (typeof v !== \"object\" || v === null || Array.isArray(v)) continue;\n const entry = v as Record<string, unknown>;\n const hasNpm = typeof entry.npm === \"string\" && entry.npm.length > 0;\n const hasGh = typeof entry.repo === \"string\" && typeof entry.tag === \"string\";\n if (!hasNpm && !hasGh) continue;\n const out: RegistryEntry = {};\n if (hasNpm) {\n out.npm = entry.npm as string;\n if (typeof entry.version === \"string\") out.version = entry.version;\n if (typeof entry.sdk === \"string\") out.sdk = entry.sdk;\n }\n if (hasGh) {\n out.repo = entry.repo as string;\n out.tag = entry.tag as string;\n }\n filtered[k] = out;\n }\n return filtered;\n}\n\nasync function fetchFresh(): Promise<RegistryIndex> {\n const res = await fetch(INDEX_URL, { headers: { \"User-Agent\": \"sfmc-cli\" } });\n if (!res.ok) throw new Error(`HTTP ${res.status} for ${INDEX_URL}`);\n return parseRegistryIndex(await res.json());\n}\n\nexport interface RegistryResult {\n index: RegistryIndex;\n /** True when the index came from a stale cache because the live fetch failed. */\n stale: boolean;\n}\n\n/**\n * Resolve the first-party index.\n *\n * Order (default):\n * 1. If the cache is fresh (< TTL): return it without trying the network.\n * 2. Otherwise attempt a live fetch.\n * - success \u2192 write cache, return fresh.\n * - failure + cache exists \u2192 return cache with `stale: true` and a warning.\n * - failure + no cache \u2192 return `{ index: {}, stale: true }` and warn.\n *\n * `force: true` \u8DF3\u8FC7 TTL \u65E9\u9000,\u59CB\u7EC8\u5C1D\u8BD5\u62C9\u7F51(\u4F9B `mod search` \u4E3B\u52A8\u5237\u65B0\u5217\u8868)\u3002\n * \u5931\u8D25\u65F6\u4ECD\u56DE\u9000\u5230\u7F13\u5B58,\u6C38\u4E0D\u629B\u5F02\u5E38\u3002\n */\nexport async function resolveRegistryIndex(opts?: { force?: boolean }): Promise<RegistryResult> {\n const cache = readCache();\n if (!opts?.force && cache && Date.now() - cache.fetchedAt < TTL_MS) {\n return { index: cache.index, stale: false };\n }\n try {\n const fresh = await fetchFresh();\n writeCache({ fetchedAt: Date.now(), index: fresh });\n return { index: fresh, stale: false };\n } catch (err) {\n if (cache) {\n const msg = err instanceof Error ? err.message : String(err);\n process.stderr.write(`[sfmc] registry offline (${msg}); using cached index from ${new Date(cache.fetchedAt).toISOString()}\\n`);\n return { index: cache.index, stale: true };\n }\n const msg = err instanceof Error ? err.message : String(err);\n process.stderr.write(`[sfmc] registry unreachable and no cache: ${msg}\\n`);\n return { index: {}, stale: true };\n }\n}\n\n/**\n * \u4ECE\u672C\u5730\u7F13\u5B58\u540C\u6B65\u8BFB\u51FA registry \u6A21\u5757 id(\u4F9B Tab \u8865\u5168)\u3002\n * \u65E0\u7F13\u5B58\u65F6\u8FD4\u56DE\u7A7A\u6570\u7EC4,\u4E0D\u89E6\u53D1\u7F51\u7EDC\u3002\n */\nexport function listRegistryModuleIdsSync(): string[] {\n const cache = readCache();\n if (!cache) return [];\n return Object.keys(cache.index).sort((a, b) => a.localeCompare(b));\n}\n\n/**\n * Compare a set of installed module ids to the registry and return the\n * subset that isn't published in the first-party index. The \"best-effort\"\n * guarantee: this returns an empty array when the registry can't be reached\n * (we don't want a network outage to mark every local module as unknown).\n */\nexport async function findUnknownModules(installedIds: string[]): Promise<string[]> {\n const { index, stale } = await resolveRegistryIndex();\n if (stale && Object.keys(index).length === 0) {\n /* No cache either \u2014 silently treat every module as \"we couldn't tell\".\n * Otherwise offline mode would scream warnings at every boot. */\n return [];\n }\n return installedIds.filter((id) => !index[id]);\n}\n\nexport { DEFAULT_REGISTRY_REPO, DEFAULT_REGISTRY_TAG };"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * registry.ts \u2014 first-party sfmc-modules index resolution, shared between\n * the module CLI and the startup unknown-source warning.\n *\n * Talks to https://raw.githubusercontent.com/Tanya7z/sfmc-modules/main/index.json\n * (the registry lives in a separate repo to keep this one free of \"what\n * modules exist\" governance). Caches to <sfmc/src/.sfmc-registry-cache.json>\n * with a 1h TTL so a brief network blip doesn't degrade the CLI.\n *\n * Both helpers are best-effort: failures are surfaced as `null` and a\n * console warning, never an exception, because the CLI must still boot\n * when the registry is unreachable.\n */\n\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport path from \"node:path\";\nimport process from \"node:process\";\nimport { fileURLToPath } from \"node:url\";\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\nconst CACHE_PATH = path.join(__dirname, \".sfmc-registry-cache.json\");\nconst TTL_MS = 60 * 60 * 1000;\n\nconst DEFAULT_REGISTRY_REPO = \"Tanya7z/sfmc-modules\";\nconst DEFAULT_REGISTRY_TAG = \"main\";\nconst INDEX_URL = `https://raw.githubusercontent.com/${DEFAULT_REGISTRY_REPO}/${DEFAULT_REGISTRY_TAG}/index.json`;\n\nexport interface RegistryEntry {\n npm?: string;\n version?: string;\n sdk?: string;\n repo?: string;\n tag?: string;\n}\nexport type RegistryIndex = Record<string, RegistryEntry>;\n\ninterface RegistryCache {\n fetchedAt: number;\n index: RegistryIndex;\n}\n\nfunction readCache(): RegistryCache | null {\n try {\n if (!existsSync(CACHE_PATH)) return null;\n return JSON.parse(readFileSync(CACHE_PATH, \"utf8\")) as RegistryCache;\n } catch {\n return null;\n }\n}\n\nfunction writeCache(cache: RegistryCache): void {\n try {\n mkdirSync(path.dirname(CACHE_PATH), { recursive: true });\n writeFileSync(CACHE_PATH, JSON.stringify(cache, null, 2));\n } catch {\n /* cache write is best-effort */\n }\n}\n\n/**\n * \u89E3\u6790 first-party index.json\u3002\n * \u5951\u7EA6\u4E0E scripts/module-install/lib/registry-index.mjs#parseRegistryIndex \u4FDD\u6301\u4E00\u81F4\uFF1A\n * `{ modules: { <id>: { npm? | repo+tag } } }`\u3002\u5FFD\u7565 `_` \u524D\u7F00\u5143\u6570\u636E\u952E\u3002\n */\nexport function parseRegistryIndex(json: unknown): RegistryIndex {\n if (typeof json !== \"object\" || json === null || Array.isArray(json)) {\n throw new Error(\"registry index must be a JSON object with a 'modules' field\");\n }\n const root = json as Record<string, unknown>;\n const modulesRaw = root.modules;\n if (typeof modulesRaw !== \"object\" || modulesRaw === null || Array.isArray(modulesRaw)) {\n throw new Error(\"registry index must have a 'modules' object mapping id \u2192 entry\");\n }\n const filtered: RegistryIndex = {};\n for (const [k, v] of Object.entries(modulesRaw as Record<string, unknown>)) {\n if (k.startsWith(\"_\")) continue;\n if (typeof v !== \"object\" || v === null || Array.isArray(v)) continue;\n const entry = v as Record<string, unknown>;\n const hasNpm = typeof entry.npm === \"string\" && entry.npm.length > 0;\n const hasGh = typeof entry.repo === \"string\" && typeof entry.tag === \"string\";\n if (!hasNpm && !hasGh) continue;\n const out: RegistryEntry = {};\n if (hasNpm) {\n out.npm = entry.npm as string;\n if (typeof entry.version === \"string\") out.version = entry.version;\n if (typeof entry.sdk === \"string\") out.sdk = entry.sdk;\n }\n if (hasGh) {\n out.repo = entry.repo as string;\n out.tag = entry.tag as string;\n }\n filtered[k] = out;\n }\n return filtered;\n}\n\nasync function fetchFresh(): Promise<RegistryIndex> {\n const res = await fetch(INDEX_URL, {\n headers: { \"User-Agent\": \"sfmc-cli\" },\n signal: AbortSignal.timeout(3000),\n });\n if (!res.ok) throw new Error(`HTTP ${res.status} for ${INDEX_URL}`);\n return parseRegistryIndex(await res.json());\n}\n\nexport interface RegistryResult {\n index: RegistryIndex;\n /** True when the index came from a stale cache because the live fetch failed. */\n stale: boolean;\n}\n\n/**\n * Resolve the first-party index.\n *\n * Order (default):\n * 1. If the cache is fresh (< TTL): return it without trying the network.\n * 2. Otherwise attempt a live fetch.\n * - success \u2192 write cache, return fresh.\n * - failure + cache exists \u2192 return cache with `stale: true` and a warning.\n * - failure + no cache \u2192 return `{ index: {}, stale: true }` and warn.\n *\n * `force: true` \u8DF3\u8FC7 TTL \u65E9\u9000,\u59CB\u7EC8\u5C1D\u8BD5\u62C9\u7F51(\u4F9B `mod search` \u4E3B\u52A8\u5237\u65B0\u5217\u8868)\u3002\n * \u5931\u8D25\u65F6\u4ECD\u56DE\u9000\u5230\u7F13\u5B58,\u6C38\u4E0D\u629B\u5F02\u5E38\u3002\n */\nexport async function resolveRegistryIndex(opts?: { force?: boolean }): Promise<RegistryResult> {\n const cache = readCache();\n if (!opts?.force && cache && Date.now() - cache.fetchedAt < TTL_MS) {\n return { index: cache.index, stale: false };\n }\n try {\n const fresh = await fetchFresh();\n writeCache({ fetchedAt: Date.now(), index: fresh });\n return { index: fresh, stale: false };\n } catch (err) {\n if (cache) {\n const msg = err instanceof Error ? err.message : String(err);\n process.stderr.write(`[sfmc] registry offline (${msg}); using cached index from ${new Date(cache.fetchedAt).toISOString()}\\n`);\n return { index: cache.index, stale: true };\n }\n const msg = err instanceof Error ? err.message : String(err);\n process.stderr.write(`[sfmc] registry unreachable and no cache: ${msg}\\n`);\n return { index: {}, stale: true };\n }\n}\n\n/**\n * \u4ECE\u672C\u5730\u7F13\u5B58\u540C\u6B65\u8BFB\u51FA registry \u6A21\u5757 id(\u4F9B Tab \u8865\u5168)\u3002\n * \u65E0\u7F13\u5B58\u65F6\u8FD4\u56DE\u7A7A\u6570\u7EC4,\u4E0D\u89E6\u53D1\u7F51\u7EDC\u3002\n */\nexport function listRegistryModuleIdsSync(): string[] {\n const cache = readCache();\n if (!cache) return [];\n return Object.keys(cache.index).sort((a, b) => a.localeCompare(b));\n}\n\n/**\n * Compare a set of installed module ids to the registry and return the\n * subset that isn't published in the first-party index. The \"best-effort\"\n * guarantee: this returns an empty array when the registry can't be reached\n * (we don't want a network outage to mark every local module as unknown).\n */\nexport async function findUnknownModules(installedIds: string[]): Promise<string[]> {\n const { index, stale } = await resolveRegistryIndex();\n if (stale && Object.keys(index).length === 0) {\n /* No cache either \u2014 silently treat every module as \"we couldn't tell\".\n * Otherwise offline mode would scream warnings at every boot. */\n return [];\n }\n return installedIds.filter((id) => !index[id]);\n}\n\nexport { DEFAULT_REGISTRY_REPO, DEFAULT_REGISTRY_TAG };"],
5
+ "mappings": "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",
6
6
  "names": ["msg"]
7
7
  }
@@ -1 +1 @@
1
- {"version":3,"file":"format-display.d.ts","sourceRoot":"","sources":["../../src/repl-windows/format-display.ts"],"names":[],"mappings":"AAIA,OAAO,EAGL,KAAK,UAAU,EAEhB,MAAM,YAAY,CAAC;AAgCpB,MAAM,MAAM,iBAAiB,GAAG;IAC9B,yBAAyB;IACzB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB,CAAC;AAEF,gBAAgB;AAChB,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,UAAU,EAAE,IAAI,GAAE,iBAAsB,GAAG,MAAM,CAUpF;AAED,mCAAmC;AACnC,wBAAgB,qBAAqB,CAAC,CAAC,EAAE,UAAU,EAAE,IAAI,GAAE,iBAAsB,GAAG,MAAM,CAQzF"}
1
+ {"version":3,"file":"format-display.d.ts","sourceRoot":"","sources":["../../src/repl-windows/format-display.ts"],"names":[],"mappings":"AAIA,OAAO,EAGL,KAAK,UAAU,EAEhB,MAAM,YAAY,CAAC;AAiCpB,MAAM,MAAM,iBAAiB,GAAG;IAC9B,yBAAyB;IACzB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB,CAAC;AAEF,gBAAgB;AAChB,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,UAAU,EAAE,IAAI,GAAE,iBAAsB,GAAG,MAAM,CAapF;AAED,mCAAmC;AACnC,wBAAgB,qBAAqB,CAAC,CAAC,EAAE,UAAU,EAAE,IAAI,GAAE,iBAAsB,GAAG,MAAM,CAQzF"}
@@ -4,6 +4,7 @@ import {
4
4
  resolveDisplayLevel,
5
5
  visibleWidth
6
6
  } from "../logs.js";
7
+ import { getCompiledLogFilter, transformLogEntry } from "../log-filter.js";
7
8
  import { c, highlightLogLine } from "../theme.js";
8
9
  const LEVEL_PLAIN = {
9
10
  error: "[ERR]",
@@ -34,7 +35,10 @@ function formatLogDisplay(l, opts = {}) {
34
35
  const ts = c.dim(l.time.toLocaleTimeString());
35
36
  const level = resolveDisplayLevel(l);
36
37
  const lvl = levelTagDisplay(level);
37
- const txt = highlightLogLine(l.source === "bds" ? stripBdsLogPrefix(l.text) : l.text);
38
+ const body = l.source === "bds" ? stripBdsLogPrefix(l.text) : l.text;
39
+ const filter = getCompiledLogFilter();
40
+ const { entry } = transformLogEntry({ text: body, source: l.source, level }, filter);
41
+ const txt = highlightLogLine(entry.text);
38
42
  if (opts.omitSource) {
39
43
  return `${ts} ${lvl} ${txt}`;
40
44
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/repl-windows/format-display.ts"],
4
- "sourcesContent": ["/**\n * repl-windows/format-display.ts \u2014 \u4EC5 TTY \u5C55\u793A\uFF1B\u843D\u76D8\u4ECD\u7528 logs.formatLog / SDK formatLogLine\n */\nimport { stripBdsLogPrefix } from \"@sfmc-bds/sdk/logs\";\nimport {\n formatSourceTag,\n resolveDisplayLevel,\n type UnifiedLog,\n visibleWidth,\n} from \"../logs.js\";\nimport { c, highlightLogLine } from \"../theme.js\";\n\n/** \u4E0E logs.ts LEVEL_TAG_TEXT \u5BF9\u9F50\u7684\u65E0\u8272\u7EA7\u522B\uFF08\u907F\u514D\u6539\u52A8\u843D\u76D8\u8DEF\u5F84\uFF09 */\nconst LEVEL_PLAIN: Record<string, string> = {\n error: \"[ERR]\",\n warn: \"[WRN]\",\n success: \"[SUC]\",\n debug: \"[DBG]\",\n info: \"[INF]\",\n};\n\nfunction levelTagDisplay(lvl: string): string {\n const text = LEVEL_PLAIN[lvl] ?? LEVEL_PLAIN.info!;\n switch (lvl) {\n case \"error\":\n return c.red(text);\n case \"warn\":\n return c.yellow(text);\n case \"success\":\n return c.green(c.bold(text));\n case \"debug\":\n return c.dim(text);\n default:\n return c.blue(text);\n }\n}\n\nfunction levelTagPlain(lvl: string): string {\n return LEVEL_PLAIN[lvl] ?? LEVEL_PLAIN.info!;\n}\n\nexport type FormatDisplayOpts = {\n /** \u670D\u52A1\u7A97\u5185\u7701\u7565\u6765\u6E90\u6807\u7B7E\uFF08\u843D\u76D8\u4E0D\u53D7\u5F71\u54CD\uFF09 */\n omitSource?: boolean;\n};\n\n/** TTY \u5C55\u793A\u683C\u5F0F\u5316 */\nexport function formatLogDisplay(l: UnifiedLog, opts: FormatDisplayOpts = {}): string {\n const ts = c.dim(l.time.toLocaleTimeString());\n const level = resolveDisplayLevel(l);\n const lvl = levelTagDisplay(level);\n const txt = highlightLogLine(l.source === \"bds\" ? stripBdsLogPrefix(l.text) : l.text);\n if (opts.omitSource) {\n return `${ts} ${lvl} ${txt}`;\n }\n const src = formatSourceTag(l.source);\n return `${ts} ${src} ${lvl} ${txt}`;\n}\n\n/** \u4E0E formatLogDisplay \u5BF9\u9F50\u7684\u60AC\u6302\u7F29\u8FDB\u5BBD\u5EA6 */\nexport function logDisplayPrefixWidth(l: UnifiedLog, opts: FormatDisplayOpts = {}): number {\n const ts = l.time.toLocaleTimeString();\n const level = resolveDisplayLevel(l);\n const lvl = levelTagPlain(level);\n if (opts.omitSource) {\n return visibleWidth(`${ts} ${lvl} `);\n }\n return visibleWidth(`${ts} ${formatSourceTag(l.source)} ${lvl} `);\n}\n"],
5
- "mappings": "AAGA,SAAS,yBAAyB;AAClC;AAAA,EACE;AAAA,EACA;AAAA,EAEA;AAAA,OACK;AACP,SAAS,GAAG,wBAAwB;AAGpC,MAAM,cAAsC;AAAA,EAC1C,OAAO;AAAA,EACP,MAAM;AAAA,EACN,SAAS;AAAA,EACT,OAAO;AAAA,EACP,MAAM;AACR;AAEA,SAAS,gBAAgB,KAAqB;AAC5C,QAAM,OAAO,YAAY,GAAG,KAAK,YAAY;AAC7C,UAAQ,KAAK;AAAA,IACX,KAAK;AACH,aAAO,EAAE,IAAI,IAAI;AAAA,IACnB,KAAK;AACH,aAAO,EAAE,OAAO,IAAI;AAAA,IACtB,KAAK;AACH,aAAO,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;AAAA,IAC7B,KAAK;AACH,aAAO,EAAE,IAAI,IAAI;AAAA,IACnB;AACE,aAAO,EAAE,KAAK,IAAI;AAAA,EACtB;AACF;AAEA,SAAS,cAAc,KAAqB;AAC1C,SAAO,YAAY,GAAG,KAAK,YAAY;AACzC;AAQO,SAAS,iBAAiB,GAAe,OAA0B,CAAC,GAAW;AACpF,QAAM,KAAK,EAAE,IAAI,EAAE,KAAK,mBAAmB,CAAC;AAC5C,QAAM,QAAQ,oBAAoB,CAAC;AACnC,QAAM,MAAM,gBAAgB,KAAK;AACjC,QAAM,MAAM,iBAAiB,EAAE,WAAW,QAAQ,kBAAkB,EAAE,IAAI,IAAI,EAAE,IAAI;AACpF,MAAI,KAAK,YAAY;AACnB,WAAO,GAAG,EAAE,IAAI,GAAG,IAAI,GAAG;AAAA,EAC5B;AACA,QAAM,MAAM,gBAAgB,EAAE,MAAM;AACpC,SAAO,GAAG,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG;AACnC;AAGO,SAAS,sBAAsB,GAAe,OAA0B,CAAC,GAAW;AACzF,QAAM,KAAK,EAAE,KAAK,mBAAmB;AACrC,QAAM,QAAQ,oBAAoB,CAAC;AACnC,QAAM,MAAM,cAAc,KAAK;AAC/B,MAAI,KAAK,YAAY;AACnB,WAAO,aAAa,GAAG,EAAE,IAAI,GAAG,GAAG;AAAA,EACrC;AACA,SAAO,aAAa,GAAG,EAAE,IAAI,gBAAgB,EAAE,MAAM,CAAC,IAAI,GAAG,GAAG;AAClE;",
4
+ "sourcesContent": ["/**\n * repl-windows/format-display.ts \u2014 \u4EC5 TTY \u5C55\u793A\uFF1B\u843D\u76D8\u4ECD\u7528 logs.formatLog / SDK formatLogLine\n */\nimport { stripBdsLogPrefix } from \"@sfmc-bds/sdk/logs\";\nimport {\n formatSourceTag,\n resolveDisplayLevel,\n type UnifiedLog,\n visibleWidth,\n} from \"../logs.js\";\nimport { getCompiledLogFilter, transformLogEntry } from \"../log-filter.js\";\nimport { c, highlightLogLine } from \"../theme.js\";\n\n/** \u4E0E logs.ts LEVEL_TAG_TEXT \u5BF9\u9F50\u7684\u65E0\u8272\u7EA7\u522B\uFF08\u907F\u514D\u6539\u52A8\u843D\u76D8\u8DEF\u5F84\uFF09 */\nconst LEVEL_PLAIN: Record<string, string> = {\n error: \"[ERR]\",\n warn: \"[WRN]\",\n success: \"[SUC]\",\n debug: \"[DBG]\",\n info: \"[INF]\",\n};\n\nfunction levelTagDisplay(lvl: string): string {\n const text = LEVEL_PLAIN[lvl] ?? LEVEL_PLAIN.info!;\n switch (lvl) {\n case \"error\":\n return c.red(text);\n case \"warn\":\n return c.yellow(text);\n case \"success\":\n return c.green(c.bold(text));\n case \"debug\":\n return c.dim(text);\n default:\n return c.blue(text);\n }\n}\n\nfunction levelTagPlain(lvl: string): string {\n return LEVEL_PLAIN[lvl] ?? LEVEL_PLAIN.info!;\n}\n\nexport type FormatDisplayOpts = {\n /** \u670D\u52A1\u7A97\u5185\u7701\u7565\u6765\u6E90\u6807\u7B7E\uFF08\u843D\u76D8\u4E0D\u53D7\u5F71\u54CD\uFF09 */\n omitSource?: boolean;\n};\n\n/** TTY \u5C55\u793A\u683C\u5F0F\u5316 */\nexport function formatLogDisplay(l: UnifiedLog, opts: FormatDisplayOpts = {}): string {\n const ts = c.dim(l.time.toLocaleTimeString());\n const level = resolveDisplayLevel(l);\n const lvl = levelTagDisplay(level);\n const body = l.source === \"bds\" ? stripBdsLogPrefix(l.text) : l.text;\n const filter = getCompiledLogFilter();\n const { entry } = transformLogEntry({ text: body, source: l.source, level }, filter);\n const txt = highlightLogLine(entry.text);\n if (opts.omitSource) {\n return `${ts} ${lvl} ${txt}`;\n }\n const src = formatSourceTag(l.source);\n return `${ts} ${src} ${lvl} ${txt}`;\n}\n\n/** \u4E0E formatLogDisplay \u5BF9\u9F50\u7684\u60AC\u6302\u7F29\u8FDB\u5BBD\u5EA6 */\nexport function logDisplayPrefixWidth(l: UnifiedLog, opts: FormatDisplayOpts = {}): number {\n const ts = l.time.toLocaleTimeString();\n const level = resolveDisplayLevel(l);\n const lvl = levelTagPlain(level);\n if (opts.omitSource) {\n return visibleWidth(`${ts} ${lvl} `);\n }\n return visibleWidth(`${ts} ${formatSourceTag(l.source)} ${lvl} `);\n}\n"],
5
+ "mappings": "AAGA,SAAS,yBAAyB;AAClC;AAAA,EACE;AAAA,EACA;AAAA,EAEA;AAAA,OACK;AACP,SAAS,sBAAsB,yBAAyB;AACxD,SAAS,GAAG,wBAAwB;AAGpC,MAAM,cAAsC;AAAA,EAC1C,OAAO;AAAA,EACP,MAAM;AAAA,EACN,SAAS;AAAA,EACT,OAAO;AAAA,EACP,MAAM;AACR;AAEA,SAAS,gBAAgB,KAAqB;AAC5C,QAAM,OAAO,YAAY,GAAG,KAAK,YAAY;AAC7C,UAAQ,KAAK;AAAA,IACX,KAAK;AACH,aAAO,EAAE,IAAI,IAAI;AAAA,IACnB,KAAK;AACH,aAAO,EAAE,OAAO,IAAI;AAAA,IACtB,KAAK;AACH,aAAO,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;AAAA,IAC7B,KAAK;AACH,aAAO,EAAE,IAAI,IAAI;AAAA,IACnB;AACE,aAAO,EAAE,KAAK,IAAI;AAAA,EACtB;AACF;AAEA,SAAS,cAAc,KAAqB;AAC1C,SAAO,YAAY,GAAG,KAAK,YAAY;AACzC;AAQO,SAAS,iBAAiB,GAAe,OAA0B,CAAC,GAAW;AACpF,QAAM,KAAK,EAAE,IAAI,EAAE,KAAK,mBAAmB,CAAC;AAC5C,QAAM,QAAQ,oBAAoB,CAAC;AACnC,QAAM,MAAM,gBAAgB,KAAK;AACjC,QAAM,OAAO,EAAE,WAAW,QAAQ,kBAAkB,EAAE,IAAI,IAAI,EAAE;AAChE,QAAM,SAAS,qBAAqB;AACpC,QAAM,EAAE,MAAM,IAAI,kBAAkB,EAAE,MAAM,MAAM,QAAQ,EAAE,QAAQ,MAAM,GAAG,MAAM;AACnF,QAAM,MAAM,iBAAiB,MAAM,IAAI;AACvC,MAAI,KAAK,YAAY;AACnB,WAAO,GAAG,EAAE,IAAI,GAAG,IAAI,GAAG;AAAA,EAC5B;AACA,QAAM,MAAM,gBAAgB,EAAE,MAAM;AACpC,SAAO,GAAG,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG;AACnC;AAGO,SAAS,sBAAsB,GAAe,OAA0B,CAAC,GAAW;AACzF,QAAM,KAAK,EAAE,KAAK,mBAAmB;AACrC,QAAM,QAAQ,oBAAoB,CAAC;AACnC,QAAM,MAAM,cAAc,KAAK;AAC/B,MAAI,KAAK,YAAY;AACnB,WAAO,aAAa,GAAG,EAAE,IAAI,GAAG,GAAG;AAAA,EACrC;AACA,SAAO,aAAa,GAAG,EAAE,IAAI,gBAAgB,EAAE,MAAM,CAAC,IAAI,GAAG,GAAG;AAClE;",
6
6
  "names": []
7
7
  }
@@ -34,15 +34,18 @@ export declare class WindowHost {
34
34
  setBuffer(id: string, lines: string[]): void;
35
35
  invalidateBuffer(id: string): void;
36
36
  private appendToBuffer;
37
- /** 按活跃服务同步 ServiceWindow id 列表(id = svc:<name>) */
37
+ /** 按活跃服务与平台窗同步轮转 id 列表(id = svc:<name> 或 sfmc) */
38
38
  setServiceOrder(ids: string[]): void;
39
39
  open(id: string): boolean;
40
40
  back(): boolean;
41
41
  /**
42
- * 在服务窗之间循环;返回新激活窗的 serviceName(供同步发送目标)。
42
+ * 在服务窗与平台窗之间循环;返回是否成功切换及新激活窗的 serviceName(供同步发送目标)。
43
43
  * 若当前在非服务窗,先回到服务环。
44
44
  */
45
- cycleServiceWindows(): ServiceName | null;
45
+ cycleServiceWindows(): {
46
+ switched: boolean;
47
+ serviceName: ServiceName | null;
48
+ };
46
49
  /**
47
50
  * 新日志:写入所有已 seed 缓存且 accept 的窗口;仅活动窗刷到 TTY。
48
51
  * 活动窗尚未 seed:只刷 TTY(随后 showActiveWindow 会 seed 含历史的缓存)。
@@ -1 +1 @@
1
- {"version":3,"file":"host.d.ts","sourceRoot":"","sources":["../../src/repl-windows/host.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAe,KAAK,UAAU,EAAE,MAAM,YAAY,CAAC;AAC1D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAE5F,MAAM,MAAM,YAAY,GAAG,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;AAEzD,qBAAa,UAAU;IACrB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAiC;IACzD,6CAA6C;IAC7C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA+B;IACvD,qBAAqB;IACrB,OAAO,CAAC,YAAY,CAAgB;IACpC,OAAO,CAAC,QAAQ,CAAuB;IACvC,OAAO,CAAC,UAAU,CAAuB;IACzC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAe;IACxC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAA2B;IAE1D,YAAY,IAAI,EAAE;QAAE,QAAQ,EAAE,YAAY,CAAC;QAAC,cAAc,CAAC,EAAE,MAAM,IAAI,CAAA;KAAE,EAGxE;IAED,QAAQ,CAAC,GAAG,EAAE,UAAU,GAAG,IAAI,CAE9B;IAED,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAS3B;IAED,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAEvB;IAED,SAAS,IAAI,UAAU,GAAG,SAAS,CAElC;IAED,WAAW,IAAI,MAAM,GAAG,IAAI,CAE3B;IAED,SAAS,IAAI,YAAY,CAUxB;IAED,6BAA6B;IAC7B,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAE7B;IAED,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAEvC;IAED,iBAAiB;IACjB,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,CAE3C;IAED,gBAAgB,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAEjC;IAED,OAAO,CAAC,cAAc;IAStB,mDAAmD;IACnD,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI,CAenC;IAED,IAAI,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAiBxB;IAED,IAAI,IAAI,OAAO,CAYd;IAED;;;OAGG;IACH,mBAAmB,IAAI,WAAW,GAAG,IAAI,CAWxC;IAED;;;OAGG;IACH,QAAQ,CAAC,GAAG,EAAE,UAAU,GAAG,IAAI,CAe9B;IAED,iCAAiC;IACjC,eAAe,CAAC,GAAG,EAAE,UAAU,GAAG;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAIxE;IAED,KAAK,CAAC,EAAE,EAAE,cAAc,GAAG,eAAe,CASzC;IAED,YAAY,IAAI,OAAO,CAEtB;CACF;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,WAAW,GAAG,MAAM,CAEzD"}
1
+ {"version":3,"file":"host.d.ts","sourceRoot":"","sources":["../../src/repl-windows/host.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAe,KAAK,UAAU,EAAE,MAAM,YAAY,CAAC;AAC1D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAElD,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAE5F,MAAM,MAAM,YAAY,GAAG,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;AAEzD,qBAAa,UAAU;IACrB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAiC;IACzD,6CAA6C;IAC7C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA+B;IACvD,qBAAqB;IACrB,OAAO,CAAC,YAAY,CAAgB;IACpC,OAAO,CAAC,QAAQ,CAAuB;IACvC,OAAO,CAAC,UAAU,CAAuB;IACzC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAe;IACxC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAA2B;IAE1D,YAAY,IAAI,EAAE;QAAE,QAAQ,EAAE,YAAY,CAAC;QAAC,cAAc,CAAC,EAAE,MAAM,IAAI,CAAA;KAAE,EAGxE;IAED,QAAQ,CAAC,GAAG,EAAE,UAAU,GAAG,IAAI,CAE9B;IAED,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAS3B;IAED,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAEvB;IAED,SAAS,IAAI,UAAU,GAAG,SAAS,CAElC;IAED,WAAW,IAAI,MAAM,GAAG,IAAI,CAE3B;IAED,SAAS,IAAI,YAAY,CAUxB;IAED,6BAA6B;IAC7B,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAE7B;IAED,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAEvC;IAED,iBAAiB;IACjB,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,CAE3C;IAED,gBAAgB,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAEjC;IAED,OAAO,CAAC,cAAc;IAStB,kDAAkD;IAClD,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI,CAqBnC;IAED,IAAI,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAiBxB;IAED,IAAI,IAAI,OAAO,CAYd;IAED;;;OAGG;IACH,mBAAmB,IAAI;QAAE,QAAQ,EAAE,OAAO,CAAC;QAAC,WAAW,EAAE,WAAW,GAAG,IAAI,CAAA;KAAE,CAc5E;IAED;;;OAGG;IACH,QAAQ,CAAC,GAAG,EAAE,UAAU,GAAG,IAAI,CAe9B;IAED,iCAAiC;IACjC,eAAe,CAAC,GAAG,EAAE,UAAU,GAAG;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAIxE;IAED,KAAK,CAAC,EAAE,EAAE,cAAc,GAAG,eAAe,CASzC;IAED,YAAY,IAAI,OAAO,CAEtB;CACF;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,WAAW,GAAG,MAAM,CAEzD"}
@@ -1,4 +1,5 @@
1
1
  import { wrapLogLine } from "../logs.js";
2
+ import { SFMC_WINDOW_ID } from "./sfmc-window.js";
2
3
  class WindowHost {
3
4
  windows = /* @__PURE__ */ new Map();
4
5
  /** 窗口 id → 已渲染(已 wrap)的行;切回时直接 dump,无需重拉源 */
@@ -68,17 +69,19 @@ class WindowHost {
68
69
  }
69
70
  buf.push(wrappedLine);
70
71
  }
71
- /** 按活跃服务同步 ServiceWindow id 列表(id = svc:<name>) */
72
+ /** 按活跃服务与平台窗同步轮转 id 列表(id = svc:<name> 或 sfmc) */
72
73
  setServiceOrder(ids) {
73
74
  this.serviceOrder = [...ids];
74
- const stale = [...this.windows.keys()].filter((id) => id.startsWith("svc:") && !ids.includes(id));
75
+ const stale = [...this.windows.keys()].filter(
76
+ (id) => (id.startsWith("svc:") || id === SFMC_WINDOW_ID) && !ids.includes(id)
77
+ );
75
78
  for (const id of stale) {
76
79
  this.windows.delete(id);
77
80
  this.buffers.delete(id);
78
81
  if (this.activeId === id) this.activeId = null;
79
82
  if (this.previousId === id) this.previousId = null;
80
83
  }
81
- if (this.activeId?.startsWith("svc:") && !ids.includes(this.activeId)) {
84
+ if (this.activeId && (this.activeId.startsWith("svc:") || this.activeId === SFMC_WINDOW_ID) && !ids.includes(this.activeId)) {
82
85
  this.activeId = null;
83
86
  }
84
87
  if (!this.activeId && ids.length > 0) {
@@ -114,11 +117,11 @@ class WindowHost {
114
117
  return this.open(fallback);
115
118
  }
116
119
  /**
117
- * 在服务窗之间循环;返回新激活窗的 serviceName(供同步发送目标)。
120
+ * 在服务窗与平台窗之间循环;返回是否成功切换及新激活窗的 serviceName(供同步发送目标)。
118
121
  * 若当前在非服务窗,先回到服务环。
119
122
  */
120
123
  cycleServiceWindows() {
121
- if (this.serviceOrder.length === 0) return null;
124
+ if (this.serviceOrder.length === 0) return { switched: false, serviceName: null };
122
125
  const cur = this.activeId;
123
126
  const idx = cur ? this.serviceOrder.indexOf(cur) : -1;
124
127
  if (idx < 0) {
@@ -127,7 +130,10 @@ class WindowHost {
127
130
  const next = this.serviceOrder[(idx + 1) % this.serviceOrder.length];
128
131
  this.open(next);
129
132
  }
130
- return this.getActive()?.serviceName ?? null;
133
+ return {
134
+ switched: true,
135
+ serviceName: this.getActive()?.serviceName ?? null
136
+ };
131
137
  }
132
138
  /**
133
139
  * 新日志:写入所有已 seed 缓存且 accept 的窗口;仅活动窗刷到 TTY。