@sfmc-bds/bds-tools 0.2.0-beta.0 → 0.2.0-beta.10
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/dist/bds-manager.d.ts +16 -6
- package/dist/bds-manager.d.ts.map +1 -1
- package/dist/bds-manager.js +40 -65
- package/dist/bds-manager.js.map +2 -2
- package/dist/check-update.d.ts.map +1 -1
- package/dist/check-update.js +15 -17
- package/dist/check-update.js.map +2 -2
- package/dist/cli-pack-manager.js +7 -3
- package/dist/cli-pack-manager.js.map +2 -2
- package/dist/fsx.d.ts +6 -1
- package/dist/fsx.d.ts.map +1 -1
- package/dist/fsx.js +9 -1
- package/dist/fsx.js.map +2 -2
- package/dist/host-platform.d.ts +25 -0
- package/dist/host-platform.d.ts.map +1 -0
- package/dist/host-platform.js +50 -0
- package/dist/host-platform.js.map +7 -0
- package/dist/http.d.ts +49 -11
- package/dist/http.d.ts.map +1 -1
- package/dist/http.js.map +2 -2
- package/dist/log.d.ts +2 -3
- package/dist/log.d.ts.map +1 -1
- package/dist/log.js +0 -1
- package/dist/log.js.map +2 -2
- package/dist/pack-manager-lifecycle.test.js +252 -0
- package/dist/pack-manager-lifecycle.test.js.map +7 -0
- package/dist/pack-manager.d.ts +24 -29
- package/dist/pack-manager.d.ts.map +1 -1
- package/dist/pack-manager.js +11 -4
- package/dist/pack-manager.js.map +2 -2
- package/dist/pack-update/bindings.d.ts +16 -0
- package/dist/pack-update/bindings.d.ts.map +1 -0
- package/dist/pack-update/bindings.js +69 -0
- package/dist/pack-update/bindings.js.map +7 -0
- package/dist/pack-update/config.d.ts +16 -0
- package/dist/pack-update/config.d.ts.map +1 -0
- package/dist/pack-update/config.js +146 -0
- package/dist/pack-update/config.js.map +7 -0
- package/dist/pack-update/config.test.js +75 -0
- package/dist/pack-update/config.test.js.map +7 -0
- package/dist/pack-update/deps.d.ts +28 -0
- package/dist/pack-update/deps.d.ts.map +1 -0
- package/dist/pack-update/deps.js +20 -0
- package/dist/pack-update/deps.js.map +7 -0
- package/dist/pack-update/index.d.ts +55 -0
- package/dist/pack-update/index.d.ts.map +1 -0
- package/dist/pack-update/index.js +72 -0
- package/dist/pack-update/index.js.map +7 -0
- package/dist/pack-update/providers/curseforge.d.ts +23 -0
- package/dist/pack-update/providers/curseforge.d.ts.map +1 -0
- package/dist/pack-update/providers/curseforge.js +229 -0
- package/dist/pack-update/providers/curseforge.js.map +7 -0
- package/dist/pack-update/providers/index.d.ts +16 -0
- package/dist/pack-update/providers/index.d.ts.map +1 -0
- package/dist/pack-update/providers/index.js +37 -0
- package/dist/pack-update/providers/index.js.map +7 -0
- package/dist/pack-update/service.d.ts +28 -0
- package/dist/pack-update/service.d.ts.map +1 -0
- package/dist/pack-update/service.js +570 -0
- package/dist/pack-update/service.js.map +7 -0
- package/dist/pack-update/types.d.ts +126 -0
- package/dist/pack-update/types.d.ts.map +1 -0
- package/dist/pack-update/types.js +8 -0
- package/dist/pack-update/types.js.map +7 -0
- package/dist/pack-update/version-policy.d.ts +81 -0
- package/dist/pack-update/version-policy.d.ts.map +1 -0
- package/dist/pack-update/version-policy.js +210 -0
- package/dist/pack-update/version-policy.js.map +7 -0
- package/dist/pack-update/version-policy.test.js +137 -0
- package/dist/pack-update/version-policy.test.js.map +7 -0
- package/dist/paths.d.ts +1 -1
- package/dist/paths.d.ts.map +1 -1
- package/dist/paths.js +3 -5
- package/dist/paths.js.map +2 -2
- package/dist/process-probe.d.ts +34 -0
- package/dist/process-probe.d.ts.map +1 -0
- package/dist/process-probe.js +152 -0
- package/dist/process-probe.js.map +7 -0
- package/dist/process-probe.test.js +76 -0
- package/dist/process-probe.test.js.map +7 -0
- package/dist/qq-events-notify.d.ts +16 -0
- package/dist/qq-events-notify.d.ts.map +1 -0
- package/dist/qq-events-notify.js +70 -0
- package/dist/qq-events-notify.js.map +7 -0
- package/dist/qqutil.d.ts +10 -5
- package/dist/qqutil.d.ts.map +1 -1
- package/dist/qqutil.js +49 -8
- package/dist/qqutil.js.map +2 -2
- package/dist/update-result.d.ts +8 -2
- package/dist/update-result.d.ts.map +1 -1
- package/dist/update-result.js +7 -5
- package/dist/update-result.js.map +2 -2
- package/dist/upstream.d.ts +18 -9
- package/dist/upstream.d.ts.map +1 -1
- package/dist/upstream.js +8 -7
- package/dist/upstream.js.map +2 -2
- package/dist/version.js +2 -2
- package/dist/version.js.map +2 -2
- package/dist/world-packs.d.ts +158 -5
- package/dist/world-packs.d.ts.map +1 -1
- package/dist/world-packs.js +294 -48
- package/dist/world-packs.js.map +2 -2
- package/dist/world-packs.test.js +676 -0
- package/dist/world-packs.test.js.map +7 -0
- package/dist/zipx.test.js +36 -0
- package/dist/zipx.test.js.map +7 -0
- package/package.json +43 -39
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import os from "node:os";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { describe, it, before, after } from "node:test";
|
|
6
|
+
import { fileURLToPath } from "node:url";
|
|
7
|
+
import { spawnSync } from "node:child_process";
|
|
8
|
+
const CLI = path.join(path.dirname(fileURLToPath(import.meta.url)), "..", "dist", "cli-pack-manager.js");
|
|
9
|
+
function run(args) {
|
|
10
|
+
const r = spawnSync(process.execPath, [CLI, ...args], { encoding: "utf8" });
|
|
11
|
+
return { status: r.status, out: r.stdout ?? "", err: r.stderr ?? "" };
|
|
12
|
+
}
|
|
13
|
+
describe("pack-manager CLI extensions", () => {
|
|
14
|
+
let tmp;
|
|
15
|
+
before(() => {
|
|
16
|
+
tmp = fs.mkdtempSync(path.join(os.tmpdir(), "sfmc-pm-"));
|
|
17
|
+
});
|
|
18
|
+
after(() => {
|
|
19
|
+
fs.rmSync(tmp, { recursive: true, force: true });
|
|
20
|
+
});
|
|
21
|
+
it("assemble-rp --modules-json \u53EA\u7528\u663E\u5F0F map(\u4E0D\u626B\u6574\u6811)", async () => {
|
|
22
|
+
const { loadModuleResourcePackMap, assembleResourcePack } = await import("./pack-manager.js");
|
|
23
|
+
const modA = path.join(tmp, "mod-a", "resource_pack");
|
|
24
|
+
const modB = path.join(tmp, "mod-b", "resource_pack");
|
|
25
|
+
fs.mkdirSync(modA, { recursive: true });
|
|
26
|
+
fs.mkdirSync(modB, { recursive: true });
|
|
27
|
+
fs.writeFileSync(path.join(modA, "a.txt"), "a");
|
|
28
|
+
fs.writeFileSync(path.join(modB, "b.txt"), "b");
|
|
29
|
+
const mapFile = path.join(tmp, "map.json");
|
|
30
|
+
fs.writeFileSync(mapFile, JSON.stringify({ "mod-a": modA }));
|
|
31
|
+
const map = loadModuleResourcePackMap(mapFile);
|
|
32
|
+
assert.deepEqual(Object.keys(map), ["mod-a"]);
|
|
33
|
+
const out = path.join(tmp, "rp-out");
|
|
34
|
+
await assembleResourcePack({
|
|
35
|
+
moduleResourceDirs: map,
|
|
36
|
+
outDir: out,
|
|
37
|
+
projectName: "test-rp",
|
|
38
|
+
uuid: "11111111-1111-1111-1111-111111111111",
|
|
39
|
+
version: [1, 0, 0]
|
|
40
|
+
});
|
|
41
|
+
assert.ok(fs.existsSync(path.join(out, "mod-a", "a.txt")));
|
|
42
|
+
assert.ok(!fs.existsSync(path.join(out, "mod-b")));
|
|
43
|
+
const cli = run([
|
|
44
|
+
"assemble-rp",
|
|
45
|
+
"--modules-json",
|
|
46
|
+
mapFile,
|
|
47
|
+
"--out",
|
|
48
|
+
path.join(tmp, "rp-cli"),
|
|
49
|
+
"--name",
|
|
50
|
+
"test-rp-cli",
|
|
51
|
+
"--uuid",
|
|
52
|
+
"22222222-2222-2222-2222-222222222222"
|
|
53
|
+
]);
|
|
54
|
+
assert.equal(cli.status, 0, cli.err || cli.out);
|
|
55
|
+
});
|
|
56
|
+
it("deploy --clear-rp \u5220\u9664\u4E16\u754C\u5185\u6B8B\u7559 RP \u76EE\u5F55", async () => {
|
|
57
|
+
const { deployToBDS } = await import("./pack-manager.js");
|
|
58
|
+
const bds = path.join(tmp, "bds");
|
|
59
|
+
const level = "Bedrock level";
|
|
60
|
+
const worlds = path.join(bds, "worlds", level);
|
|
61
|
+
const bpSrc = path.join(tmp, "bp-src");
|
|
62
|
+
const rpDst = path.join(worlds, "resource_packs", "sfmc-modules-rp");
|
|
63
|
+
fs.mkdirSync(bpSrc, { recursive: true });
|
|
64
|
+
fs.writeFileSync(path.join(bpSrc, "dummy.txt"), "bp");
|
|
65
|
+
fs.mkdirSync(rpDst, { recursive: true });
|
|
66
|
+
fs.writeFileSync(path.join(rpDst, "stale.txt"), "old");
|
|
67
|
+
await deployToBDS({
|
|
68
|
+
bdsRoot: bds,
|
|
69
|
+
levelName: level,
|
|
70
|
+
behaviorPackSrc: bpSrc,
|
|
71
|
+
bpName: "sfmc-modules",
|
|
72
|
+
rpName: "sfmc-modules-rp",
|
|
73
|
+
clearResourcePack: true
|
|
74
|
+
});
|
|
75
|
+
assert.ok(!fs.existsSync(rpDst));
|
|
76
|
+
assert.ok(fs.existsSync(path.join(worlds, "behavior_packs", "sfmc-modules", "dummy.txt")));
|
|
77
|
+
});
|
|
78
|
+
it("read-manifest / has-pack / list-packs CLI \u5951\u7EA6", async () => {
|
|
79
|
+
const { assembleBehaviorPack, enablePackInWorld, worldPackListHas, readWorldPackList } = await import("./pack-manager.js");
|
|
80
|
+
const bpOut = path.join(tmp, "bp-assembled");
|
|
81
|
+
const src = path.join(tmp, "bp-empty-src");
|
|
82
|
+
fs.mkdirSync(path.join(src, "scripts"), { recursive: true });
|
|
83
|
+
fs.writeFileSync(path.join(src, "scripts", "main.js"), "//\n");
|
|
84
|
+
const uuid = "33333333-3333-3333-3333-333333333333";
|
|
85
|
+
await assembleBehaviorPack({
|
|
86
|
+
srcDir: src,
|
|
87
|
+
outDir: bpOut,
|
|
88
|
+
projectName: "sfmc-modules",
|
|
89
|
+
uuid,
|
|
90
|
+
version: [1, 2, 3]
|
|
91
|
+
});
|
|
92
|
+
const rm = run(["read-manifest", "--pack-dir", bpOut]);
|
|
93
|
+
assert.equal(rm.status, 0, rm.err);
|
|
94
|
+
const header = JSON.parse(rm.out.trim());
|
|
95
|
+
assert.equal(header.uuid, uuid);
|
|
96
|
+
assert.deepEqual(header.version, [1, 2, 3]);
|
|
97
|
+
const worldsDir = path.join(tmp, "worlds-root");
|
|
98
|
+
await enablePackInWorld({
|
|
99
|
+
worldsDir,
|
|
100
|
+
levelName: "L1",
|
|
101
|
+
kind: "behavior",
|
|
102
|
+
packUuid: uuid,
|
|
103
|
+
version: [1, 2, 3]
|
|
104
|
+
});
|
|
105
|
+
assert.equal(worldPackListHas(worldsDir, "L1", "behavior", uuid), true);
|
|
106
|
+
assert.equal(worldPackListHas(worldsDir, "L1", "behavior", "00000000-0000-0000-0000-000000000000"), false);
|
|
107
|
+
const hp = run([
|
|
108
|
+
"has-pack",
|
|
109
|
+
"--worlds-dir",
|
|
110
|
+
worldsDir,
|
|
111
|
+
"--level",
|
|
112
|
+
"L1",
|
|
113
|
+
"--kind",
|
|
114
|
+
"behavior",
|
|
115
|
+
"--pack-id",
|
|
116
|
+
uuid
|
|
117
|
+
]);
|
|
118
|
+
assert.equal(hp.status, 0);
|
|
119
|
+
assert.equal(hp.out.trim(), "1");
|
|
120
|
+
const lp = run(["list-packs", "--worlds-dir", worldsDir, "--level", "L1", "--kind", "behavior"]);
|
|
121
|
+
assert.equal(lp.status, 0, lp.err);
|
|
122
|
+
const listed = JSON.parse(lp.out.trim());
|
|
123
|
+
assert.equal(listed.length, 1);
|
|
124
|
+
assert.equal(listed[0].pack_id, uuid);
|
|
125
|
+
assert.deepEqual(readWorldPackList(worldsDir, "L1", "behavior"), listed);
|
|
126
|
+
});
|
|
127
|
+
it("readLevelNameSync \u4E0E async \u540C\u5951\u7EA6\uFF08\u4F9B sfmc resolveBdsContext\uFF09", async () => {
|
|
128
|
+
const { readLevelName, readLevelNameSync } = await import("./pack-manager.js");
|
|
129
|
+
const bds = path.join(tmp, "bds-level");
|
|
130
|
+
fs.mkdirSync(bds, { recursive: true });
|
|
131
|
+
assert.equal(readLevelNameSync(bds), "Bedrock level");
|
|
132
|
+
assert.equal(await readLevelName(bds), "Bedrock level");
|
|
133
|
+
fs.writeFileSync(path.join(bds, "server.properties"), "level-name=My World\n", "utf8");
|
|
134
|
+
assert.equal(readLevelNameSync(bds), "My World");
|
|
135
|
+
assert.equal(await readLevelName(bds), "My World");
|
|
136
|
+
});
|
|
137
|
+
it("BDS \u8DEF\u5F84 helpers \u5355\u4E00\u6743\u5A01\uFF08Demeter/DRY\uFF09", async () => {
|
|
138
|
+
const {
|
|
139
|
+
bdsWorldsDir,
|
|
140
|
+
bdsWorldLevelDir,
|
|
141
|
+
worldPackListFile,
|
|
142
|
+
configPermissionPath,
|
|
143
|
+
hasConfigPermission,
|
|
144
|
+
serverPropertiesPath,
|
|
145
|
+
ensureConfigPermission
|
|
146
|
+
} = await import("./pack-manager.js");
|
|
147
|
+
const bds = path.join(tmp, "bds-paths");
|
|
148
|
+
fs.mkdirSync(bds, { recursive: true });
|
|
149
|
+
assert.equal(bdsWorldsDir(bds), path.join(bds, "worlds"));
|
|
150
|
+
assert.equal(bdsWorldLevelDir(bds, "L1"), path.join(bds, "worlds", "L1"));
|
|
151
|
+
assert.equal(
|
|
152
|
+
worldPackListFile(bdsWorldsDir(bds), "L1", "behavior"),
|
|
153
|
+
path.join(bds, "worlds", "L1", "world_behavior_packs.json")
|
|
154
|
+
);
|
|
155
|
+
assert.equal(
|
|
156
|
+
worldPackListFile(bdsWorldsDir(bds), "L1", "resource"),
|
|
157
|
+
path.join(bds, "worlds", "L1", "world_resource_packs.json")
|
|
158
|
+
);
|
|
159
|
+
assert.equal(serverPropertiesPath(bds), path.join(bds, "server.properties"));
|
|
160
|
+
const uuid = "00000000-0000-4000-8000-000000000099";
|
|
161
|
+
assert.equal(configPermissionPath(bds, uuid), path.join(bds, "config", uuid, "permission.json"));
|
|
162
|
+
assert.equal(hasConfigPermission(bds, uuid), false);
|
|
163
|
+
assert.equal(await ensureConfigPermission(bds, uuid), true);
|
|
164
|
+
assert.equal(hasConfigPermission(bds, uuid), true);
|
|
165
|
+
assert.equal(await ensureConfigPermission(bds, uuid), false);
|
|
166
|
+
});
|
|
167
|
+
it("readWorldPackListResult \u533A\u5206\u7F3A\u5931\u4E0E JSON \u635F\u574F\uFF08doctor parseFail\uFF09", async () => {
|
|
168
|
+
const { readWorldPackListResult } = await import("./pack-manager.js");
|
|
169
|
+
const worldsDir = path.join(tmp, "worlds-parse");
|
|
170
|
+
const levelDir = path.join(worldsDir, "Lbad");
|
|
171
|
+
fs.mkdirSync(levelDir, { recursive: true });
|
|
172
|
+
const missing = readWorldPackListResult(worldsDir, "Lbad", "behavior");
|
|
173
|
+
assert.deepEqual(missing.entries, []);
|
|
174
|
+
assert.equal(missing.parseFailedFile, void 0);
|
|
175
|
+
const badFile = path.join(levelDir, "world_behavior_packs.json");
|
|
176
|
+
fs.writeFileSync(badFile, "{not-json", "utf8");
|
|
177
|
+
const bad = readWorldPackListResult(worldsDir, "Lbad", "behavior");
|
|
178
|
+
assert.deepEqual(bad.entries, []);
|
|
179
|
+
assert.equal(bad.parseFailedFile, badFile);
|
|
180
|
+
fs.writeFileSync(badFile, '{"not":"array"}', "utf8");
|
|
181
|
+
const notArr = readWorldPackListResult(worldsDir, "Lbad", "behavior");
|
|
182
|
+
assert.deepEqual(notArr.entries, []);
|
|
183
|
+
assert.equal(notArr.parseFailedFile, badFile);
|
|
184
|
+
});
|
|
185
|
+
it("\u65E0 deploy-catalog \u65F6\u4ECD\u53EF\u51ED\u78C1\u76D8 RP manifest \u5378\u4E16\u754C\u6E05\u5355(BLOCKER \u56DE\u5F52)", async () => {
|
|
186
|
+
const {
|
|
187
|
+
assembleResourcePack,
|
|
188
|
+
deployToBDS,
|
|
189
|
+
enablePackInWorld,
|
|
190
|
+
disablePackInWorld,
|
|
191
|
+
readPackManifestHeader,
|
|
192
|
+
worldPackListHas
|
|
193
|
+
} = await import("./pack-manager.js");
|
|
194
|
+
const bds = path.join(tmp, "bds-stale");
|
|
195
|
+
const level = "Bedrock level";
|
|
196
|
+
const worlds = path.join(bds, "worlds", level);
|
|
197
|
+
const worldsDir = path.join(bds, "worlds");
|
|
198
|
+
const bpSrc = path.join(tmp, "bp-stale-src");
|
|
199
|
+
const rpMod = path.join(tmp, "mod-stale", "resource_pack");
|
|
200
|
+
fs.mkdirSync(path.join(bpSrc, "scripts"), { recursive: true });
|
|
201
|
+
fs.writeFileSync(path.join(bpSrc, "scripts", "main.js"), "//\n");
|
|
202
|
+
fs.mkdirSync(rpMod, { recursive: true });
|
|
203
|
+
fs.writeFileSync(path.join(rpMod, "x.txt"), "x");
|
|
204
|
+
const staleUuid = "44444444-4444-4444-4444-444444444444";
|
|
205
|
+
const rpAssembled = path.join(tmp, "rp-stale-assembled");
|
|
206
|
+
await assembleResourcePack({
|
|
207
|
+
moduleResourceDirs: { stale: rpMod },
|
|
208
|
+
outDir: rpAssembled,
|
|
209
|
+
projectName: "sfmc-modules-rp",
|
|
210
|
+
uuid: staleUuid,
|
|
211
|
+
version: [1, 0, 0]
|
|
212
|
+
});
|
|
213
|
+
await deployToBDS({
|
|
214
|
+
bdsRoot: bds,
|
|
215
|
+
levelName: level,
|
|
216
|
+
behaviorPackSrc: bpSrc,
|
|
217
|
+
resourcePackSrc: rpAssembled,
|
|
218
|
+
bpName: "sfmc-modules",
|
|
219
|
+
rpName: "sfmc-modules-rp"
|
|
220
|
+
});
|
|
221
|
+
await enablePackInWorld({
|
|
222
|
+
worldsDir,
|
|
223
|
+
levelName: level,
|
|
224
|
+
kind: "resource",
|
|
225
|
+
packUuid: staleUuid,
|
|
226
|
+
version: [1, 0, 0]
|
|
227
|
+
});
|
|
228
|
+
assert.equal(worldPackListHas(worldsDir, level, "resource", staleUuid), true);
|
|
229
|
+
const rpDst = path.join(worlds, "resource_packs", "sfmc-modules-rp");
|
|
230
|
+
const header = readPackManifestHeader(rpDst);
|
|
231
|
+
assert.equal(header?.uuid, staleUuid);
|
|
232
|
+
assert.ok(header);
|
|
233
|
+
await deployToBDS({
|
|
234
|
+
bdsRoot: bds,
|
|
235
|
+
levelName: level,
|
|
236
|
+
behaviorPackSrc: bpSrc,
|
|
237
|
+
bpName: "sfmc-modules",
|
|
238
|
+
rpName: "sfmc-modules-rp",
|
|
239
|
+
clearResourcePack: true
|
|
240
|
+
});
|
|
241
|
+
assert.ok(!fs.existsSync(rpDst));
|
|
242
|
+
await disablePackInWorld({
|
|
243
|
+
worldsDir,
|
|
244
|
+
levelName: level,
|
|
245
|
+
kind: "resource",
|
|
246
|
+
packUuid: header.uuid,
|
|
247
|
+
version: [1, 0, 0]
|
|
248
|
+
});
|
|
249
|
+
assert.equal(worldPackListHas(worldsDir, level, "resource", staleUuid), false);
|
|
250
|
+
});
|
|
251
|
+
});
|
|
252
|
+
//# sourceMappingURL=pack-manager-lifecycle.test.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/pack-manager-lifecycle.test.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * pack-manager SOLID \u56DE\u5F52:modules-json / clear-rp / has-pack / read-manifest\n */\nimport assert from \"node:assert/strict\";\nimport fs from \"node:fs\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport { describe, it, before, after } from \"node:test\";\nimport { fileURLToPath } from \"node:url\";\nimport { spawnSync } from \"node:child_process\";\n\nconst CLI = path.join(path.dirname(fileURLToPath(import.meta.url)), \"..\", \"dist\", \"cli-pack-manager.js\");\n\nfunction run(args) {\n const r = spawnSync(process.execPath, [CLI, ...args], { encoding: \"utf8\" });\n return { status: r.status, out: r.stdout ?? \"\", err: r.stderr ?? \"\" };\n}\n\ndescribe(\"pack-manager CLI extensions\", () => {\n /** @type {string} */\n let tmp;\n before(() => {\n tmp = fs.mkdtempSync(path.join(os.tmpdir(), \"sfmc-pm-\"));\n });\n after(() => {\n fs.rmSync(tmp, { recursive: true, force: true });\n });\n\n it(\"assemble-rp --modules-json \u53EA\u7528\u663E\u5F0F map(\u4E0D\u626B\u6574\u6811)\", async () => {\n const { loadModuleResourcePackMap, assembleResourcePack } = await import(\"./pack-manager.js\");\n const modA = path.join(tmp, \"mod-a\", \"resource_pack\");\n const modB = path.join(tmp, \"mod-b\", \"resource_pack\");\n fs.mkdirSync(modA, { recursive: true });\n fs.mkdirSync(modB, { recursive: true });\n fs.writeFileSync(path.join(modA, \"a.txt\"), \"a\");\n fs.writeFileSync(path.join(modB, \"b.txt\"), \"b\");\n const mapFile = path.join(tmp, \"map.json\");\n /* \u4EC5\u542F\u7528 mod-a */\n fs.writeFileSync(mapFile, JSON.stringify({ \"mod-a\": modA }));\n const map = loadModuleResourcePackMap(mapFile);\n assert.deepEqual(Object.keys(map), [\"mod-a\"]);\n\n const out = path.join(tmp, \"rp-out\");\n await assembleResourcePack({\n moduleResourceDirs: map,\n outDir: out,\n projectName: \"test-rp\",\n uuid: \"11111111-1111-1111-1111-111111111111\",\n version: [1, 0, 0],\n });\n assert.ok(fs.existsSync(path.join(out, \"mod-a\", \"a.txt\")));\n assert.ok(!fs.existsSync(path.join(out, \"mod-b\")));\n\n const cli = run([\n \"assemble-rp\",\n \"--modules-json\",\n mapFile,\n \"--out\",\n path.join(tmp, \"rp-cli\"),\n \"--name\",\n \"test-rp-cli\",\n \"--uuid\",\n \"22222222-2222-2222-2222-222222222222\",\n ]);\n assert.equal(cli.status, 0, cli.err || cli.out);\n });\n\n it(\"deploy --clear-rp \u5220\u9664\u4E16\u754C\u5185\u6B8B\u7559 RP \u76EE\u5F55\", async () => {\n const { deployToBDS } = await import(\"./pack-manager.js\");\n const bds = path.join(tmp, \"bds\");\n const level = \"Bedrock level\";\n const worlds = path.join(bds, \"worlds\", level);\n const bpSrc = path.join(tmp, \"bp-src\");\n const rpDst = path.join(worlds, \"resource_packs\", \"sfmc-modules-rp\");\n fs.mkdirSync(bpSrc, { recursive: true });\n fs.writeFileSync(path.join(bpSrc, \"dummy.txt\"), \"bp\");\n fs.mkdirSync(rpDst, { recursive: true });\n fs.writeFileSync(path.join(rpDst, \"stale.txt\"), \"old\");\n\n await deployToBDS({\n bdsRoot: bds,\n levelName: level,\n behaviorPackSrc: bpSrc,\n bpName: \"sfmc-modules\",\n rpName: \"sfmc-modules-rp\",\n clearResourcePack: true,\n });\n assert.ok(!fs.existsSync(rpDst));\n assert.ok(fs.existsSync(path.join(worlds, \"behavior_packs\", \"sfmc-modules\", \"dummy.txt\")));\n });\n\n it(\"read-manifest / has-pack / list-packs CLI \u5951\u7EA6\", async () => {\n const { assembleBehaviorPack, enablePackInWorld, worldPackListHas, readWorldPackList } =\n await import(\"./pack-manager.js\");\n const bpOut = path.join(tmp, \"bp-assembled\");\n const src = path.join(tmp, \"bp-empty-src\");\n fs.mkdirSync(path.join(src, \"scripts\"), { recursive: true });\n fs.writeFileSync(path.join(src, \"scripts\", \"main.js\"), \"//\\n\");\n const uuid = \"33333333-3333-3333-3333-333333333333\";\n await assembleBehaviorPack({\n srcDir: src,\n outDir: bpOut,\n projectName: \"sfmc-modules\",\n uuid,\n version: [1, 2, 3],\n });\n\n const rm = run([\"read-manifest\", \"--pack-dir\", bpOut]);\n assert.equal(rm.status, 0, rm.err);\n const header = JSON.parse(rm.out.trim());\n assert.equal(header.uuid, uuid);\n assert.deepEqual(header.version, [1, 2, 3]);\n\n const worldsDir = path.join(tmp, \"worlds-root\");\n await enablePackInWorld({\n worldsDir,\n levelName: \"L1\",\n kind: \"behavior\",\n packUuid: uuid,\n version: [1, 2, 3],\n });\n assert.equal(worldPackListHas(worldsDir, \"L1\", \"behavior\", uuid), true);\n assert.equal(worldPackListHas(worldsDir, \"L1\", \"behavior\", \"00000000-0000-0000-0000-000000000000\"), false);\n\n const hp = run([\n \"has-pack\",\n \"--worlds-dir\",\n worldsDir,\n \"--level\",\n \"L1\",\n \"--kind\",\n \"behavior\",\n \"--pack-id\",\n uuid,\n ]);\n assert.equal(hp.status, 0);\n assert.equal(hp.out.trim(), \"1\");\n\n const lp = run([\"list-packs\", \"--worlds-dir\", worldsDir, \"--level\", \"L1\", \"--kind\", \"behavior\"]);\n assert.equal(lp.status, 0, lp.err);\n const listed = JSON.parse(lp.out.trim());\n assert.equal(listed.length, 1);\n assert.equal(listed[0].pack_id, uuid);\n assert.deepEqual(readWorldPackList(worldsDir, \"L1\", \"behavior\"), listed);\n });\n\n it(\"readLevelNameSync \u4E0E async \u540C\u5951\u7EA6\uFF08\u4F9B sfmc resolveBdsContext\uFF09\", async () => {\n const { readLevelName, readLevelNameSync } = await import(\"./pack-manager.js\");\n const bds = path.join(tmp, \"bds-level\");\n fs.mkdirSync(bds, { recursive: true });\n assert.equal(readLevelNameSync(bds), \"Bedrock level\");\n assert.equal(await readLevelName(bds), \"Bedrock level\");\n fs.writeFileSync(path.join(bds, \"server.properties\"), \"level-name=My World\\n\", \"utf8\");\n assert.equal(readLevelNameSync(bds), \"My World\");\n assert.equal(await readLevelName(bds), \"My World\");\n });\n\n it(\"BDS \u8DEF\u5F84 helpers \u5355\u4E00\u6743\u5A01\uFF08Demeter/DRY\uFF09\", async () => {\n const {\n bdsWorldsDir,\n bdsWorldLevelDir,\n worldPackListFile,\n configPermissionPath,\n hasConfigPermission,\n serverPropertiesPath,\n ensureConfigPermission,\n } = await import(\"./pack-manager.js\");\n const bds = path.join(tmp, \"bds-paths\");\n fs.mkdirSync(bds, { recursive: true });\n assert.equal(bdsWorldsDir(bds), path.join(bds, \"worlds\"));\n assert.equal(bdsWorldLevelDir(bds, \"L1\"), path.join(bds, \"worlds\", \"L1\"));\n assert.equal(\n worldPackListFile(bdsWorldsDir(bds), \"L1\", \"behavior\"),\n path.join(bds, \"worlds\", \"L1\", \"world_behavior_packs.json\")\n );\n assert.equal(\n worldPackListFile(bdsWorldsDir(bds), \"L1\", \"resource\"),\n path.join(bds, \"worlds\", \"L1\", \"world_resource_packs.json\")\n );\n assert.equal(serverPropertiesPath(bds), path.join(bds, \"server.properties\"));\n const uuid = \"00000000-0000-4000-8000-000000000099\";\n assert.equal(configPermissionPath(bds, uuid), path.join(bds, \"config\", uuid, \"permission.json\"));\n assert.equal(hasConfigPermission(bds, uuid), false);\n assert.equal(await ensureConfigPermission(bds, uuid), true);\n assert.equal(hasConfigPermission(bds, uuid), true);\n assert.equal(await ensureConfigPermission(bds, uuid), false);\n });\n\n it(\"readWorldPackListResult \u533A\u5206\u7F3A\u5931\u4E0E JSON \u635F\u574F\uFF08doctor parseFail\uFF09\", async () => {\n const { readWorldPackListResult } = await import(\"./pack-manager.js\");\n const worldsDir = path.join(tmp, \"worlds-parse\");\n const levelDir = path.join(worldsDir, \"Lbad\");\n fs.mkdirSync(levelDir, { recursive: true });\n\n const missing = readWorldPackListResult(worldsDir, \"Lbad\", \"behavior\");\n assert.deepEqual(missing.entries, []);\n assert.equal(missing.parseFailedFile, undefined);\n\n const badFile = path.join(levelDir, \"world_behavior_packs.json\");\n fs.writeFileSync(badFile, \"{not-json\", \"utf8\");\n const bad = readWorldPackListResult(worldsDir, \"Lbad\", \"behavior\");\n assert.deepEqual(bad.entries, []);\n assert.equal(bad.parseFailedFile, badFile);\n\n fs.writeFileSync(badFile, '{\"not\":\"array\"}', \"utf8\");\n const notArr = readWorldPackListResult(worldsDir, \"Lbad\", \"behavior\");\n assert.deepEqual(notArr.entries, []);\n assert.equal(notArr.parseFailedFile, badFile);\n });\n\n it(\"\u65E0 deploy-catalog \u65F6\u4ECD\u53EF\u51ED\u78C1\u76D8 RP manifest \u5378\u4E16\u754C\u6E05\u5355(BLOCKER \u56DE\u5F52)\", async () => {\n const {\n assembleResourcePack,\n deployToBDS,\n enablePackInWorld,\n disablePackInWorld,\n readPackManifestHeader,\n worldPackListHas,\n } = await import(\"./pack-manager.js\");\n\n const bds = path.join(tmp, \"bds-stale\");\n const level = \"Bedrock level\";\n const worlds = path.join(bds, \"worlds\", level);\n const worldsDir = path.join(bds, \"worlds\");\n const bpSrc = path.join(tmp, \"bp-stale-src\");\n const rpMod = path.join(tmp, \"mod-stale\", \"resource_pack\");\n fs.mkdirSync(path.join(bpSrc, \"scripts\"), { recursive: true });\n fs.writeFileSync(path.join(bpSrc, \"scripts\", \"main.js\"), \"//\\n\");\n fs.mkdirSync(rpMod, { recursive: true });\n fs.writeFileSync(path.join(rpMod, \"x.txt\"), \"x\");\n\n const staleUuid = \"44444444-4444-4444-4444-444444444444\";\n const rpAssembled = path.join(tmp, \"rp-stale-assembled\");\n await assembleResourcePack({\n moduleResourceDirs: { stale: rpMod },\n outDir: rpAssembled,\n projectName: \"sfmc-modules-rp\",\n uuid: staleUuid,\n version: [1, 0, 0],\n });\n\n await deployToBDS({\n bdsRoot: bds,\n levelName: level,\n behaviorPackSrc: bpSrc,\n resourcePackSrc: rpAssembled,\n bpName: \"sfmc-modules\",\n rpName: \"sfmc-modules-rp\",\n });\n await enablePackInWorld({\n worldsDir,\n levelName: level,\n kind: \"resource\",\n packUuid: staleUuid,\n version: [1, 0, 0],\n });\n assert.equal(worldPackListHas(worldsDir, level, \"resource\", staleUuid), true);\n\n /* \u6A21\u62DF catalog \u7F3A\u5931:\u53EA\u7559\u78C1\u76D8 RP,lifecycle \u5E94\u5728 clear \u524D\u8BFB manifest */\n const rpDst = path.join(worlds, \"resource_packs\", \"sfmc-modules-rp\");\n const header = readPackManifestHeader(rpDst);\n assert.equal(header?.uuid, staleUuid);\n assert.ok(header);\n\n await deployToBDS({\n bdsRoot: bds,\n levelName: level,\n behaviorPackSrc: bpSrc,\n bpName: \"sfmc-modules\",\n rpName: \"sfmc-modules-rp\",\n clearResourcePack: true,\n });\n assert.ok(!fs.existsSync(rpDst));\n\n await disablePackInWorld({\n worldsDir,\n levelName: level,\n kind: \"resource\",\n packUuid: header.uuid,\n version: [1, 0, 0],\n });\n assert.equal(worldPackListHas(worldsDir, level, \"resource\", staleUuid), false);\n });\n});\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
package/dist/pack-manager.d.ts
CHANGED
|
@@ -1,53 +1,48 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* pack-manager.ts — Bedrock
|
|
2
|
+
* pack-manager.ts — Bedrock 行为包(BP)与资源包(RP)组装及部署引擎
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* 核心设计与调用路径:
|
|
5
|
+
* - 进程内直连(推荐):`@sfmc-bds/bds-tools/pack-manager-lib` 供 CLI 编排与生命周期管理直接调用(遵循依赖倒置原则)
|
|
6
|
+
* - 独立 CLI:由 `cli-pack-manager.ts` 暴露命令行子命令供脚本与手工调试使用
|
|
5
7
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* 约束:本文件不引入 esbuild / 重型 npm-only 包,保持可被 Node 子进程直接加载。
|
|
12
|
-
*
|
|
13
|
-
* 已有依赖 (bds-tools/package.json):
|
|
14
|
-
* - @sfmc-bds/sdk/logs createTerminalProgress: 进度条(BDS 更新等)
|
|
15
|
-
* - node-html-parser: changelog 抓取 (本文件用不到)
|
|
16
|
-
* - jszip: zip 解压(模块 zip / BDS server.zip)
|
|
8
|
+
* 核心能力:
|
|
9
|
+
* - 行为包组装:将 esbuild 打包后的 `scripts/main.js`、元数据 manifest 与图标封装为 BDS 行为包结构
|
|
10
|
+
* - 资源包聚合:将各模块私有的 `resource_pack` 目录无冲突递归合并为聚合资源包
|
|
11
|
+
* - 世界部署与清单激活:将包部署至 BDS `<level>/behavior_packs` 与 `resource_packs`,并同步维护 `world_behavior_packs.json`
|
|
17
12
|
*/
|
|
18
13
|
import { copyDirAsync, copyFileAsync } from "./fsx.js";
|
|
19
14
|
export interface AssembleBehaviorPackOpts {
|
|
20
|
-
/**
|
|
15
|
+
/** 已完成打包的 `scripts/main.js` 所在源码目录(即 esbuild 输出目录)。 */
|
|
21
16
|
srcDir: string;
|
|
22
|
-
/**
|
|
17
|
+
/** 行为包目标输出目录(若不存在则自动创建)。 */
|
|
23
18
|
outDir: string;
|
|
24
|
-
/** BP
|
|
19
|
+
/** BP 项目/目录名(默认为 `'sfmc-modules'`)。 */
|
|
25
20
|
projectName: string;
|
|
26
|
-
/** manifest.json
|
|
21
|
+
/** `manifest.json` 中的 `header.version` `[major, minor, patch]`(默认为 `[1, 0, 0]`)。 */
|
|
27
22
|
version?: [number, number, number] | undefined;
|
|
28
|
-
/** manifest.json
|
|
23
|
+
/** `manifest.json` 中的包描述信息。 */
|
|
29
24
|
description?: string | undefined;
|
|
30
|
-
/** pack_icon.png
|
|
25
|
+
/** `pack_icon.png` 图标源文件路径(可选,未提供则跳过)。 */
|
|
31
26
|
iconSrc?: string | undefined;
|
|
32
|
-
/**
|
|
27
|
+
/** 稳定的 `header.uuid`(缺省时将在首次装配时随机生成)。 */
|
|
33
28
|
uuid?: string | undefined;
|
|
34
|
-
/**
|
|
29
|
+
/** 稳定的 `script module uuid`(缺省时随机生成)。 */
|
|
35
30
|
moduleUuid?: string | undefined;
|
|
36
31
|
}
|
|
37
32
|
export interface AssembleResourcePackOpts {
|
|
38
|
-
/**
|
|
33
|
+
/** 需合并资源包目录的模块映射字典(`Record<moduleId, resourcePackDir>`)。 */
|
|
39
34
|
moduleResourceDirs: Record<string, string>;
|
|
40
|
-
/**
|
|
35
|
+
/** 资源包目标输出目录(若不存在则自动创建)。 */
|
|
41
36
|
outDir: string;
|
|
42
|
-
/** RP
|
|
37
|
+
/** RP 项目/目录名。 */
|
|
43
38
|
projectName: string;
|
|
44
|
-
/** manifest.json
|
|
39
|
+
/** `manifest.json` 中的 `header.version` `[major, minor, patch]`(默认为 `[1, 0, 0]`)。 */
|
|
45
40
|
version?: [number, number, number] | undefined;
|
|
46
|
-
/** manifest.json
|
|
41
|
+
/** `manifest.json` 中的包描述信息。 */
|
|
47
42
|
description?: string | undefined;
|
|
48
|
-
/**
|
|
43
|
+
/** 稳定的 `header.uuid`(缺省时随机生成)。 */
|
|
49
44
|
uuid?: string | undefined;
|
|
50
|
-
/**
|
|
45
|
+
/** 稳定的 `resources module uuid`(缺省时随机生成)。 */
|
|
51
46
|
moduleUuid?: string | undefined;
|
|
52
47
|
}
|
|
53
48
|
export interface AssembleResult {
|
|
@@ -138,7 +133,7 @@ export declare function readPackManifestHeader(packDir: string): {
|
|
|
138
133
|
moduleUuid?: string;
|
|
139
134
|
} | null;
|
|
140
135
|
/**
|
|
141
|
-
* Write
|
|
136
|
+
* Write `@minecraft/*` allowed_modules into a behavior pack's
|
|
142
137
|
* `permissions.json`. Idempotent: rewrites any pre-existing file.
|
|
143
138
|
*/
|
|
144
139
|
export declare function writePermissionsJson(bpDir: string): Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pack-manager.d.ts","sourceRoot":"","sources":["../src/pack-manager.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"pack-manager.d.ts","sourceRoot":"","sources":["../src/pack-manager.ts"],"names":[],"mappings":"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"}
|
package/dist/pack-manager.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
|
-
import { copyDirAsync, copyFileAsync } from "./fsx.js";
|
|
3
|
+
import { copyDirAsync, copyFileAsync, readJsonFile } from "./fsx.js";
|
|
4
4
|
const SFMC_PERMISSIONS = [
|
|
5
5
|
"@minecraft/server",
|
|
6
6
|
"@minecraft/server-ui",
|
|
@@ -124,7 +124,7 @@ function readPackManifestHeader(packDir) {
|
|
|
124
124
|
const file = path.join(packDir, "manifest.json");
|
|
125
125
|
if (!fs.existsSync(file)) return null;
|
|
126
126
|
try {
|
|
127
|
-
const raw =
|
|
127
|
+
const raw = readJsonFile(file);
|
|
128
128
|
const uuid = raw.header?.uuid;
|
|
129
129
|
const ver = raw.header?.version;
|
|
130
130
|
if (typeof uuid !== "string" || !Array.isArray(ver) || ver.length < 3) return null;
|
|
@@ -184,7 +184,9 @@ async function writeBehaviorPackManifest(outDir, header) {
|
|
|
184
184
|
}
|
|
185
185
|
],
|
|
186
186
|
dependencies: [
|
|
187
|
-
{ module_name: "@minecraft/server", version: "1.18.0" }
|
|
187
|
+
{ module_name: "@minecraft/server", version: "1.18.0" },
|
|
188
|
+
{ module_name: "@minecraft/server-admin", version: "1.0.0-beta" },
|
|
189
|
+
{ module_name: "@minecraft/diagnostics", version: "1.0.0-beta" }
|
|
188
190
|
]
|
|
189
191
|
};
|
|
190
192
|
const file = path.join(outDir, "manifest.json");
|
|
@@ -217,7 +219,12 @@ function scanModuleResourcePacks(modulesDir) {
|
|
|
217
219
|
const out = {};
|
|
218
220
|
if (!fs.existsSync(modulesDir)) return out;
|
|
219
221
|
for (const entry of fs.readdirSync(modulesDir, { withFileTypes: true })) {
|
|
220
|
-
if (
|
|
222
|
+
if (entry.name.startsWith(".")) continue;
|
|
223
|
+
try {
|
|
224
|
+
if (!fs.statSync(path.join(modulesDir, entry.name)).isDirectory()) continue;
|
|
225
|
+
} catch {
|
|
226
|
+
continue;
|
|
227
|
+
}
|
|
221
228
|
const rpDir = path.join(modulesDir, entry.name, "resource_pack");
|
|
222
229
|
if (fs.existsSync(rpDir)) {
|
|
223
230
|
out[entry.name] = rpDir;
|
package/dist/pack-manager.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/pack-manager.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * pack-manager.ts \u2014 Bedrock \u884C\u4E3A\u5305/\u8D44\u6E90\u5305 \u88C5\u914D + \u90E8\u7F72\u5230 BDS \u6839\u3002\n *\n * \u7EAF\u51FD\u6570\u5E93,\u4E24\u6761\u6D88\u8D39\u8DEF\u5F84:\n *\n * - \u540C\u8FDB\u7A0B(\u63A8\u8350): sfmc/pack-lifecycle \u7ECF `@sfmc-bds/bds-tools/pack-manager-lib`\n * \u76F4\u8FDE\u672C\u6A21\u5757\uFF08DIP\uFF09\uFF1Bworld-packs \u7B49\u540C\u7406\u3002\n * - CLI: `cli-pack-manager.js` \u4ECD\u66B4\u9732\u76F8\u540C\u52A8\u8BCD\uFF0C\u4F9B\u5916\u90E8\u811A\u672C/\u624B\u5DE5\u8C03\u8BD5\uFF1B\n * CLI \u53EA\u662F\u672C\u5E93\u7684\u8584\u9002\u914D\uFF0C\u4E0D\u518D\u662F sfmc \u4E3B\u8DEF\u5F84\u3002\n *\n * \u7EA6\u675F:\u672C\u6587\u4EF6\u4E0D\u5F15\u5165 esbuild / \u91CD\u578B npm-only \u5305\uFF0C\u4FDD\u6301\u53EF\u88AB Node \u5B50\u8FDB\u7A0B\u76F4\u63A5\u52A0\u8F7D\u3002\n *\n * \u5DF2\u6709\u4F9D\u8D56 (bds-tools/package.json):\n * - @sfmc-bds/sdk/logs createTerminalProgress: \u8FDB\u5EA6\u6761\uFF08BDS \u66F4\u65B0\u7B49\uFF09\n * - node-html-parser: changelog \u6293\u53D6 (\u672C\u6587\u4EF6\u7528\u4E0D\u5230)\n * - jszip: zip \u89E3\u538B(\u6A21\u5757 zip / BDS server.zip)\n */\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { copyDirAsync, copyFileAsync } from \"./fsx.js\";\n\n/* \u2500\u2500 \u7C7B\u578B \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 interface AssembleBehaviorPackOpts {\n /** Where the bundled scripts/main.js already exists (esbuild output dir) */\n srcDir: string;\n /** Output behavior pack directory (created if missing) */\n outDir: string;\n /** BP \u76EE\u5F55\u540D \u2014 \u9ED8\u8BA4 'sfmc-modules' */\n projectName: string;\n /** manifest.json \u7684 header.version [major, minor, patch]; \u9ED8\u8BA4 [1, 0, 0] */\n version?: [number, number, number] | undefined;\n /** manifest.json \u7684 description */\n description?: string | undefined;\n /** pack_icon.png \u6E90\u6587\u4EF6 (optional, \u4E0D\u63D0\u4F9B\u5219\u8DF3\u8FC7) */\n iconSrc?: string | undefined;\n /** \u7A33\u5B9A header.uuid;\u7701\u7565\u5219\u968F\u673A\u751F\u6210(\u9996\u6B21\u88C5\u914D) */\n uuid?: string | undefined;\n /** \u7A33\u5B9A script module uuid;\u7701\u7565\u5219\u968F\u673A */\n moduleUuid?: string | undefined;\n}\n\nexport interface AssembleResourcePackOpts {\n /** Modules whose resource_pack/** should be merged. Map<moduleId, resourcePackDir>. */\n moduleResourceDirs: Record<string, string>;\n /** Output resource pack directory (created if missing) */\n outDir: string;\n /** RP \u76EE\u5F55\u540D */\n projectName: string;\n /** manifest.json \u7684 header.version [major, minor, patch]; \u9ED8\u8BA4 [1, 0, 0] */\n version?: [number, number, number] | undefined;\n /** manifest.json \u7684 description */\n description?: string | undefined;\n /** \u7A33\u5B9A header.uuid;\u7701\u7565\u5219\u968F\u673A\u751F\u6210(\u9996\u6B21\u88C5\u914D) */\n uuid?: string | undefined;\n /** \u7A33\u5B9A resources module uuid;\u7701\u7565\u5219\u968F\u673A */\n moduleUuid?: string | undefined;\n}\n\nexport interface AssembleResult {\n uuid: string;\n version: [number, number, number];\n}\n\nexport interface DeployOpts {\n bdsRoot: string;\n levelName: string;\n /** \u5DF2\u7EC4\u88C5\u597D\u7684 BP \u6E90\u76EE\u5F55 */\n behaviorPackSrc: string;\n /** \u5DF2\u7EC4\u88C5\u597D\u7684 RP \u6E90\u76EE\u5F55 (\u53EF\u7701\u7565,\u53EA\u7528 BP \u4E5F\u5408\u6CD5) */\n resourcePackSrc?: string;\n /** BP \u76EE\u6807\u76EE\u5F55\u540D (worlds/<level>/behavior_packs/<bpName>) */\n bpName: string;\n /** RP \u76EE\u6807\u76EE\u5F55\u540D (worlds/<level>/resource_packs/<rpName>);\u7701\u7565\u65F6\u590D\u7528 bpName + '-rp' */\n rpName?: string;\n /**\n * \u65E0 resourcePackSrc \u65F6\u662F\u5426\u5220\u9664\u4E16\u754C\u5185\u5DF2\u6709 RP \u76EE\u5F55\u3002\n * \u7528\u4E8E\u6A21\u5757\u4E0D\u518D\u63D0\u4F9B RP \u65F6\u6E05\u7406\u805A\u5408\u5305\u6B8B\u7559(\u9ED8\u8BA4 false,\u907F\u514D\u8BEF\u5220\u672A\u58F0\u660E\u7684 RP)\u3002\n */\n clearResourcePack?: boolean;\n}\n\nexport interface DeployResult {\n bpDir: string;\n rpDir: string | null;\n}\n\nexport interface EnablePackOpts {\n worldsDir: string;\n levelName: string;\n kind: \"behavior\" | \"resource\";\n packUuid: string;\n version: [number, number, number];\n}\n\n/* \u2500\u2500 \u8DEF\u5F84\u5E38\u91CF \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n/** SFMC \u5408\u6210 BP \u7684\u56FA\u5B9A @minecraft/* permissions,\u6240\u6709\u7528\u5230\u7684\u547D\u540D\u7A7A\u95F4\u90FD\u6253\u5F00\u3002 */\nexport const SFMC_PERMISSIONS = [\n \"@minecraft/server\",\n \"@minecraft/server-ui\",\n \"@minecraft/server-admin\",\n \"@minecraft/server-gametest\",\n \"@minecraft/server-net\",\n \"@minecraft/server-editor\",\n \"@minecraft/diagnostics\",\n] as const;\n\n/** `<bdsRoot>/server.properties` \u2014 level-name / telemetry \u7B49\u5171\u7528\uFF08DRY\uFF09 */\nexport function serverPropertiesPath(bdsRoot: string): string {\n return path.join(bdsRoot, \"server.properties\");\n}\n\n/** `<bdsRoot>/worlds` \u2014 enable-list / \u90E8\u7F72\u8C03\u7528\u65B9\u52FF\u518D\u786C\u62FC\uFF08Demeter\uFF09 */\nexport function bdsWorldsDir(bdsRoot: string): string {\n return path.join(bdsRoot, \"worlds\");\n}\n\n/** `<bdsRoot>/worlds/<level>` */\nexport function bdsWorldLevelDir(bdsRoot: string, levelName: string): string {\n return path.join(bdsWorldsDir(bdsRoot), levelName);\n}\n\n/** \u4E16\u754C enable-list JSON \u7EDD\u5BF9\u8DEF\u5F84\uFF08\u5355\u4E00\u6743\u5A01\uFF0C\u4F9B\u8BFB\u5199\u4E24\u4FA7\uFF09 */\nexport function worldPackListFile(\n worldsDir: string,\n levelName: string,\n kind: \"behavior\" | \"resource\"\n): string {\n const name = kind === \"behavior\" ? \"world_behavior_packs.json\" : \"world_resource_packs.json\";\n return path.join(worldsDir, levelName, name);\n}\n\n/** `<bdsRoot>/config/<bpUuid>/permission.json` \u2014 Script API \u6743\u9650\u6587\u4EF6\u6743\u5A01\u8DEF\u5F84 */\nexport function configPermissionPath(bdsRoot: string, bpUuid: string): string {\n return path.join(bdsRoot, \"config\", bpUuid, \"permission.json\");\n}\n\n/** \u662F\u5426\u5DF2\u6709 Script API permission.json\uFF08\u53EA\u8BFB\uFF0C\u4F9B preflight/status\uFF09 */\nexport function hasConfigPermission(bdsRoot: string, bpUuid: string): boolean {\n return fs.existsSync(configPermissionPath(bdsRoot, bpUuid));\n}\n\n/** \u968F\u673A\u751F\u6210 BP/RP manifest.json header.uuid (RFC 4122 v4) */\nexport function randomUuid(): string {\n /* crypto.randomUUID \u662F Node 19+ \u5185\u7F6E,\u8FD9\u91CC\u76F4\u63A5\u7528 */\n return crypto.randomUUID();\n}\n\n/* \u2500\u2500 \u9AA8\u67B6\u51FD\u6570 (Commit 5 \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 */\n\n/**\n * Assemble a Bedrock behavior pack directory at `outDir` from a prebuilt\n * `srcDir` (which must already contain `scripts/main.js` plus whatever else\n * was bundled by esbuild) and write a fresh `manifest.json` + `permissions.json`.\n *\n * The caller is responsible for running esbuild first; pack-manager does not\n * bundle scripts. That decoupling keeps pack assembly independent of the bundler.\n */\nexport async function assembleBehaviorPack(opts: AssembleBehaviorPackOpts): Promise<AssembleResult> {\n const version = opts.version ?? [1, 0, 0];\n const bpUuid = opts.uuid ?? randomUuid();\n await fs.promises.rm(opts.outDir, { recursive: true, force: true });\n await fs.promises.mkdir(opts.outDir, { recursive: true });\n if (fs.existsSync(opts.srcDir)) {\n await copyDirAsync(opts.srcDir, opts.outDir);\n } else {\n await fs.promises.mkdir(path.join(opts.outDir, \"scripts\"), { recursive: true });\n await fs.promises.writeFile(path.join(opts.outDir, \"scripts\", \"main.js\"), \"/* no scripts */\\n\", \"utf8\");\n }\n await writeBehaviorPackManifest(opts.outDir, {\n name: opts.projectName,\n uuid: bpUuid,\n version,\n description: opts.description,\n moduleUuid: opts.moduleUuid,\n });\n if (opts.iconSrc && fs.existsSync(opts.iconSrc)) {\n await copyFileAsync(opts.iconSrc, path.join(opts.outDir, \"pack_icon.png\"));\n }\n await writePermissionsJson(opts.outDir);\n return { uuid: bpUuid, version };\n}\n\n/**\n * Merge every enabled module's `resource_pack/**` tree into one RP directory\n * at `outDir`, with a single fresh `manifest.json`. Per-module subfolders are\n * preserved so resource pack authors can disambiguate (e.g. `peace/textures/...`).\n */\nexport async function assembleResourcePack(opts: AssembleResourcePackOpts): Promise<AssembleResult> {\n const version = opts.version ?? [1, 0, 0];\n const rpUuid = opts.uuid ?? randomUuid();\n await fs.promises.rm(opts.outDir, { recursive: true, force: true });\n await fs.promises.mkdir(opts.outDir, { recursive: true });\n for (const [moduleId, rpDir] of Object.entries(opts.moduleResourceDirs)) {\n if (!fs.existsSync(rpDir)) continue;\n const dst = path.join(opts.outDir, moduleId);\n await fs.promises.mkdir(dst, { recursive: true });\n await copyDirAsync(rpDir, dst);\n }\n await writeResourcePackManifest(opts.outDir, {\n name: opts.projectName,\n uuid: rpUuid,\n version,\n description: opts.description,\n moduleUuid: opts.moduleUuid,\n });\n return { uuid: rpUuid, version };\n}\n\n/**\n * Read the `level-name=` value from `<bdsRoot>/server.properties`.\n * Falls back to \"Bedrock level\" (BDS default) when the file is missing or\n * the key is absent.\n */\nfunction parseLevelNameFromProperties(text: string): string {\n for (const line of text.split(/\\r?\\n/)) {\n const m = /^\\s*level-name\\s*=\\s*(.+?)\\s*$/.exec(line);\n if (m && m[1]) return m[1];\n }\n return \"Bedrock level\";\n}\n\n/** \u540C\u6B65\u8BFB level-name\uFF08\u4F9B sfmc resolveBdsContext \u7B49\u540C\u8FDB\u7A0B\u8C03\u7528\u65B9\uFF0CDRY\uFF09\u3002 */\nexport function readLevelNameSync(bdsRoot: string): string {\n const file = serverPropertiesPath(bdsRoot);\n if (!fs.existsSync(file)) return \"Bedrock level\";\n return parseLevelNameFromProperties(fs.readFileSync(file, \"utf8\"));\n}\n\n/** \u4E0E sync \u540C\u5951\u7EA6\uFF1BCLI / async \u8C03\u7528\u65B9\u8D70\u6B64\u5165\u53E3\uFF08LSP\uFF09 */\nexport async function readLevelName(bdsRoot: string): Promise<string> {\n return readLevelNameSync(bdsRoot);\n}\n\n/**\n * Copy BP/RP source dirs into the world's behavior_packs/ + resource_packs/\n * folders, and write a fresh `permissions.json` into the BP target.\n *\n * Does NOT edit world_behavior_packs.json \u2014 that's a separate step the caller\n * must invoke after restart, because BDS only reads that file at startup.\n */\nexport async function deployToBDS(opts: DeployOpts): Promise<DeployResult> {\n /* levelDir = worlds/<level>\uFF1B\u4E0E EnablePackOpts.worldsDir(=worlds/) \u8BED\u4E49\u4E0D\u540C \u2014 \u52FF\u6DF7\u7528\uFF08LSP\uFF09 */\n const levelDir = bdsWorldLevelDir(opts.bdsRoot, opts.levelName);\n const bpDst = path.join(levelDir, \"behavior_packs\", opts.bpName);\n const rpDst = path.join(levelDir, \"resource_packs\", opts.rpName ?? `${opts.bpName}-rp`);\n await fs.promises.mkdir(levelDir, { recursive: true });\n await fs.promises.rm(bpDst, { recursive: true, force: true });\n await copyDirAsync(opts.behaviorPackSrc, bpDst);\n await writePermissionsJson(bpDst);\n let rpDir: string | null = null;\n if (opts.resourcePackSrc && fs.existsSync(opts.resourcePackSrc)) {\n await fs.promises.rm(rpDst, { recursive: true, force: true });\n await copyDirAsync(opts.resourcePackSrc, rpDst);\n rpDir = rpDst;\n } else if (opts.clearResourcePack) {\n /* \u8C03\u7528\u65B9\u663E\u5F0F\u58F0\u660E\u4E0D\u518D\u90E8\u7F72 RP \u2014 \u6E05\u6389\u805A\u5408 RP \u76EE\u5F55\u6B8B\u7559 */\n await fs.promises.rm(rpDst, { recursive: true, force: true });\n }\n return { bpDir: bpDst, rpDir };\n}\n\n/**\n * \u786E\u4FDD BDS Script API \u4FA7 `<bdsRoot>/config/<bpUuid>/permission.json` \u5B58\u5728\u3002\n * \u5DF2\u5B58\u5728\u5219\u8DF3\u8FC7(\u4E0D\u8986\u76D6\u7528\u6237\u624B\u5DE5\u6539\u52A8)\u3002\n * @returns true = \u65B0\u5199\u5165; false = \u5DF2\u5B58\u5728\u8DF3\u8FC7\n */\nexport async function ensureConfigPermission(bdsRoot: string, bpUuid: string): Promise<boolean> {\n const file = configPermissionPath(bdsRoot, bpUuid);\n if (fs.existsSync(file)) return false;\n const dir = path.dirname(file);\n await fs.promises.mkdir(dir, { recursive: true });\n const payload = { allowed_modules: [...SFMC_PERMISSIONS] };\n const tmp = path.join(dir, `.permission.${process.pid}.tmp`);\n await fs.promises.writeFile(tmp, JSON.stringify(payload, null, 2) + \"\\n\", \"utf8\");\n await fs.promises.rename(tmp, file);\n return true;\n}\n\n/** \u4ECE\u5DF2\u88C5\u914D BP/RP \u76EE\u5F55\u8BFB\u53D6 header.uuid + version;\u5931\u8D25\u8FD4\u56DE null\u3002 */\nexport function readPackManifestHeader(\n packDir: string\n): { uuid: string; version: [number, number, number]; moduleUuid?: string } | null {\n const file = path.join(packDir, \"manifest.json\");\n if (!fs.existsSync(file)) return null;\n try {\n const raw = JSON.parse(fs.readFileSync(file, \"utf8\")) as {\n header?: { uuid?: string; version?: number[] };\n modules?: Array<{ uuid?: string }>;\n };\n const uuid = raw.header?.uuid;\n const ver = raw.header?.version;\n if (typeof uuid !== \"string\" || !Array.isArray(ver) || ver.length < 3) return null;\n const version: [number, number, number] = [Number(ver[0]), Number(ver[1]), Number(ver[2])];\n const moduleUuid = raw.modules?.[0]?.uuid;\n return { uuid, version, ...(typeof moduleUuid === \"string\" ? { moduleUuid } : {}) };\n } catch {\n return null;\n }\n}\n\n/**\n * Write the seven `@minecraft/*` allowed_modules into a behavior pack's\n * `permissions.json`. Idempotent: rewrites any pre-existing file.\n */\nexport async function writePermissionsJson(bpDir: string): Promise<void> {\n const payload = { allowed_modules: [...SFMC_PERMISSIONS] };\n await fs.promises.mkdir(bpDir, { recursive: true });\n const tmp = path.join(bpDir, `.permissions.${process.pid}.tmp`);\n await fs.promises.writeFile(tmp, JSON.stringify(payload, null, 2) + \"\\n\", \"utf8\");\n await fs.promises.rename(tmp, path.join(bpDir, \"permissions.json\"));\n}\n\n/**\n * Add `{ pack_id, version }` to `worlds/<level>/world_behavior_packs.json`\n * (or `world_resource_packs.json`). If the pack_id already exists, replace its\n * version. File missing \u2192 initialize as `[]`.\n */\nexport async function enablePackInWorld(opts: EnablePackOpts): Promise<void> {\n await editWorldPackList(opts, \"enable\");\n}\n\n/** Remove a pack_id from the world's enable-list JSON. */\nexport async function disablePackInWorld(opts: EnablePackOpts): Promise<void> {\n await editWorldPackList(opts, \"disable\");\n}\n\ninterface WorldPackEntry {\n pack_id: string;\n version: [number, number, number];\n}\n\nasync function editWorldPackList(\n opts: EnablePackOpts,\n mode: \"enable\" | \"disable\"\n): Promise<void> {\n const file = worldPackListFile(opts.worldsDir, opts.levelName, opts.kind);\n /* \u4E0E readWorldPackList \u540C\u6E90\u89E3\u6790,\u518D\u5199\u56DE(DRY);\u5F02\u6B65\u5199\u8DEF\u5F84\u4FDD\u7559\u539F\u8BED\u4E49 */\n let entries: WorldPackEntry[] = readWorldPackList(opts.worldsDir, opts.levelName, opts.kind);\n const idx = entries.findIndex((e) => e.pack_id === opts.packUuid);\n if (mode === \"enable\") {\n const next: WorldPackEntry = { pack_id: opts.packUuid, version: opts.version };\n if (idx >= 0) entries[idx] = next;\n else entries.push(next);\n } else {\n if (idx >= 0) entries.splice(idx, 1);\n }\n await fs.promises.mkdir(path.dirname(file), { recursive: true });\n const tmp = `${file}.${process.pid}.tmp`;\n await fs.promises.writeFile(tmp, JSON.stringify(entries, null, 2) + \"\\n\", \"utf8\");\n await fs.promises.rename(tmp, file);\n}\n\n/* \u2500\u2500 \u4F4E\u5C42 helpers (Commit 5 \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 */\n\nexport async function writeBehaviorPackManifest(\n outDir: string,\n header: {\n name: string;\n uuid: string;\n version: [number, number, number];\n description?: string | undefined;\n moduleUuid?: string | undefined;\n }\n): Promise<void> {\n const manifest = {\n format_version: 2,\n header: {\n name: header.name,\n uuid: header.uuid,\n version: header.version,\n description: header.description ? `${header.description} (behavior pack)` : \"SFMC behavior pack\",\n min_engine_version: [1, 21, 0],\n },\n modules: [\n {\n type: \"script\",\n language: \"javascript\",\n entry: \"scripts/main.js\",\n uuid: header.moduleUuid ?? crypto.randomUUID(),\n version: header.version,\n },\n ],\n dependencies: [\n { module_name: \"@minecraft/server\", version: \"1.18.0\" },\n ],\n };\n const file = path.join(outDir, \"manifest.json\");\n await fs.promises.mkdir(outDir, { recursive: true });\n await fs.promises.writeFile(file, JSON.stringify(manifest, null, 2) + \"\\n\", \"utf8\");\n}\n\nexport async function writeResourcePackManifest(\n outDir: string,\n header: {\n name: string;\n uuid: string;\n version: [number, number, number];\n description?: string | undefined;\n moduleUuid?: string | undefined;\n }\n): Promise<void> {\n const manifest = {\n format_version: 2,\n header: {\n name: header.name,\n uuid: header.uuid,\n version: header.version,\n description: header.description ? `${header.description} (resource pack)` : \"SFMC resource pack\",\n min_engine_version: [1, 21, 0],\n },\n modules: [\n {\n type: \"resources\",\n uuid: header.moduleUuid ?? crypto.randomUUID(),\n version: header.version,\n },\n ],\n };\n const file = path.join(outDir, \"manifest.json\");\n await fs.promises.mkdir(outDir, { recursive: true });\n await fs.promises.writeFile(file, JSON.stringify(manifest, null, 2) + \"\\n\", \"utf8\");\n}\n\n/* Re-export copyFileAsync so callers can copy icon without\n * pulling in the full fsx surface area. */\nexport { copyFileAsync, copyDirAsync };\n\n/* \u2500\u2500 Discovery \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n/**\n * Walk `<modulesDir>/<id>/resource_pack/` for every installed module and\n * return a map { id: absoluteDir }. Modules without a resource_pack folder\n * are silently skipped. Used by `assemble-rp` and the sfmc CLI to know which\n * modules to merge into the resource pack output.\n */\nexport function scanModuleResourcePacks(modulesDir: string): Record<string, string> {\n const out: Record<string, string> = {};\n if (!fs.existsSync(modulesDir)) return out;\n for (const entry of fs.readdirSync(modulesDir, { withFileTypes: true })) {\n if (!entry.isDirectory()) continue;\n const rpDir = path.join(modulesDir, entry.name, \"resource_pack\");\n if (fs.existsSync(rpDir)) {\n out[entry.name] = rpDir;\n }\n }\n return out;\n}\n\n/**\n * \u4ECE JSON \u6587\u4EF6\u52A0\u8F7D\u663E\u5F0F moduleId \u2192 resource_pack \u76EE\u5F55\u6620\u5C04\u3002\n * \u4F9B assemble-rp --modules-json \u4F7F\u7528,\u907F\u514D\u8C03\u7528\u65B9\u518D\u505A\u4E34\u65F6\u76EE\u5F55\u955C\u50CF(OCP/DRY)\u3002\n */\nexport function loadModuleResourcePackMap(jsonPath: string): Record<string, string> {\n const raw = JSON.parse(fs.readFileSync(jsonPath, \"utf8\")) as unknown;\n if (!raw || typeof raw !== \"object\" || Array.isArray(raw)) {\n throw new Error(`modules-json must be an object: ${jsonPath}`);\n }\n const out: Record<string, string> = {};\n for (const [id, dir] of Object.entries(raw as Record<string, unknown>)) {\n if (typeof id !== \"string\" || !id || typeof dir !== \"string\" || !dir) continue;\n const abs = path.resolve(dir);\n if (!fs.existsSync(abs)) {\n throw new Error(`modules-json entry missing: ${id} \u2192 ${abs}`);\n }\n out[id] = abs;\n }\n return out;\n}\n\n/**\n * \u8BFB\u53D6\u4E16\u754C enable-list(\u5355\u4E00\u6743\u5A01,\u4F9B has-pack / list-packs / \u8C03\u7528\u65B9\u590D\u7528 \u2014 DRY)\u3002\n * \u6587\u4EF6\u7F3A\u5931 \u2192 entries=[]\uFF1BJSON \u635F\u574F \u2192 entries=[] \u4E14 parseFailedFile \u6709\u503C\uFF08\u4F9B doctor \u533A\u5206\uFF09\u3002\n */\nexport type WorldPackListReadResult = {\n entries: Array<{ pack_id: string; version: [number, number, number] }>;\n /** \u6587\u4EF6\u5B58\u5728\u4F46\u89E3\u6790\u5931\u8D25\u65F6\u4E3A\u8BE5 JSON \u7EDD\u5BF9\u8DEF\u5F84 */\n parseFailedFile?: string;\n};\n\nexport function readWorldPackListResult(\n worldsDir: string,\n levelName: string,\n kind: \"behavior\" | \"resource\"\n): WorldPackListReadResult {\n const file = worldPackListFile(worldsDir, levelName, kind);\n if (!fs.existsSync(file)) return { entries: [] };\n try {\n const arr = JSON.parse(fs.readFileSync(file, \"utf8\")) as unknown;\n if (!Array.isArray(arr)) return { entries: [], parseFailedFile: file };\n const out: Array<{ pack_id: string; version: [number, number, number] }> = [];\n for (const e of arr) {\n if (!e || typeof e !== \"object\") continue;\n const packId = (e as { pack_id?: unknown }).pack_id;\n const ver = (e as { version?: unknown }).version;\n if (typeof packId !== \"string\" || !packId) continue;\n const version: [number, number, number] =\n Array.isArray(ver) && ver.length >= 3\n ? [Number(ver[0]), Number(ver[1]), Number(ver[2])]\n : [1, 0, 0];\n out.push({ pack_id: packId, version });\n }\n return { entries: out };\n } catch {\n return { entries: [], parseFailedFile: file };\n }\n}\n\n/** \u517C\u5BB9\u8BFB\u4FA7\uFF1A\u53EA\u8981 entries\uFF08\u635F\u574F\u65F6\u4E0E\u7F3A\u5931\u540C\u4E3A []\uFF09\u3002\u8BE6\u7EC6\u7ED3\u679C\u89C1 readWorldPackListResult\u3002 */\nexport function readWorldPackList(\n worldsDir: string,\n levelName: string,\n kind: \"behavior\" | \"resource\"\n): Array<{ pack_id: string; version: [number, number, number] }> {\n return readWorldPackListResult(worldsDir, levelName, kind).entries;\n}\n\n/** \u4E16\u754C enable-list \u662F\u5426\u5DF2\u542B\u6307\u5B9A pack_id(\u53EA\u8BFB,\u4F9B preflight \u590D\u7528)\u3002 */\nexport function worldPackListHas(\n worldsDir: string,\n levelName: string,\n kind: \"behavior\" | \"resource\",\n packUuid: string\n): boolean {\n return readWorldPackList(worldsDir, levelName, kind).some((e) => e.pack_id === packUuid);\n}"],
|
|
5
|
-
"mappings": "
|
|
4
|
+
"sourcesContent": ["/**\n * pack-manager.ts \u2014 Bedrock \u884C\u4E3A\u5305\uFF08BP\uFF09\u4E0E\u8D44\u6E90\u5305\uFF08RP\uFF09\u7EC4\u88C5\u53CA\u90E8\u7F72\u5F15\u64CE\n *\n * \u6838\u5FC3\u8BBE\u8BA1\u4E0E\u8C03\u7528\u8DEF\u5F84\uFF1A\n * - \u8FDB\u7A0B\u5185\u76F4\u8FDE\uFF08\u63A8\u8350\uFF09\uFF1A`@sfmc-bds/bds-tools/pack-manager-lib` \u4F9B CLI \u7F16\u6392\u4E0E\u751F\u547D\u5468\u671F\u7BA1\u7406\u76F4\u63A5\u8C03\u7528\uFF08\u9075\u5FAA\u4F9D\u8D56\u5012\u7F6E\u539F\u5219\uFF09\n * - \u72EC\u7ACB CLI\uFF1A\u7531 `cli-pack-manager.ts` \u66B4\u9732\u547D\u4EE4\u884C\u5B50\u547D\u4EE4\u4F9B\u811A\u672C\u4E0E\u624B\u5DE5\u8C03\u8BD5\u4F7F\u7528\n *\n * \u6838\u5FC3\u80FD\u529B\uFF1A\n * - \u884C\u4E3A\u5305\u7EC4\u88C5\uFF1A\u5C06 esbuild \u6253\u5305\u540E\u7684 `scripts/main.js`\u3001\u5143\u6570\u636E manifest \u4E0E\u56FE\u6807\u5C01\u88C5\u4E3A BDS \u884C\u4E3A\u5305\u7ED3\u6784\n * - \u8D44\u6E90\u5305\u805A\u5408\uFF1A\u5C06\u5404\u6A21\u5757\u79C1\u6709\u7684 `resource_pack` \u76EE\u5F55\u65E0\u51B2\u7A81\u9012\u5F52\u5408\u5E76\u4E3A\u805A\u5408\u8D44\u6E90\u5305\n * - \u4E16\u754C\u90E8\u7F72\u4E0E\u6E05\u5355\u6FC0\u6D3B\uFF1A\u5C06\u5305\u90E8\u7F72\u81F3 BDS `<level>/behavior_packs` \u4E0E `resource_packs`\uFF0C\u5E76\u540C\u6B65\u7EF4\u62A4 `world_behavior_packs.json`\n */\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { copyDirAsync, copyFileAsync, readJsonFile } from \"./fsx.js\";\n\n/* \u2500\u2500 \u7C7B\u578B\u5B9A\u4E49 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 interface AssembleBehaviorPackOpts {\n /** \u5DF2\u5B8C\u6210\u6253\u5305\u7684 `scripts/main.js` \u6240\u5728\u6E90\u7801\u76EE\u5F55\uFF08\u5373 esbuild \u8F93\u51FA\u76EE\u5F55\uFF09\u3002 */\n srcDir: string;\n /** \u884C\u4E3A\u5305\u76EE\u6807\u8F93\u51FA\u76EE\u5F55\uFF08\u82E5\u4E0D\u5B58\u5728\u5219\u81EA\u52A8\u521B\u5EFA\uFF09\u3002 */\n outDir: string;\n /** BP \u9879\u76EE/\u76EE\u5F55\u540D\uFF08\u9ED8\u8BA4\u4E3A `'sfmc-modules'`\uFF09\u3002 */\n projectName: string;\n /** `manifest.json` \u4E2D\u7684 `header.version` `[major, minor, patch]`\uFF08\u9ED8\u8BA4\u4E3A `[1, 0, 0]`\uFF09\u3002 */\n version?: [number, number, number] | undefined;\n /** `manifest.json` \u4E2D\u7684\u5305\u63CF\u8FF0\u4FE1\u606F\u3002 */\n description?: string | undefined;\n /** `pack_icon.png` \u56FE\u6807\u6E90\u6587\u4EF6\u8DEF\u5F84\uFF08\u53EF\u9009\uFF0C\u672A\u63D0\u4F9B\u5219\u8DF3\u8FC7\uFF09\u3002 */\n iconSrc?: string | undefined;\n /** \u7A33\u5B9A\u7684 `header.uuid`\uFF08\u7F3A\u7701\u65F6\u5C06\u5728\u9996\u6B21\u88C5\u914D\u65F6\u968F\u673A\u751F\u6210\uFF09\u3002 */\n uuid?: string | undefined;\n /** \u7A33\u5B9A\u7684 `script module uuid`\uFF08\u7F3A\u7701\u65F6\u968F\u673A\u751F\u6210\uFF09\u3002 */\n moduleUuid?: string | undefined;\n}\n\nexport interface AssembleResourcePackOpts {\n /** \u9700\u5408\u5E76\u8D44\u6E90\u5305\u76EE\u5F55\u7684\u6A21\u5757\u6620\u5C04\u5B57\u5178\uFF08`Record<moduleId, resourcePackDir>`\uFF09\u3002 */\n moduleResourceDirs: Record<string, string>;\n /** \u8D44\u6E90\u5305\u76EE\u6807\u8F93\u51FA\u76EE\u5F55\uFF08\u82E5\u4E0D\u5B58\u5728\u5219\u81EA\u52A8\u521B\u5EFA\uFF09\u3002 */\n outDir: string;\n /** RP \u9879\u76EE/\u76EE\u5F55\u540D\u3002 */\n projectName: string;\n /** `manifest.json` \u4E2D\u7684 `header.version` `[major, minor, patch]`\uFF08\u9ED8\u8BA4\u4E3A `[1, 0, 0]`\uFF09\u3002 */\n version?: [number, number, number] | undefined;\n /** `manifest.json` \u4E2D\u7684\u5305\u63CF\u8FF0\u4FE1\u606F\u3002 */\n description?: string | undefined;\n /** \u7A33\u5B9A\u7684 `header.uuid`\uFF08\u7F3A\u7701\u65F6\u968F\u673A\u751F\u6210\uFF09\u3002 */\n uuid?: string | undefined;\n /** \u7A33\u5B9A\u7684 `resources module uuid`\uFF08\u7F3A\u7701\u65F6\u968F\u673A\u751F\u6210\uFF09\u3002 */\n moduleUuid?: string | undefined;\n}\n\n\nexport interface AssembleResult {\n uuid: string;\n version: [number, number, number];\n}\n\nexport interface DeployOpts {\n bdsRoot: string;\n levelName: string;\n /** \u5DF2\u7EC4\u88C5\u597D\u7684 BP \u6E90\u76EE\u5F55 */\n behaviorPackSrc: string;\n /** \u5DF2\u7EC4\u88C5\u597D\u7684 RP \u6E90\u76EE\u5F55 (\u53EF\u7701\u7565,\u53EA\u7528 BP \u4E5F\u5408\u6CD5) */\n resourcePackSrc?: string;\n /** BP \u76EE\u6807\u76EE\u5F55\u540D (worlds/<level>/behavior_packs/<bpName>) */\n bpName: string;\n /** RP \u76EE\u6807\u76EE\u5F55\u540D (worlds/<level>/resource_packs/<rpName>);\u7701\u7565\u65F6\u590D\u7528 bpName + '-rp' */\n rpName?: string;\n /**\n * \u65E0 resourcePackSrc \u65F6\u662F\u5426\u5220\u9664\u4E16\u754C\u5185\u5DF2\u6709 RP \u76EE\u5F55\u3002\n * \u7528\u4E8E\u6A21\u5757\u4E0D\u518D\u63D0\u4F9B RP \u65F6\u6E05\u7406\u805A\u5408\u5305\u6B8B\u7559(\u9ED8\u8BA4 false,\u907F\u514D\u8BEF\u5220\u672A\u58F0\u660E\u7684 RP)\u3002\n */\n clearResourcePack?: boolean;\n}\n\nexport interface DeployResult {\n bpDir: string;\n rpDir: string | null;\n}\n\nexport interface EnablePackOpts {\n worldsDir: string;\n levelName: string;\n kind: \"behavior\" | \"resource\";\n packUuid: string;\n version: [number, number, number];\n}\n\n/* \u2500\u2500 \u8DEF\u5F84\u5E38\u91CF \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n/** SFMC \u5408\u6210 BP \u7684\u56FA\u5B9A @minecraft/* permissions,\u6240\u6709\u7528\u5230\u7684\u547D\u540D\u7A7A\u95F4\u90FD\u6253\u5F00\u3002 */\nexport const SFMC_PERMISSIONS = [\n \"@minecraft/server\",\n \"@minecraft/server-ui\",\n \"@minecraft/server-admin\",\n \"@minecraft/server-gametest\",\n \"@minecraft/server-net\",\n \"@minecraft/server-editor\",\n \"@minecraft/diagnostics\",\n] as const;\n\n/** `<bdsRoot>/server.properties` \u2014 level-name / telemetry \u7B49\u5171\u7528\uFF08DRY\uFF09 */\nexport function serverPropertiesPath(bdsRoot: string): string {\n return path.join(bdsRoot, \"server.properties\");\n}\n\n/** `<bdsRoot>/worlds` \u2014 enable-list / \u90E8\u7F72\u8C03\u7528\u65B9\u52FF\u518D\u786C\u62FC\uFF08Demeter\uFF09 */\nexport function bdsWorldsDir(bdsRoot: string): string {\n return path.join(bdsRoot, \"worlds\");\n}\n\n/** `<bdsRoot>/worlds/<level>` */\nexport function bdsWorldLevelDir(bdsRoot: string, levelName: string): string {\n return path.join(bdsWorldsDir(bdsRoot), levelName);\n}\n\n/** \u4E16\u754C enable-list JSON \u7EDD\u5BF9\u8DEF\u5F84\uFF08\u5355\u4E00\u6743\u5A01\uFF0C\u4F9B\u8BFB\u5199\u4E24\u4FA7\uFF09 */\nexport function worldPackListFile(\n worldsDir: string,\n levelName: string,\n kind: \"behavior\" | \"resource\"\n): string {\n const name = kind === \"behavior\" ? \"world_behavior_packs.json\" : \"world_resource_packs.json\";\n return path.join(worldsDir, levelName, name);\n}\n\n/** `<bdsRoot>/config/<bpUuid>/permission.json` \u2014 Script API \u6743\u9650\u6587\u4EF6\u6743\u5A01\u8DEF\u5F84 */\nexport function configPermissionPath(bdsRoot: string, bpUuid: string): string {\n return path.join(bdsRoot, \"config\", bpUuid, \"permission.json\");\n}\n\n/** \u662F\u5426\u5DF2\u6709 Script API permission.json\uFF08\u53EA\u8BFB\uFF0C\u4F9B preflight/status\uFF09 */\nexport function hasConfigPermission(bdsRoot: string, bpUuid: string): boolean {\n return fs.existsSync(configPermissionPath(bdsRoot, bpUuid));\n}\n\n/** \u968F\u673A\u751F\u6210 BP/RP manifest.json header.uuid (RFC 4122 v4) */\nexport function randomUuid(): string {\n /* crypto.randomUUID \u662F Node 19+ \u5185\u7F6E,\u8FD9\u91CC\u76F4\u63A5\u7528 */\n return crypto.randomUUID();\n}\n\n/* \u2500\u2500 \u9AA8\u67B6\u51FD\u6570 (Commit 5 \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 */\n\n/**\n * Assemble a Bedrock behavior pack directory at `outDir` from a prebuilt\n * `srcDir` (which must already contain `scripts/main.js` plus whatever else\n * was bundled by esbuild) and write a fresh `manifest.json` + `permissions.json`.\n *\n * The caller is responsible for running esbuild first; pack-manager does not\n * bundle scripts. That decoupling keeps pack assembly independent of the bundler.\n */\nexport async function assembleBehaviorPack(opts: AssembleBehaviorPackOpts): Promise<AssembleResult> {\n const version = opts.version ?? [1, 0, 0];\n const bpUuid = opts.uuid ?? randomUuid();\n await fs.promises.rm(opts.outDir, { recursive: true, force: true });\n await fs.promises.mkdir(opts.outDir, { recursive: true });\n if (fs.existsSync(opts.srcDir)) {\n await copyDirAsync(opts.srcDir, opts.outDir);\n } else {\n await fs.promises.mkdir(path.join(opts.outDir, \"scripts\"), { recursive: true });\n await fs.promises.writeFile(path.join(opts.outDir, \"scripts\", \"main.js\"), \"/* no scripts */\\n\", \"utf8\");\n }\n await writeBehaviorPackManifest(opts.outDir, {\n name: opts.projectName,\n uuid: bpUuid,\n version,\n description: opts.description,\n moduleUuid: opts.moduleUuid,\n });\n if (opts.iconSrc && fs.existsSync(opts.iconSrc)) {\n await copyFileAsync(opts.iconSrc, path.join(opts.outDir, \"pack_icon.png\"));\n }\n await writePermissionsJson(opts.outDir);\n return { uuid: bpUuid, version };\n}\n\n/**\n * Merge every enabled module's `resource_pack/**` tree into one RP directory\n * at `outDir`, with a single fresh `manifest.json`. Per-module subfolders are\n * preserved so resource pack authors can disambiguate (e.g. `peace/textures/...`).\n */\nexport async function assembleResourcePack(opts: AssembleResourcePackOpts): Promise<AssembleResult> {\n const version = opts.version ?? [1, 0, 0];\n const rpUuid = opts.uuid ?? randomUuid();\n await fs.promises.rm(opts.outDir, { recursive: true, force: true });\n await fs.promises.mkdir(opts.outDir, { recursive: true });\n for (const [moduleId, rpDir] of Object.entries(opts.moduleResourceDirs)) {\n if (!fs.existsSync(rpDir)) continue;\n const dst = path.join(opts.outDir, moduleId);\n await fs.promises.mkdir(dst, { recursive: true });\n await copyDirAsync(rpDir, dst);\n }\n await writeResourcePackManifest(opts.outDir, {\n name: opts.projectName,\n uuid: rpUuid,\n version,\n description: opts.description,\n moduleUuid: opts.moduleUuid,\n });\n return { uuid: rpUuid, version };\n}\n\n/**\n * Read the `level-name=` value from `<bdsRoot>/server.properties`.\n * Falls back to \"Bedrock level\" (BDS default) when the file is missing or\n * the key is absent.\n */\nfunction parseLevelNameFromProperties(text: string): string {\n for (const line of text.split(/\\r?\\n/)) {\n const m = /^\\s*level-name\\s*=\\s*(.+?)\\s*$/.exec(line);\n if (m && m[1]) return m[1];\n }\n return \"Bedrock level\";\n}\n\n/** \u540C\u6B65\u8BFB level-name\uFF08\u4F9B sfmc resolveBdsContext \u7B49\u540C\u8FDB\u7A0B\u8C03\u7528\u65B9\uFF0CDRY\uFF09\u3002 */\nexport function readLevelNameSync(bdsRoot: string): string {\n const file = serverPropertiesPath(bdsRoot);\n if (!fs.existsSync(file)) return \"Bedrock level\";\n return parseLevelNameFromProperties(fs.readFileSync(file, \"utf8\"));\n}\n\n/** \u4E0E sync \u540C\u5951\u7EA6\uFF1BCLI / async \u8C03\u7528\u65B9\u8D70\u6B64\u5165\u53E3\uFF08LSP\uFF09 */\nexport async function readLevelName(bdsRoot: string): Promise<string> {\n return readLevelNameSync(bdsRoot);\n}\n\n/**\n * Copy BP/RP source dirs into the world's behavior_packs/ + resource_packs/\n * folders, and write a fresh `permissions.json` into the BP target.\n *\n * Does NOT edit world_behavior_packs.json \u2014 that's a separate step the caller\n * must invoke after restart, because BDS only reads that file at startup.\n */\nexport async function deployToBDS(opts: DeployOpts): Promise<DeployResult> {\n /* levelDir = worlds/<level>\uFF1B\u4E0E EnablePackOpts.worldsDir(=worlds/) \u8BED\u4E49\u4E0D\u540C \u2014 \u52FF\u6DF7\u7528\uFF08LSP\uFF09 */\n const levelDir = bdsWorldLevelDir(opts.bdsRoot, opts.levelName);\n const bpDst = path.join(levelDir, \"behavior_packs\", opts.bpName);\n const rpDst = path.join(levelDir, \"resource_packs\", opts.rpName ?? `${opts.bpName}-rp`);\n await fs.promises.mkdir(levelDir, { recursive: true });\n await fs.promises.rm(bpDst, { recursive: true, force: true });\n await copyDirAsync(opts.behaviorPackSrc, bpDst);\n await writePermissionsJson(bpDst);\n let rpDir: string | null = null;\n if (opts.resourcePackSrc && fs.existsSync(opts.resourcePackSrc)) {\n await fs.promises.rm(rpDst, { recursive: true, force: true });\n await copyDirAsync(opts.resourcePackSrc, rpDst);\n rpDir = rpDst;\n } else if (opts.clearResourcePack) {\n /* \u8C03\u7528\u65B9\u663E\u5F0F\u58F0\u660E\u4E0D\u518D\u90E8\u7F72 RP \u2014 \u6E05\u6389\u805A\u5408 RP \u76EE\u5F55\u6B8B\u7559 */\n await fs.promises.rm(rpDst, { recursive: true, force: true });\n }\n return { bpDir: bpDst, rpDir };\n}\n\n/**\n * \u786E\u4FDD BDS Script API \u4FA7 `<bdsRoot>/config/<bpUuid>/permission.json` \u5B58\u5728\u3002\n * \u5DF2\u5B58\u5728\u5219\u8DF3\u8FC7(\u4E0D\u8986\u76D6\u7528\u6237\u624B\u5DE5\u6539\u52A8)\u3002\n * @returns true = \u65B0\u5199\u5165; false = \u5DF2\u5B58\u5728\u8DF3\u8FC7\n */\nexport async function ensureConfigPermission(bdsRoot: string, bpUuid: string): Promise<boolean> {\n const file = configPermissionPath(bdsRoot, bpUuid);\n if (fs.existsSync(file)) return false;\n const dir = path.dirname(file);\n await fs.promises.mkdir(dir, { recursive: true });\n const payload = { allowed_modules: [...SFMC_PERMISSIONS] };\n const tmp = path.join(dir, `.permission.${process.pid}.tmp`);\n await fs.promises.writeFile(tmp, JSON.stringify(payload, null, 2) + \"\\n\", \"utf8\");\n await fs.promises.rename(tmp, file);\n return true;\n}\n\n/** \u4ECE\u5DF2\u88C5\u914D BP/RP \u76EE\u5F55\u8BFB\u53D6 header.uuid + version;\u5931\u8D25\u8FD4\u56DE null\u3002 */\nexport function readPackManifestHeader(\n packDir: string\n): { uuid: string; version: [number, number, number]; moduleUuid?: string } | null {\n const file = path.join(packDir, \"manifest.json\");\n if (!fs.existsSync(file)) return null;\n try {\n const raw = readJsonFile<{\n header?: { uuid?: string; version?: number[] };\n modules?: Array<{ uuid?: string }>;\n }>(file);\n const uuid = raw.header?.uuid;\n const ver = raw.header?.version;\n if (typeof uuid !== \"string\" || !Array.isArray(ver) || ver.length < 3) return null;\n const version: [number, number, number] = [Number(ver[0]), Number(ver[1]), Number(ver[2])];\n const moduleUuid = raw.modules?.[0]?.uuid;\n return { uuid, version, ...(typeof moduleUuid === \"string\" ? { moduleUuid } : {}) };\n } catch {\n return null;\n }\n}\n\n/**\n * Write `@minecraft/*` allowed_modules into a behavior pack's\n * `permissions.json`. Idempotent: rewrites any pre-existing file.\n */\nexport async function writePermissionsJson(bpDir: string): Promise<void> {\n const payload = { allowed_modules: [...SFMC_PERMISSIONS] };\n await fs.promises.mkdir(bpDir, { recursive: true });\n const tmp = path.join(bpDir, `.permissions.${process.pid}.tmp`);\n await fs.promises.writeFile(tmp, JSON.stringify(payload, null, 2) + \"\\n\", \"utf8\");\n await fs.promises.rename(tmp, path.join(bpDir, \"permissions.json\"));\n}\n\n/**\n * Add `{ pack_id, version }` to `worlds/<level>/world_behavior_packs.json`\n * (or `world_resource_packs.json`). If the pack_id already exists, replace its\n * version. File missing \u2192 initialize as `[]`.\n */\nexport async function enablePackInWorld(opts: EnablePackOpts): Promise<void> {\n await editWorldPackList(opts, \"enable\");\n}\n\n/** Remove a pack_id from the world's enable-list JSON. */\nexport async function disablePackInWorld(opts: EnablePackOpts): Promise<void> {\n await editWorldPackList(opts, \"disable\");\n}\n\ninterface WorldPackEntry {\n pack_id: string;\n version: [number, number, number];\n}\n\nasync function editWorldPackList(\n opts: EnablePackOpts,\n mode: \"enable\" | \"disable\"\n): Promise<void> {\n const file = worldPackListFile(opts.worldsDir, opts.levelName, opts.kind);\n /* \u4E0E readWorldPackList \u540C\u6E90\u89E3\u6790,\u518D\u5199\u56DE(DRY);\u5F02\u6B65\u5199\u8DEF\u5F84\u4FDD\u7559\u539F\u8BED\u4E49 */\n let entries: WorldPackEntry[] = readWorldPackList(opts.worldsDir, opts.levelName, opts.kind);\n const idx = entries.findIndex((e) => e.pack_id === opts.packUuid);\n if (mode === \"enable\") {\n const next: WorldPackEntry = { pack_id: opts.packUuid, version: opts.version };\n if (idx >= 0) entries[idx] = next;\n else entries.push(next);\n } else {\n if (idx >= 0) entries.splice(idx, 1);\n }\n await fs.promises.mkdir(path.dirname(file), { recursive: true });\n const tmp = `${file}.${process.pid}.tmp`;\n await fs.promises.writeFile(tmp, JSON.stringify(entries, null, 2) + \"\\n\", \"utf8\");\n await fs.promises.rename(tmp, file);\n}\n\n/* \u2500\u2500 \u4F4E\u5C42 helpers (Commit 5 \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 */\n\nexport async function writeBehaviorPackManifest(\n outDir: string,\n header: {\n name: string;\n uuid: string;\n version: [number, number, number];\n description?: string | undefined;\n moduleUuid?: string | undefined;\n }\n): Promise<void> {\n const manifest = {\n format_version: 2,\n header: {\n name: header.name,\n uuid: header.uuid,\n version: header.version,\n description: header.description ? `${header.description} (behavior pack)` : \"SFMC behavior pack\",\n min_engine_version: [1, 21, 0],\n },\n modules: [\n {\n type: \"script\",\n language: \"javascript\",\n entry: \"scripts/main.js\",\n uuid: header.moduleUuid ?? crypto.randomUUID(),\n version: header.version,\n },\n ],\n dependencies: [\n { module_name: \"@minecraft/server\", version: \"1.18.0\" },\n { module_name: \"@minecraft/server-admin\", version: \"1.0.0-beta\" },\n { module_name: \"@minecraft/diagnostics\", version: \"1.0.0-beta\" },\n ],\n };\n const file = path.join(outDir, \"manifest.json\");\n await fs.promises.mkdir(outDir, { recursive: true });\n await fs.promises.writeFile(file, JSON.stringify(manifest, null, 2) + \"\\n\", \"utf8\");\n}\n\nexport async function writeResourcePackManifest(\n outDir: string,\n header: {\n name: string;\n uuid: string;\n version: [number, number, number];\n description?: string | undefined;\n moduleUuid?: string | undefined;\n }\n): Promise<void> {\n const manifest = {\n format_version: 2,\n header: {\n name: header.name,\n uuid: header.uuid,\n version: header.version,\n description: header.description ? `${header.description} (resource pack)` : \"SFMC resource pack\",\n min_engine_version: [1, 21, 0],\n },\n modules: [\n {\n type: \"resources\",\n uuid: header.moduleUuid ?? crypto.randomUUID(),\n version: header.version,\n },\n ],\n };\n const file = path.join(outDir, \"manifest.json\");\n await fs.promises.mkdir(outDir, { recursive: true });\n await fs.promises.writeFile(file, JSON.stringify(manifest, null, 2) + \"\\n\", \"utf8\");\n}\n\n/* Re-export copyFileAsync so callers can copy icon without\n * pulling in the full fsx surface area. */\nexport { copyFileAsync, copyDirAsync };\n\n/* \u2500\u2500 Discovery \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n/**\n * Walk `<modulesDir>/<id>/resource_pack/` for every installed module and\n * return a map { id: absoluteDir }. Modules without a resource_pack folder\n * are silently skipped. Used by `assemble-rp` and the sfmc CLI to know which\n * modules to merge into the resource pack output.\n */\nexport function scanModuleResourcePacks(modulesDir: string): Record<string, string> {\n const out: Record<string, string> = {};\n if (!fs.existsSync(modulesDir)) return out;\n for (const entry of fs.readdirSync(modulesDir, { withFileTypes: true })) {\n if (entry.name.startsWith(\".\")) continue;\n // \u8DDF\u968F symlink\uFF08--link \u5B89\u88C5\uFF09\uFF1BDirent.isDirectory() \u5BF9\u94FE\u63A5\u76EE\u5F55\u4E3A false\n try {\n if (!fs.statSync(path.join(modulesDir, entry.name)).isDirectory()) continue;\n } catch {\n continue;\n }\n const rpDir = path.join(modulesDir, entry.name, \"resource_pack\");\n if (fs.existsSync(rpDir)) {\n out[entry.name] = rpDir;\n }\n }\n return out;\n}\n\n/**\n * \u4ECE JSON \u6587\u4EF6\u52A0\u8F7D\u663E\u5F0F moduleId \u2192 resource_pack \u76EE\u5F55\u6620\u5C04\u3002\n * \u4F9B assemble-rp --modules-json \u4F7F\u7528,\u907F\u514D\u8C03\u7528\u65B9\u518D\u505A\u4E34\u65F6\u76EE\u5F55\u955C\u50CF(OCP/DRY)\u3002\n */\nexport function loadModuleResourcePackMap(jsonPath: string): Record<string, string> {\n const raw = JSON.parse(fs.readFileSync(jsonPath, \"utf8\")) as unknown;\n if (!raw || typeof raw !== \"object\" || Array.isArray(raw)) {\n throw new Error(`modules-json must be an object: ${jsonPath}`);\n }\n const out: Record<string, string> = {};\n for (const [id, dir] of Object.entries(raw as Record<string, unknown>)) {\n if (typeof id !== \"string\" || !id || typeof dir !== \"string\" || !dir) continue;\n const abs = path.resolve(dir);\n if (!fs.existsSync(abs)) {\n throw new Error(`modules-json entry missing: ${id} \u2192 ${abs}`);\n }\n out[id] = abs;\n }\n return out;\n}\n\n/**\n * \u8BFB\u53D6\u4E16\u754C enable-list(\u5355\u4E00\u6743\u5A01,\u4F9B has-pack / list-packs / \u8C03\u7528\u65B9\u590D\u7528 \u2014 DRY)\u3002\n * \u6587\u4EF6\u7F3A\u5931 \u2192 entries=[]\uFF1BJSON \u635F\u574F \u2192 entries=[] \u4E14 parseFailedFile \u6709\u503C\uFF08\u4F9B doctor \u533A\u5206\uFF09\u3002\n */\nexport type WorldPackListReadResult = {\n entries: Array<{ pack_id: string; version: [number, number, number] }>;\n /** \u6587\u4EF6\u5B58\u5728\u4F46\u89E3\u6790\u5931\u8D25\u65F6\u4E3A\u8BE5 JSON \u7EDD\u5BF9\u8DEF\u5F84 */\n parseFailedFile?: string;\n};\n\nexport function readWorldPackListResult(\n worldsDir: string,\n levelName: string,\n kind: \"behavior\" | \"resource\"\n): WorldPackListReadResult {\n const file = worldPackListFile(worldsDir, levelName, kind);\n if (!fs.existsSync(file)) return { entries: [] };\n try {\n const arr = JSON.parse(fs.readFileSync(file, \"utf8\")) as unknown;\n if (!Array.isArray(arr)) return { entries: [], parseFailedFile: file };\n const out: Array<{ pack_id: string; version: [number, number, number] }> = [];\n for (const e of arr) {\n if (!e || typeof e !== \"object\") continue;\n const packId = (e as { pack_id?: unknown }).pack_id;\n const ver = (e as { version?: unknown }).version;\n if (typeof packId !== \"string\" || !packId) continue;\n const version: [number, number, number] =\n Array.isArray(ver) && ver.length >= 3\n ? [Number(ver[0]), Number(ver[1]), Number(ver[2])]\n : [1, 0, 0];\n out.push({ pack_id: packId, version });\n }\n return { entries: out };\n } catch {\n return { entries: [], parseFailedFile: file };\n }\n}\n\n/** \u517C\u5BB9\u8BFB\u4FA7\uFF1A\u53EA\u8981 entries\uFF08\u635F\u574F\u65F6\u4E0E\u7F3A\u5931\u540C\u4E3A []\uFF09\u3002\u8BE6\u7EC6\u7ED3\u679C\u89C1 readWorldPackListResult\u3002 */\nexport function readWorldPackList(\n worldsDir: string,\n levelName: string,\n kind: \"behavior\" | \"resource\"\n): Array<{ pack_id: string; version: [number, number, number] }> {\n return readWorldPackListResult(worldsDir, levelName, kind).entries;\n}\n\n/** \u4E16\u754C enable-list \u662F\u5426\u5DF2\u542B\u6307\u5B9A pack_id(\u53EA\u8BFB,\u4F9B preflight \u590D\u7528)\u3002 */\nexport function worldPackListHas(\n worldsDir: string,\n levelName: string,\n kind: \"behavior\" | \"resource\",\n packUuid: string\n): boolean {\n return readWorldPackList(worldsDir, levelName, kind).some((e) => e.pack_id === packUuid);\n}"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|