Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .changeset/build-deps-world-packs-solid.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@
"@sfmc-bds/bds-tools": patch
---

发版:build-publishable 拓扑 + listPublishableBuildDeps(npm-publish 应急补发不再硬编码只 build SDK);push 缺失态 DRY 对齐 listUnpushedExistingVersionTags。世界包:readPackDirOccupancy DRY,去掉死不变式,occupancy 保留真实 kind(LSP)。
发版:build-publishable 拓扑 + listPublishableBuildDeps(npm-publish 应急补发不再硬编码只 build SDK);push 缺失态 DRY 对齐 listUnpushedExistingVersionTags。世界包:readPackDirOccupancy DRY,去掉死不变式,occupancy 保留真实 kind(LSP)。修 #80/#81 合并冲突:scanDestOccupancy 须赋值 facts=readPackDirOccupancy,禁止残留未声明 uuid/version/name 赋值(否则 --dts 挂掉且 catch 吞掉 ReferenceError 导致占用 uuid 恒空)。
11 changes: 9 additions & 2 deletions bds-tools/src/world-packs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -566,7 +566,8 @@ export type PackInstallPlan =

/**
* 读单目录占用事实(info 优先,否则 header)。
* 解析失败返回 null;BOM 已由 readJsonFile 剥离,不再抛 Utf8BomError。
* info/header 解析失败返回 null;BOM 已由 readJsonFile 剥离。
* 其它异常上抛,由 scanDestOccupancy 决定仍占文件夹名(uuid 置空)。
*/
export function readPackDirOccupancy(dir: string): {
uuid: string;
Expand Down Expand Up @@ -594,7 +595,13 @@ export function readPackDirOccupancy(dir: string): {
export function scanDestOccupancy(destParent: string): DestOccupancy[] {
const out: DestOccupancy[] = [];
for (const dir of listPackDirsIn(destParent)) {
const facts = readPackDirOccupancy(dir);
let facts: ReturnType<typeof readPackDirOccupancy> = null;
try {
// DRY:单目录占用只走 readPackDirOccupancy,禁止再内联一份 info/header 分支
facts = readPackDirOccupancy(dir);
} catch {
/* manifest 不可读则占位 uuid 为空(#81 契约:扫描本身不因单目录失败而中断) */
}
out.push({
folderName: path.basename(dir),
dir,
Expand Down
53 changes: 25 additions & 28 deletions bds-tools/world-packs.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -283,52 +283,49 @@ describe("world-packs primitives", () => {
assert.deepEqual(version, [2, 0, 1]);
});

it("scanDestOccupancy / readPackDirOccupancy:完整与残缺 manifest", async () => {
const { scanDestOccupancy, readPackDirOccupancy, formatWorldPackFolderName } = await import(
"./dist/world-packs.js"
);
const parent = path.join(tmp, "occupancy-scan");
const fullName = formatWorldPackFolderName("Full", "resource");
const brokenName = formatWorldPackFolderName("Broken", "behavior");
const fullDir = path.join(parent, fullName);
const brokenDir = path.join(parent, brokenName);
it("scanDestOccupancy 走 readPackDirOccupancy(完整 + 残缺 header)", async () => {
const { scanDestOccupancy, readPackDirOccupancy } = await import("./dist/world-packs.js");
const dest = path.join(tmp, "occupancy-dry");
const fullDir = path.join(dest, "[RP] Full");
writeManifest(fullDir, {
name: "Full Pack",
uuid: "11111111-1111-1111-1111-111111111111",
version: [2, 3, 4],
uuid: "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa",
version: [2, 1, 0],
type: "resources",
});
fs.mkdirSync(brokenDir, { recursive: true });
const partialDir = path.join(dest, "[RP] Partial");
fs.mkdirSync(partialDir, { recursive: true });
fs.writeFileSync(
path.join(brokenDir, "manifest.json"),
path.join(partialDir, "manifest.json"),
JSON.stringify({
format_version: 2,
header: {
name: "Broken Pack",
uuid: "22222222-2222-2222-2222-222222222222",
version: [9, 0, 1],
name: "Partial",
uuid: "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb",
version: [3, 0, 0],
},
modules: [],
})
);

const fullFacts = readPackDirOccupancy(fullDir);
assert.equal(fullFacts?.uuid, "11111111-1111-1111-1111-111111111111");
assert.deepEqual(fullFacts?.version, [2, 3, 4]);
assert.equal(fullFacts?.uuid, "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa");
assert.deepEqual(fullFacts?.version, [2, 1, 0]);
assert.equal(fullFacts?.name, "Full Pack");
assert.equal(fullFacts?.kind, "resource");

const brokenFacts = readPackDirOccupancy(brokenDir);
assert.equal(brokenFacts?.uuid, "22222222-2222-2222-2222-222222222222");
assert.deepEqual(brokenFacts?.version, [9, 0, 1]);
assert.equal(brokenFacts?.kind, undefined);
const partialFacts = readPackDirOccupancy(partialDir);
assert.equal(partialFacts?.uuid, "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb");
assert.deepEqual(partialFacts?.version, [3, 0, 0]);
assert.equal(partialFacts?.kind, undefined);

const occ = scanDestOccupancy(parent);
const occ = scanDestOccupancy(dest);
assert.equal(occ.length, 2);
const byFolder = Object.fromEntries(occ.map((o) => [o.folderName, o]));
assert.equal(byFolder[fullName]?.uuid, "11111111-1111-1111-1111-111111111111");
assert.equal(byFolder[fullName]?.kind, "resource");
assert.equal(byFolder[brokenName]?.uuid, "22222222-2222-2222-2222-222222222222");
assert.equal(byFolder[brokenName]?.kind, undefined);
const byUuid = new Map(occ.map((o) => [o.uuid, o]));
assert.equal(byUuid.get("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa")?.name, "Full Pack");
assert.equal(byUuid.get("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa")?.kind, "resource");
assert.equal(byUuid.get("bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb")?.version?.[0], 3);
assert.equal(byUuid.get("bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb")?.name, undefined);
});

it("decidePackInstallPlan 表驱动", async () => {
Expand Down