@sfmc-bds/cli 0.2.0-beta.8 → 0.2.0

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 (149) 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.js +3 -3
  8. package/dist/command-surface.js.map +2 -2
  9. package/dist/commands.d.ts +57 -4
  10. package/dist/commands.d.ts.map +1 -1
  11. package/dist/commands.js +184 -68
  12. package/dist/commands.js.map +2 -2
  13. package/dist/directory-picker.d.ts +27 -0
  14. package/dist/directory-picker.d.ts.map +1 -0
  15. package/dist/directory-picker.js +112 -0
  16. package/dist/directory-picker.js.map +7 -0
  17. package/dist/help-text.d.ts.map +1 -1
  18. package/dist/help-text.js +1 -5
  19. package/dist/help-text.js.map +2 -2
  20. package/dist/i18n/locales/en.d.ts +49 -14
  21. package/dist/i18n/locales/en.d.ts.map +1 -1
  22. package/dist/i18n/locales/en.js +49 -15
  23. package/dist/i18n/locales/en.js.map +2 -2
  24. package/dist/i18n/locales/zh-CN.d.ts.map +1 -1
  25. package/dist/i18n/locales/zh-CN.js +50 -16
  26. package/dist/i18n/locales/zh-CN.js.map +2 -2
  27. package/dist/index.d.ts +1 -1
  28. package/dist/index.d.ts.map +1 -1
  29. package/dist/index.js +2 -0
  30. package/dist/index.js.map +2 -2
  31. package/dist/interactive-prompts.d.ts +1 -2
  32. package/dist/interactive-prompts.d.ts.map +1 -1
  33. package/dist/interactive-prompts.js +12 -23
  34. package/dist/interactive-prompts.js.map +3 -3
  35. package/dist/llbot-launch.d.ts +20 -0
  36. package/dist/llbot-launch.d.ts.map +1 -0
  37. package/dist/llbot-launch.js +40 -0
  38. package/dist/llbot-launch.js.map +7 -0
  39. package/dist/log-filter.d.ts +18 -2
  40. package/dist/log-filter.d.ts.map +1 -1
  41. package/dist/log-filter.js +54 -4
  42. package/dist/log-filter.js.map +2 -2
  43. package/dist/log-translator.d.ts +36 -0
  44. package/dist/log-translator.d.ts.map +1 -0
  45. package/dist/log-translator.js +279 -0
  46. package/dist/log-translator.js.map +7 -0
  47. package/dist/logs.d.ts +2 -0
  48. package/dist/logs.d.ts.map +1 -1
  49. package/dist/logs.js +24 -11
  50. package/dist/logs.js.map +2 -2
  51. package/dist/main.js +9 -6
  52. package/dist/main.js.map +2 -2
  53. package/dist/module-commands.d.ts.map +1 -1
  54. package/dist/module-commands.js +22 -8
  55. package/dist/module-commands.js.map +2 -2
  56. package/dist/module-fingerprint.d.ts.map +1 -1
  57. package/dist/module-fingerprint.js +1 -0
  58. package/dist/module-fingerprint.js.map +2 -2
  59. package/dist/module-pack-build.d.ts +14 -4
  60. package/dist/module-pack-build.d.ts.map +1 -1
  61. package/dist/module-pack-build.js +81 -108
  62. package/dist/module-pack-build.js.map +2 -2
  63. package/dist/module-toggle.d.ts +1 -1
  64. package/dist/module-toggle.d.ts.map +1 -1
  65. package/dist/module-toggle.js.map +1 -1
  66. package/dist/node-service-probe.d.ts +18 -0
  67. package/dist/node-service-probe.d.ts.map +1 -0
  68. package/dist/node-service-probe.js +97 -0
  69. package/dist/node-service-probe.js.map +7 -0
  70. package/dist/pack-lifecycle.d.ts +15 -1
  71. package/dist/pack-lifecycle.d.ts.map +1 -1
  72. package/dist/pack-lifecycle.js +249 -16
  73. package/dist/pack-lifecycle.js.map +2 -2
  74. package/dist/player-session.d.ts +13 -0
  75. package/dist/player-session.d.ts.map +1 -0
  76. package/dist/player-session.js +26 -0
  77. package/dist/player-session.js.map +7 -0
  78. package/dist/registry.d.ts +1 -1
  79. package/dist/registry.d.ts.map +1 -1
  80. package/dist/registry.js +4 -1
  81. package/dist/registry.js.map +2 -2
  82. package/dist/repl-windows/format-display.d.ts.map +1 -1
  83. package/dist/repl-windows/format-display.js +5 -1
  84. package/dist/repl-windows/format-display.js.map +2 -2
  85. package/dist/repl-windows/host.d.ts +6 -3
  86. package/dist/repl-windows/host.d.ts.map +1 -1
  87. package/dist/repl-windows/host.js +12 -6
  88. package/dist/repl-windows/host.js.map +2 -2
  89. package/dist/repl-windows/index.d.ts +1 -0
  90. package/dist/repl-windows/index.d.ts.map +1 -1
  91. package/dist/repl-windows/index.js +3 -0
  92. package/dist/repl-windows/index.js.map +2 -2
  93. package/dist/repl-windows/service-window.d.ts +1 -1
  94. package/dist/repl-windows/service-window.d.ts.map +1 -1
  95. package/dist/repl-windows/service-window.js +9 -1
  96. package/dist/repl-windows/service-window.js.map +2 -2
  97. package/dist/repl-windows/sfmc-window.d.ts +7 -0
  98. package/dist/repl-windows/sfmc-window.d.ts.map +1 -0
  99. package/dist/repl-windows/sfmc-window.js +28 -0
  100. package/dist/repl-windows/sfmc-window.js.map +7 -0
  101. package/dist/repl.d.ts.map +1 -1
  102. package/dist/repl.js +37 -22
  103. package/dist/repl.js.map +2 -2
  104. package/dist/runtime.d.ts +2 -2
  105. package/dist/runtime.d.ts.map +1 -1
  106. package/dist/runtime.js +15 -2
  107. package/dist/runtime.js.map +2 -2
  108. package/dist/send-target.d.ts +2 -0
  109. package/dist/send-target.d.ts.map +1 -1
  110. package/dist/send-target.js +12 -2
  111. package/dist/send-target.js.map +2 -2
  112. package/dist/services.d.ts +58 -5
  113. package/dist/services.d.ts.map +1 -1
  114. package/dist/services.js +273 -50
  115. package/dist/services.js.map +2 -2
  116. package/dist/sfmc-modules-root.d.ts.map +1 -1
  117. package/dist/sfmc-modules-root.js +6 -2
  118. package/dist/sfmc-modules-root.js.map +2 -2
  119. package/dist/ui-command.d.ts +6 -0
  120. package/dist/ui-command.d.ts.map +1 -0
  121. package/dist/ui-command.js +68 -0
  122. package/dist/ui-command.js.map +7 -0
  123. package/dist/wizard.d.ts.map +1 -1
  124. package/dist/wizard.js +95 -32
  125. package/dist/wizard.js.map +2 -2
  126. package/dist/world-packs.d.ts +2 -0
  127. package/dist/world-packs.d.ts.map +1 -1
  128. package/dist/world-packs.js +161 -18
  129. package/dist/world-packs.js.map +2 -2
  130. package/package.json +21 -15
  131. package/scripts/module-install/check-modules.mjs +178 -0
  132. package/scripts/module-install/fetch-module.mjs +1083 -0
  133. package/scripts/module-install/lib/catalog.mjs +96 -0
  134. package/scripts/module-install/lib/config-seeding.mjs +128 -0
  135. package/scripts/module-install/lib/io.mjs +37 -0
  136. package/scripts/module-install/lib/link-from.mjs +80 -0
  137. package/scripts/module-install/lib/lock.mjs +78 -0
  138. package/scripts/module-install/lib/npm-resolver.mjs +55 -0
  139. package/scripts/module-install/lib/packages.mjs +136 -0
  140. package/scripts/module-install/lib/paths.mjs +48 -0
  141. package/scripts/module-install/lib/registry-index.mjs +50 -0
  142. package/dist/cmd-remote.d.ts +0 -13
  143. package/dist/cmd-remote.d.ts.map +0 -1
  144. package/dist/cmd-remote.js +0 -38
  145. package/dist/cmd-remote.js.map +0 -7
  146. package/dist/remote-agent.d.ts +0 -18
  147. package/dist/remote-agent.d.ts.map +0 -1
  148. package/dist/remote-agent.js +0 -198
  149. package/dist/remote-agent.js.map +0 -7
