diff --git a/.changeset/fix-scan-dest-occupancy-dry.md b/.changeset/fix-scan-dest-occupancy-dry.md new file mode 100644 index 0000000..2753592 --- /dev/null +++ b/.changeset/fix-scan-dest-occupancy-dry.md @@ -0,0 +1,5 @@ +--- +"@sfmc-bds/bds-tools": patch +--- + +修复 #80 合入冲突残留:`scanDestOccupancy` 恢复走 `readPackDirOccupancy`(DRY),消除未声明标识符导致的 tsc7 构建失败。 diff --git a/bds-tools/src/world-packs.ts b/bds-tools/src/world-packs.ts index 2659b4b..9201999 100644 --- a/bds-tools/src/world-packs.ts +++ b/bds-tools/src/world-packs.ts @@ -566,7 +566,7 @@ export type PackInstallPlan = /** * 读单目录占用事实(info 优先,否则 header)。 - * 解析失败返回 null;不抛 BOM(readJsonFile 已剥离)。 + * 解析失败返回 null;BOM 已由 readJsonFile 剥离,不再抛 Utf8BomError。 */ export function readPackDirOccupancy(dir: string): { uuid: string; @@ -590,17 +590,11 @@ export function readPackDirOccupancy(dir: string): { return null; } -/** 扫描 destParent 下含 manifest 的目录占用(单一事实源:readPackDirOccupancy) */ +/** 扫描 destParent 下含 manifest 的目录占用(占用事实唯一入口:readPackDirOccupancy) */ export function scanDestOccupancy(destParent: string): DestOccupancy[] { const out: DestOccupancy[] = []; for (const dir of listPackDirsIn(destParent)) { - let facts: ReturnType = null; - try { - // DRY:与 readPackDirOccupancy 共用 info→header 回退,禁止内联双读 - facts = readPackDirOccupancy(dir); - } catch { - /* manifest 不可读则占位 uuid 为空 */ - } + const facts = readPackDirOccupancy(dir); out.push({ folderName: path.basename(dir), dir, diff --git a/bds-tools/world-packs.test.mjs b/bds-tools/world-packs.test.mjs index 67caf3a..08e2377 100644 --- a/bds-tools/world-packs.test.mjs +++ b/bds-tools/world-packs.test.mjs @@ -550,6 +550,51 @@ describe("world-packs primitives", () => { assert.equal(readPackManifestInfo(existingB)?.name, "Slash Blade v2b"); }); + 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: "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa", + version: [2, 1, 0], + type: "resources", + }); + const partialDir = path.join(dest, "[RP] Partial"); + fs.mkdirSync(partialDir, { recursive: true }); + fs.writeFileSync( + path.join(partialDir, "manifest.json"), + JSON.stringify({ + format_version: 2, + header: { + name: "Partial", + uuid: "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb", + version: [3, 0, 0], + }, + modules: [], + }) + ); + + const fullFacts = readPackDirOccupancy(fullDir); + 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 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(dest); + assert.equal(occ.length, 2); + 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("installPackDirectory:残缺 manifest 占用目录时换名而非覆盖", async () => { const { installPackDirectory, formatWorldPackFolderName } = await import("./dist/world-packs.js"); const dest = path.join(tmp, "broken-parent");