@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.
- package/LICENSE +663 -0
- package/README.md +4 -5
- package/dist/bds-runtime-version.d.ts +3 -0
- package/dist/bds-runtime-version.d.ts.map +1 -0
- package/dist/bds-runtime-version.js +15 -0
- package/dist/bds-runtime-version.js.map +7 -0
- package/dist/command-surface.js +3 -3
- package/dist/command-surface.js.map +2 -2
- package/dist/commands.d.ts +57 -4
- package/dist/commands.d.ts.map +1 -1
- package/dist/commands.js +184 -68
- package/dist/commands.js.map +2 -2
- package/dist/directory-picker.d.ts +27 -0
- package/dist/directory-picker.d.ts.map +1 -0
- package/dist/directory-picker.js +112 -0
- package/dist/directory-picker.js.map +7 -0
- package/dist/help-text.d.ts.map +1 -1
- package/dist/help-text.js +1 -5
- package/dist/help-text.js.map +2 -2
- package/dist/i18n/locales/en.d.ts +49 -14
- package/dist/i18n/locales/en.d.ts.map +1 -1
- package/dist/i18n/locales/en.js +49 -15
- package/dist/i18n/locales/en.js.map +2 -2
- package/dist/i18n/locales/zh-CN.d.ts.map +1 -1
- package/dist/i18n/locales/zh-CN.js +50 -16
- package/dist/i18n/locales/zh-CN.js.map +2 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +2 -2
- package/dist/interactive-prompts.d.ts +1 -2
- package/dist/interactive-prompts.d.ts.map +1 -1
- package/dist/interactive-prompts.js +12 -23
- package/dist/interactive-prompts.js.map +3 -3
- package/dist/llbot-launch.d.ts +20 -0
- package/dist/llbot-launch.d.ts.map +1 -0
- package/dist/llbot-launch.js +40 -0
- package/dist/llbot-launch.js.map +7 -0
- package/dist/log-filter.d.ts +18 -2
- package/dist/log-filter.d.ts.map +1 -1
- package/dist/log-filter.js +54 -4
- package/dist/log-filter.js.map +2 -2
- package/dist/log-translator.d.ts +36 -0
- package/dist/log-translator.d.ts.map +1 -0
- package/dist/log-translator.js +279 -0
- package/dist/log-translator.js.map +7 -0
- package/dist/logs.d.ts +2 -0
- package/dist/logs.d.ts.map +1 -1
- package/dist/logs.js +24 -11
- package/dist/logs.js.map +2 -2
- package/dist/main.js +9 -6
- package/dist/main.js.map +2 -2
- package/dist/module-commands.d.ts.map +1 -1
- package/dist/module-commands.js +22 -8
- package/dist/module-commands.js.map +2 -2
- package/dist/module-fingerprint.d.ts.map +1 -1
- package/dist/module-fingerprint.js +1 -0
- package/dist/module-fingerprint.js.map +2 -2
- package/dist/module-pack-build.d.ts +14 -4
- package/dist/module-pack-build.d.ts.map +1 -1
- package/dist/module-pack-build.js +81 -108
- package/dist/module-pack-build.js.map +2 -2
- package/dist/module-toggle.d.ts +1 -1
- package/dist/module-toggle.d.ts.map +1 -1
- package/dist/module-toggle.js.map +1 -1
- package/dist/node-service-probe.d.ts +18 -0
- package/dist/node-service-probe.d.ts.map +1 -0
- package/dist/node-service-probe.js +97 -0
- package/dist/node-service-probe.js.map +7 -0
- package/dist/pack-lifecycle.d.ts +15 -1
- package/dist/pack-lifecycle.d.ts.map +1 -1
- package/dist/pack-lifecycle.js +249 -16
- package/dist/pack-lifecycle.js.map +2 -2
- package/dist/player-session.d.ts +13 -0
- package/dist/player-session.d.ts.map +1 -0
- package/dist/player-session.js +26 -0
- package/dist/player-session.js.map +7 -0
- package/dist/registry.d.ts +1 -1
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js +4 -1
- package/dist/registry.js.map +2 -2
- package/dist/repl-windows/format-display.d.ts.map +1 -1
- package/dist/repl-windows/format-display.js +5 -1
- package/dist/repl-windows/format-display.js.map +2 -2
- package/dist/repl-windows/host.d.ts +6 -3
- package/dist/repl-windows/host.d.ts.map +1 -1
- package/dist/repl-windows/host.js +12 -6
- package/dist/repl-windows/host.js.map +2 -2
- package/dist/repl-windows/index.d.ts +1 -0
- package/dist/repl-windows/index.d.ts.map +1 -1
- package/dist/repl-windows/index.js +3 -0
- package/dist/repl-windows/index.js.map +2 -2
- package/dist/repl-windows/service-window.d.ts +1 -1
- package/dist/repl-windows/service-window.d.ts.map +1 -1
- package/dist/repl-windows/service-window.js +9 -1
- package/dist/repl-windows/service-window.js.map +2 -2
- package/dist/repl-windows/sfmc-window.d.ts +7 -0
- package/dist/repl-windows/sfmc-window.d.ts.map +1 -0
- package/dist/repl-windows/sfmc-window.js +28 -0
- package/dist/repl-windows/sfmc-window.js.map +7 -0
- package/dist/repl.d.ts.map +1 -1
- package/dist/repl.js +37 -22
- package/dist/repl.js.map +2 -2
- package/dist/runtime.d.ts +2 -2
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +15 -2
- package/dist/runtime.js.map +2 -2
- package/dist/send-target.d.ts +2 -0
- package/dist/send-target.d.ts.map +1 -1
- package/dist/send-target.js +12 -2
- package/dist/send-target.js.map +2 -2
- package/dist/services.d.ts +58 -5
- package/dist/services.d.ts.map +1 -1
- package/dist/services.js +273 -50
- package/dist/services.js.map +2 -2
- package/dist/sfmc-modules-root.d.ts.map +1 -1
- package/dist/sfmc-modules-root.js +6 -2
- package/dist/sfmc-modules-root.js.map +2 -2
- package/dist/ui-command.d.ts +6 -0
- package/dist/ui-command.d.ts.map +1 -0
- package/dist/ui-command.js +68 -0
- package/dist/ui-command.js.map +7 -0
- package/dist/wizard.d.ts.map +1 -1
- package/dist/wizard.js +95 -32
- package/dist/wizard.js.map +2 -2
- package/dist/world-packs.d.ts +2 -0
- package/dist/world-packs.d.ts.map +1 -1
- package/dist/world-packs.js +161 -18
- package/dist/world-packs.js.map +2 -2
- package/package.json +21 -15
- package/scripts/module-install/check-modules.mjs +178 -0
- package/scripts/module-install/fetch-module.mjs +1083 -0
- package/scripts/module-install/lib/catalog.mjs +96 -0
- package/scripts/module-install/lib/config-seeding.mjs +128 -0
- package/scripts/module-install/lib/io.mjs +37 -0
- package/scripts/module-install/lib/link-from.mjs +80 -0
- package/scripts/module-install/lib/lock.mjs +78 -0
- package/scripts/module-install/lib/npm-resolver.mjs +55 -0
- package/scripts/module-install/lib/packages.mjs +136 -0
- package/scripts/module-install/lib/paths.mjs +48 -0
- package/scripts/module-install/lib/registry-index.mjs +50 -0
- package/dist/cmd-remote.d.ts +0 -13
- package/dist/cmd-remote.d.ts.map +0 -1
- package/dist/cmd-remote.js +0 -38
- package/dist/cmd-remote.js.map +0 -7
- package/dist/remote-agent.d.ts +0 -18
- package/dist/remote-agent.d.ts.map +0 -1
- package/dist/remote-agent.js +0 -198
- package/dist/remote-agent.js.map +0 -7
package/dist/pack-lifecycle.js
CHANGED
|
@@ -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
|
|
96
|
-
if (!
|
|
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 (
|
|
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
|
-
|
|
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:
|
|
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,
|