Files
HiveGrid-Wireframes/03 Quellen und Referenzen/hivegrid-cloud/scripts/prune-pnpm-runtime-closure.test.mjs
T

103 lines
4.8 KiB
JavaScript

// @vitest-environment node
import assert from "node:assert/strict";
import fs from "node:fs";
import os from "node:os";
import path from "node:path";
import { afterEach, describe, test } from "vitest";
import { prunePnpmRuntimeClosure } from "./prune-pnpm-runtime-closure.mjs";
const fixtures = [];
afterEach(() => {
for (const fixture of fixtures.splice(0)) fs.rmSync(fixture, { force: true, recursive: true });
});
describe("pnpm runtime closure pruning", () => {
test("keeps reachable native packages while removing an excluded optional peer toolchain and its orphans", async () => {
const fixture = createFixture();
const nodeModulesPath = path.join(fixture, "node_modules");
const client = addPackage(nodeModulesPath, "@prisma+client@7.8.0_peer", "@prisma/client");
const prisma = addPackage(nodeModulesPath, "prisma@7.8.0_peer", "prisma");
const prismaDev = addPackage(nodeModulesPath, "@prisma+dev@0.24.3", "@prisma/dev");
const pglite = addPackage(nodeModulesPath, "@electric-sql+pglite@0.4.1", "@electric-sql/pglite");
const typescript = addPackage(nodeModulesPath, "typescript@5.9.3", "typescript");
const sharp = addPackage(nodeModulesPath, "sharp@0.35.2", "sharp");
const sharpBinary = addPackage(nodeModulesPath, "@img+sharp-linux-x64@0.35.2", "@img/sharp-linux-x64");
const unrelatedOrphan = addPackage(nodeModulesPath, "orphan@1.0.0", "orphan");
linkPackage(nodeModulesPath, "@prisma/client", client.packagePath);
linkPackage(nodeModulesPath, "prisma", prisma.packagePath);
linkPackage(nodeModulesPath, "typescript", typescript.packagePath);
linkPackage(nodeModulesPath, "sharp", sharp.packagePath);
linkPackage(path.join(client.entryPath, "node_modules"), "prisma", prisma.packagePath);
linkPackage(path.join(prisma.entryPath, "node_modules"), "@prisma/dev", prismaDev.packagePath);
linkPackage(path.join(prismaDev.entryPath, "node_modules"), "@electric-sql/pglite", pglite.packagePath);
linkPackage(path.join(sharp.entryPath, "node_modules"), "@img/sharp-linux-x64", sharpBinary.packagePath);
linkPackage(path.join(nodeModulesPath, ".bin"), "prisma", path.join(prisma.packagePath, "index.js"));
const result = await prunePnpmRuntimeClosure({
excludedPackageNames: ["prisma", "typescript"],
nodeModulesPath,
});
assert.deepEqual(
result.removedEntries,
[
"@electric-sql+pglite@0.4.1",
"@prisma+dev@0.24.3",
"orphan@1.0.0",
"prisma@7.8.0_peer",
"typescript@5.9.3",
].sort()
);
assert.ok(result.bytesRemoved > 0);
assert.ok(result.filesRemoved > 0);
assert.ok(result.brokenLinksRemoved > 0);
assert.ok(fs.existsSync(client.packagePath));
assert.ok(fs.existsSync(sharp.packagePath));
assert.ok(fs.existsSync(sharpBinary.packagePath));
assert.ok(!fs.existsSync(prisma.packagePath));
assert.ok(!fs.existsSync(prismaDev.packagePath));
assert.ok(!fs.existsSync(pglite.packagePath));
assert.ok(!fs.existsSync(typescript.packagePath));
assert.ok(!fs.existsSync(unrelatedOrphan.packagePath));
assert.doesNotThrow(() => fs.realpathSync(path.join(nodeModulesPath, "@prisma/client")));
assert.doesNotThrow(() => fs.realpathSync(path.join(nodeModulesPath, "sharp")));
assert.doesNotThrow(() => fs.realpathSync(path.join(sharp.entryPath, "node_modules/@img/sharp-linux-x64")));
assert.ok(!fs.existsSync(path.join(nodeModulesPath, ".bin/prisma")));
});
test("fails closed instead of deleting a store with no reachable runtime roots", async () => {
const fixture = createFixture();
const nodeModulesPath = path.join(fixture, "node_modules");
const orphan = addPackage(nodeModulesPath, "orphan@1.0.0", "orphan");
await assert.rejects(
() => prunePnpmRuntimeClosure({ excludedPackageNames: [], nodeModulesPath }),
/refusing to prune 1 pnpm entries without a reachable runtime root/
);
assert.ok(fs.existsSync(orphan.packagePath));
});
});
function createFixture() {
const fixture = fs.mkdtempSync(path.join(os.tmpdir(), "pnpm-runtime-prune-"));
fixtures.push(fixture);
fs.mkdirSync(path.join(fixture, "node_modules/.pnpm"), { recursive: true });
return fixture;
}
function addPackage(nodeModulesPath, entryName, packageName) {
const entryPath = path.join(nodeModulesPath, ".pnpm", entryName);
const packagePath = path.join(entryPath, "node_modules", ...packageName.split("/"));
fs.mkdirSync(packagePath, { recursive: true });
fs.writeFileSync(path.join(packagePath, "index.js"), `module.exports = ${JSON.stringify(packageName)};\n`);
return { entryPath, packagePath };
}
function linkPackage(nodeModulesPath, packageName, target) {
const linkPath = path.join(nodeModulesPath, ...packageName.split("/"));
fs.mkdirSync(path.dirname(linkPath), { recursive: true });
fs.symlinkSync(path.relative(path.dirname(linkPath), target), linkPath);
}