@@ -1,5 +1,6 @@
1
1
  import {
2
2
  configPath,
3
+ DEFAULT_DB_CONFIG,
3
4
  modulePath,
4
5
  readJson,
5
6
  writeJson
@@ -25,7 +26,10 @@ import {
25
26
  readLevelNameSync,
26
27
  readPackManifestHeader,
27
28
  readWorldPackList,
28
- worldPackListHas as pmWorldPackListHas
29
+ worldPackListHas as pmWorldPackListHas,
30
+ BASELINE_BEDROCK_DEPENDENCIES,
31
+ negotiateBedrockDependencies,
32
+ NATIVE_BEDROCK_SCRIPT_MODULES
29
33
  } from "@sfmc-bds/bds-tools/pack-manager-lib";
30
34
  import { ROOT, PACKAGES_DIR, resolveSdkPackageRoot, getRoot } from "./runtime.js";
31
35
  import { c } from "./theme.js";
@@ -33,7 +37,7 @@ const BP_NAME = "sfmc-modules";
33
37
  const RP_NAME = "sfmc-modules-rp";
34
38
  const DEPLOY_CATALOG_NAME = "sfmc-deploy-catalog.json";
35
39
  const DEFAULT_PACK_VERSION = [1, 0, 0];
36
- function createSdkResolvePlugin(sdkRoot) {
40
+ function createSdkResolvePlugin(sdkRoot, dbPort) {
37
41
  const pkg = JSON.parse(readFileSync(path.join(sdkRoot, "package.json"), "utf8"));
38
42
  const exportsMap = pkg.exports ?? {};
39
43
  function resolveExportSubpath(subpath) {
@@ -48,9 +52,59 @@ function createSdkResolvePlugin(sdkRoot) {
48
52
  return {
49
53
  name: "sfmc-sdk-resolve",
50
54
  setup(build) {
55
+ build.onResolve({ filter: /^sfmc:host$/ }, () => ({
56
+ path: "sfmc:host",
57
+ namespace: "sfmc-host"
58
+ }));
59
+ build.onLoad({ filter: /.*/, namespace: "sfmc-host" }, () => ({
60
+ contents: [
61
+ 'import { installHostBootstrap } from "@sfmc-bds/sdk/module-loader/install";',
62
+ `installHostBootstrap({ dbServerUrl: ${JSON.stringify(`http://127.0.0.1:${dbPort}`)} });`
63
+ ].join("\n"),
64
+ loader: "ts"
65
+ }));
51
66
  build.onResolve({ filter: /^@sfmc(?:-bds)?\/sdk(?:\/|$)/ }, (args) => {
52
67
  const normalized = args.path.replace(/^@sfmc\/sdk/, "@sfmc-bds/sdk");
53
68
  const sub = normalized === "@sfmc-bds/sdk" ? "" : normalized.slice("@sfmc-bds/sdk/".length);
69
+ const importerNorm = (args.importer || "").replace(/\\/g, "/");
70
+ const sapiIdx = importerNorm.indexOf("/sapi/");
71
+ if (sapiIdx !== -1 && !importerNorm.includes("@sfmc-sdk") && !importerNorm.includes("@sfmc/sdk")) {
72
+ const sapiDir = importerNorm.slice(0, sapiIdx + "/sapi".length);
73
+ const manifestFile = path.join(sapiDir, "manifest.json");
74
+ let logicalId = "";
75
+ let configKey = "";
76
+ if (existsSync(manifestFile)) {
77
+ try {
78
+ const man = JSON.parse(readFileSync(manifestFile, "utf8"));
79
+ if (man.id) logicalId = man.id;
80
+ if (man.configKey) configKey = man.configKey;
81
+ } catch {
82
+ }
83
+ }
84
+ if (!logicalId) {
85
+ const rootDir = importerNorm.slice(0, sapiIdx);
86
+ logicalId = path.basename(rootDir).replace(/^sfmc-module-/, "");
87
+ configKey = logicalId;
88
+ }
89
+ if (sub === "sapi/db") {
90
+ return {
91
+ path: `sfmc-scoped:db?mod=${encodeURIComponent(logicalId)}`,
92
+ namespace: "sfmc-scoped-db"
93
+ };
94
+ }
95
+ if (sub === "sapi/config") {
96
+ return {
97
+ path: `sfmc-scoped:config?cfg=${encodeURIComponent(configKey)}`,
98
+ namespace: "sfmc-scoped-config"
99
+ };
100
+ }
101
+ if (sub === "sapi/service") {
102
+ return {
103
+ path: `sfmc-scoped:service?mod=${encodeURIComponent(logicalId)}`,
104
+ namespace: "sfmc-scoped-service"
105
+ };
106
+ }
107
+ }
54
108
  const resolved = resolveExportSubpath(sub);
55
109
  if (!resolved) {
56
110
  return {
@@ -61,7 +115,64 @@ function createSdkResolvePlugin(sdkRoot) {
61
115
  ]
62
116
  };
63
117
  }
64
- return { path: resolved };
118
+ return { path: resolved, namespace: "file" };
119
+ });
120
+ build.onLoad({ filter: /.*/, namespace: "sfmc-scoped-db" }, (args) => {
121
+ const u = new URL(args.path);
122
+ const mod = u.searchParams.get("mod") || "";
123
+ return {
124
+ contents: [
125
+ 'import { getDbClient } from "@sfmc-bds/sdk/sapi/db";',
126
+ 'export * from "@sfmc-bds/sdk/sapi/db";',
127
+ "export const db = new Proxy({}, {",
128
+ " get(_t, prop) {",
129
+ ` const c = getDbClient(${JSON.stringify(mod)});`,
130
+ " const val = (c as any)[prop];",
131
+ ' return typeof val === "function" ? val.bind(c) : val;',
132
+ " }",
133
+ "});"
134
+ ].join("\n"),
135
+ loader: "ts",
136
+ resolveDir: sdkRoot
137
+ };
138
+ });
139
+ build.onLoad({ filter: /.*/, namespace: "sfmc-scoped-config" }, (args) => {
140
+ const u = new URL(args.path);
141
+ const cfg = u.searchParams.get("cfg") || "";
142
+ return {
143
+ contents: [
144
+ 'import { getConfigClient } from "@sfmc-bds/sdk/sapi/config";',
145
+ 'export * from "@sfmc-bds/sdk/sapi/config";',
146
+ "export const config = new Proxy({}, {",
147
+ " get(_t, prop) {",
148
+ ` const c = getConfigClient(${JSON.stringify(cfg)});`,
149
+ " const val = (c as any)[prop];",
150
+ ' return typeof val === "function" ? val.bind(c) : val;',
151
+ " }",
152
+ "});"
153
+ ].join("\n"),
154
+ loader: "ts",
155
+ resolveDir: sdkRoot
156
+ };
157
+ });
158
+ build.onLoad({ filter: /.*/, namespace: "sfmc-scoped-service" }, (args) => {
159
+ const u = new URL(args.path);
160
+ const mod = u.searchParams.get("mod") || "";
161
+ return {
162
+ contents: [
163
+ 'import { getServiceClient } from "@sfmc-bds/sdk/sapi/service";',
164
+ 'export * from "@sfmc-bds/sdk/sapi/service";',
165
+ "export const service = new Proxy({}, {",
166
+ " get(_t, prop) {",
167
+ ` const c = getServiceClient(${JSON.stringify(mod)});`,
168
+ " const val = (c as any)[prop];",
169
+ ' return typeof val === "function" ? val.bind(c) : val;',
170
+ " }",
171
+ "});"
172
+ ].join("\n"),
173
+ loader: "ts",
174
+ resolveDir: sdkRoot
175
+ };
65
176
  });
66
177
  }
67
178
  };
@@ -90,12 +201,21 @@ function lockPath() {
90
201
  function catalogPath() {
91
202
  return modulePath(path.join(ROOT, "modules"), "catalog.json");
92
203
  }
204
+ function configuredDbPort(root) {
205
+ const configured = readJson(configPath(root, "db_config.json"));
206
+ const port = configured?.db_port ?? DEFAULT_DB_CONFIG.db_port ?? 3001;
207
+ if (!Number.isInteger(port) || port < 1 || port > 65535) {
208
+ throw new Error(`configs/db_config.json: db_port \u5FC5\u987B\u662F 1\u201365535 \u7684\u6574\u6570 (\u5F53\u524D ${port})`);
209
+ }
210
+ return port;
211
+ }
93
212
  function resolveBdsContext(root = getRoot()) {
94
213
  const cfg = readJson(configPath(root, "bds_updater.json")) ?? {};
95
- const bdsRoot = cfg.bds_path;
96
- if (!bdsRoot) {
214
+ const rawBds = cfg.bds_path;
215
+ if (!rawBds) {
97
216
  throw new Error("bds_path not configured. Run `sfmc init` first.");
98
217
  }
218
+ const bdsRoot = path.isAbsolute(rawBds) ? rawBds : path.resolve(root, rawBds);
99
219
  return { bdsRoot, levelName: readLevelNameSync(bdsRoot) };
100
220
  }
101
221
  function deployedBpDir(bdsRoot, levelName) {
@@ -124,11 +244,71 @@ function collectDeployedPackUuids(bdsRoot, levelName) {
124
244
  if (liveRp?.uuid) rp.add(liveRp.uuid);
125
245
  return { bp, rp };
126
246
  }
247
+ async function extractModuleBedrockDependencies(modPath) {
248
+ const deps = [];
249
+ const seen = /* @__PURE__ */ new Set();
250
+ const manifestPath = path.join(modPath, "sapi", "manifest.json");
251
+ if (existsSync(manifestPath)) {
252
+ try {
253
+ const raw = JSON.parse(await fs.readFile(manifestPath, "utf8"));
254
+ if (Array.isArray(raw.dependencies)) {
255
+ for (const d of raw.dependencies) {
256
+ if (d && typeof d === "object" && typeof d.module_name === "string" && d.module_name.startsWith("@minecraft/") && NATIVE_BEDROCK_SCRIPT_MODULES.has(d.module_name)) {
257
+ const modName = d.module_name;
258
+ const ver = String(d.version ?? "1.0.0");
259
+ const uuid = typeof d.uuid === "string" ? d.uuid : void 0;
260
+ deps.push({ module_name: modName, version: ver, ...uuid ? { uuid } : {} });
261
+ seen.add(modName);
262
+ }
263
+ }
264
+ } else if (raw.dependencies && typeof raw.dependencies === "object") {
265
+ for (const [modName, ver] of Object.entries(raw.dependencies)) {
266
+ if (modName.startsWith("@minecraft/") && !seen.has(modName) && NATIVE_BEDROCK_SCRIPT_MODULES.has(modName)) {
267
+ deps.push({ module_name: modName, version: String(ver ?? "1.0.0") });
268
+ seen.add(modName);
269
+ }
270
+ }
271
+ }
272
+ if (raw.minecraft && typeof raw.minecraft === "object") {
273
+ const mc = raw.minecraft;
274
+ const mcDeps = Array.isArray(mc.dependencies) ? mc.dependencies : mc;
275
+ if (typeof mcDeps === "object" && !Array.isArray(mcDeps)) {
276
+ for (const [modName, ver] of Object.entries(mcDeps)) {
277
+ if (modName.startsWith("@minecraft/") && !seen.has(modName) && NATIVE_BEDROCK_SCRIPT_MODULES.has(modName)) {
278
+ deps.push({ module_name: modName, version: String(ver ?? "1.0.0") });
279
+ seen.add(modName);
280
+ }
281
+ }
282
+ }
283
+ }
284
+ } catch {
285
+ }
286
+ }
287
+ const pkgPath = path.join(modPath, "package.json");
288
+ if (existsSync(pkgPath)) {
289
+ try {
290
+ const pkg = JSON.parse(await fs.readFile(pkgPath, "utf8"));
291
+ const candidateMap = {
292
+ ...pkg.devDependencies ?? {},
293
+ ...pkg.dependencies ?? {},
294
+ ...pkg.peerDependencies ?? {}
295
+ };
296
+ for (const [modName, ver] of Object.entries(candidateMap)) {
297
+ if (modName.startsWith("@minecraft/") && !seen.has(modName) && NATIVE_BEDROCK_SCRIPT_MODULES.has(modName)) {
298
+ deps.push({ module_name: modName, version: ver });
299
+ seen.add(modName);
300
+ }
301
+ }
302
+ } catch {
303
+ }
304
+ }
305
+ return deps;
306
+ }
127
307
  async function scanLocalModules() {
128
308
  const dir = packagesDir();
129
309
  if (!existsSync(dir)) return [];
130
310
  const lock = readJson(lockPath()) ?? { version: 1, modules: {} };
131
- const cat = readJson(catalogPath()) ?? {};
311
+ const cat = readJson(catalogPath()) ?? { version: 1, modules: [] };
132
312
  const defaults = /* @__PURE__ */ new Map();
133
313
  if (Array.isArray(cat.modules)) {
134
314
  for (const m of cat.modules) {
@@ -140,9 +320,15 @@ async function scanLocalModules() {
140
320
  const entries = await fs.readdir(dir, { withFileTypes: true });
141
321
  const out = [];
142
322
  for (const e of entries) {
143
- if (!e.isDirectory()) continue;
323
+ if (e.name.startsWith(".")) continue;
144
324
  const folderId = e.name;
145
325
  const modPath = path.join(dir, folderId);
326
+ try {
327
+ const st = await fs.stat(modPath);
328
+ if (!st.isDirectory()) continue;
329
+ } catch {
330
+ continue;
331
+ }
146
332
  const manifestPath = path.join(modPath, "sapi", "manifest.json");
147
333
  const entryPath = path.join(modPath, "sapi", "src", "index.ts");
148
334
  let logicalId = folderId;
@@ -160,6 +346,7 @@ async function scanLocalModules() {
160
346
  const hasResourcePack = existsSync(path.join(modPath, "resource_pack"));
161
347
  const fingerprint = await dirFingerprint(modPath);
162
348
  const enabled = isModuleEnabled(logicalId, lock, defaults);
349
+ const declaredDependencies = await extractModuleBedrockDependencies(modPath);
163
350
  out.push({
164
351
  folderId,
165
352
  logicalId,
@@ -168,7 +355,8 @@ async function scanLocalModules() {
168
355
  hasSapi,
169
356
  hasResourcePack,
170
357
  fingerprint,
171
- entryPath: hasSapi ? entryPath : null
358
+ entryPath: hasSapi ? entryPath : null,
359
+ declaredDependencies
172
360
  });
173
361
  }
174
362
  out.sort((a, b) => a.folderId.localeCompare(b.folderId));
@@ -201,8 +389,26 @@ async function computeDesiredCatalog(opts) {
201
389
  rpVersion = opts?.rpVersion ?? localRp?.version ?? DEFAULT_PACK_VERSION;
202
390
  rpModuleUuid = opts?.rpModuleUuid ?? localRp?.moduleUuid;
203
391
  }
392
+ let sdkVersion;
393
+ try {
394
+ const sdkRoot = resolveSdkPackageRoot();
395
+ const pkg = JSON.parse(readFileSync(path.join(sdkRoot, "package.json"), "utf8"));
396
+ sdkVersion = pkg.version;
397
+ } catch {
398
+ }
399
+ const enabledModuleReqs = mods.filter((m) => m.enabled && m.declaredDependencies.length > 0).map((m) => ({ folderId: m.folderId, dependencies: m.declaredDependencies }));
400
+ const negotiated = negotiateBedrockDependencies(BASELINE_BEDROCK_DEPENDENCIES, enabledModuleReqs);
401
+ if (negotiated.promotions.length > 0) {
402
+ for (const p of negotiated.promotions) {
403
+ packLog(
404
+ `promoted ${p.moduleName} ${p.from} -> ${p.to} (requested by: ${p.requestedBy.join(", ")})`,
405
+ "info"
406
+ );
407
+ }
408
+ }
204
409
  return {
205
410
  schemaVersion: 1,
411
+ dbPort: configuredDbPort(getRoot()),
206
412
  bpUuid,
207
413
  rpUuid,
208
414
  bpVersion,
@@ -210,6 +416,8 @@ async function computeDesiredCatalog(opts) {
210
416
  ...bpModuleUuid ? { bpModuleUuid } : {},
211
417
  ...rpModuleUuid ? { rpModuleUuid } : {},
212
418
  generatedAt: Date.now(),
419
+ ...sdkVersion ? { sdkVersion } : {},
420
+ dependencies: negotiated.dependencies,
213
421
  modules
214
422
  };
215
423
  }
@@ -223,8 +431,20 @@ function readDeployedCatalog(bdsRoot, levelName) {
223
431
  }
224
432
  }
225
433
  function catalogsEqual(a, b) {
434
+ if (a.dbPort !== b.dbPort) return false;
226
435
  if (a.bpUuid !== b.bpUuid) return false;
227
436
  if ((a.rpUuid ?? null) !== (b.rpUuid ?? null)) return false;
437
+ if ((a.sdkVersion ?? null) !== (b.sdkVersion ?? null)) return false;
438
+ const depsA = a.dependencies ?? [];
439
+ const depsB = b.dependencies ?? [];
440
+ if (depsA.length !== depsB.length) return false;
441
+ for (let i = 0; i < depsA.length; i++) {
442
+ const da = depsA[i];
443
+ const db = depsB[i];
444
+ if (!da || !db || da.module_name !== db.module_name || da.version !== db.version) {
445
+ return false;
446
+ }
447
+ }
228
448
  const aKeys = Object.keys(a.modules).sort();
229
449
  const bKeys = Object.keys(b.modules).sort();
230
450
  if (aKeys.length !== bKeys.length) return false;
@@ -264,19 +484,23 @@ async function buildPacks(desired) {
264
484
  const sdkRoot = resolveSdkPackageRoot();
265
485
  packLog(`SDK root: ${sdkRoot}`);
266
486
  await build({
267
- entryPoints: entries,
487
+ stdin: {
488
+ contents: [
489
+ 'import "sfmc:host";',
490
+ ...entries.map((e) => `import ${JSON.stringify(path.resolve(e).replace(/\\/g, "/"))};`)
491
+ ].join("\n"),
492
+ resolveDir: ROOT,
493
+ sourcefile: "bootstrap.ts",
494
+ loader: "ts"
495
+ },
268
496
  outfile: outFile,
269
497
  bundle: true,
270
498
  platform: "neutral",
271
499
  format: "esm",
272
500
  target: "es2022",
273
501
  logLevel: "warning",
274
- sourcemap: false,
502
+ sourcemap: true,
275
503
  external: ["@minecraft/*"],
276
- // BDS host 启动:与 module-loader barrel 分离(DIP),须在模块 register 之前执行
277
- banner: {
278
- js: 'import { installHostBootstrap } from "@sfmc-bds/sdk/module-loader/install";\ninstallHostBootstrap();\n'
279
- },
280
504
  // 避免读取模块内残缺的 extends(如 ../../../sdk/@sfmc-sdk/tsconfig.json)
281
505
  tsconfigRaw: JSON.stringify({
282
506
  compilerOptions: {
@@ -287,7 +511,7 @@ async function buildPacks(desired) {
287
511
  skipLibCheck: true
288
512
  }
289
513
  }),
290
- plugins: [createSdkResolvePlugin(sdkRoot)]
514
+ plugins: [createSdkResolvePlugin(sdkRoot, catalog.dbPort)]
291
515
  });
292
516
  packLog(`esbuild bundled ${entries.length} entr(y/ies)`, "success");
293
517
  }
@@ -299,7 +523,8 @@ async function buildPacks(desired) {
299
523
  version: catalog.bpVersion,
300
524
  description: "ScriptsForMinecraftServer aggregated behavior pack",
301
525
  uuid: catalog.bpUuid,
302
- ...catalog.bpModuleUuid ? { moduleUuid: catalog.bpModuleUuid } : {}
526
+ ...catalog.bpModuleUuid ? { moduleUuid: catalog.bpModuleUuid } : {},
527
+ ...catalog.dependencies ? { dependencies: catalog.dependencies } : {}
303
528
  });
304
529
  } catch (e) {
305
530
  throw new Error(`assemble-bp failed: ${e.message}`);
@@ -425,6 +650,10 @@ function formatPackLoadInfo(catalog, rebuilt) {
425
650
  catalog.rpUuid ? ` RP ${catalog.rpUuid} v${(catalog.rpVersion ?? DEFAULT_PACK_VERSION).join(".")}` : ` RP (none)`,
426
651
  ` modules: ${enabled.length} enabled / ${disabled.length} disabled / ${mods.length} installed`
427
652
  ];
653
+ if (catalog.dependencies && catalog.dependencies.length > 0) {
654
+ const depStr = catalog.dependencies.map((d) => `${d.module_name}@${d.version}`).join(" ");
655
+ lines.push(` dependencies: ${depStr}`);
656
+ }
428
657
  for (const [folderId, m] of enabled.sort((a, b) => a[0].localeCompare(b[0]))) {
429
658
  lines.push(` \u25CF ${folderId} (${m.logicalId}) ${m.version}${m.hasResourcePack ? " +rp" : ""}`);
430
659
  }
@@ -468,6 +697,8 @@ async function ensurePacksReady() {
468
697
  if (deployed.rpUuid && !worldPackListHas(bdsRoot, levelName, "resource", deployed.rpUuid)) {
469
698
  needRebuild = true;
470
699
  }
700
+ const deployedMainJs = path.join(deployedBpDir(bdsRoot, levelName), "scripts", "main.js");
701
+ if (!existsSync(deployedMainJs)) needRebuild = true;
471
702
  if (!hasConfigPermission(bdsRoot, deployed.bpUuid)) {
472
703
  try {
473
704
  const wrote = await ensureConfigPermission(bdsRoot, deployed.bpUuid);
@@ -624,11 +855,13 @@ export {
624
855
  cmdPackList,
625
856
  cmdPackStatus,
626
857
  computeDesiredCatalog,
858
+ createSdkResolvePlugin,
627
859
  deployPacks,
628
860
  deployedBpDir,
629
861
  deployedCatalogPath,
630
862
  deployedRpDir,
631
863
  ensurePacksReady,
864
+ extractModuleBedrockDependencies,
632
865
  formatPackLoadInfo,
633
866
  readDeployedCatalog,
634
867
  resolveBdsContext,