Luigit
repositories / pi-ext

pi-ext

bugabingas pi extensions

owned by admin

scripts/build/release.test.ts

Raw
import {
	mkdirSync,
	mkdtempSync,
	readFileSync,
	rmSync,
	symlinkSync,
	writeFileSync,
} from "node:fs";
import { join } from "node:path";
import { afterEach, describe, expect, it } from "vitest";
import { ROOT } from "./build.ts";
import { archivePackage, collectionManifest, treeDigest } from "./release.ts";

const roots: string[] = [];
afterEach(() => {
	for (const root of roots.splice(0))
		rmSync(root, { recursive: true, force: true });
});

describe("repository release", () => {
	it("exposes every extension and resource from the root installation unit", () => {
		expect(
			collectionManifest("0.1.0", [
				{ name: "a", pi: { extensions: ["index.js"], skills: ["skills"] } },
				{ name: "b", pi: { extensions: ["entry.js"], prompts: ["prompts"] } },
			]),
		).toEqual({
			name: "pi-ext",
			version: "0.1.0",
			private: true,
			type: "module",
			pi: {
				extensions: ["packages/a/index.js", "packages/b/entry.js"],
				skills: ["packages/a/skills"],
				prompts: ["packages/b/prompts"],
			},
		});
	});

	it("archives exact package bytes and records their SHA-256", () => {
		const scratch = join(ROOT, ".pi", "tmp");
		mkdirSync(scratch, { recursive: true });
		const root = mkdtempSync(join(scratch, "release-test-"));
		roots.push(root);
		const pkg = join(root, "package");
		mkdirSync(pkg);
		writeFileSync(join(pkg, "index.js"), "export default () => {};\n");
		symlinkSync("index.js", join(pkg, "entry.js"));
		const digest = treeDigest(pkg);
		const archive = join(root, "package.tgz");
		expect(archivePackage(pkg, archive, root)).toMatch(/^[a-f0-9]{64}$/u);
		expect(readFileSync(archive).length).toBeGreaterThan(0);
		expect(treeDigest(pkg)).toBe(digest);
		writeFileSync(join(pkg, "index.js"), "changed\n");
		expect(treeDigest(pkg)).not.toBe(digest);
		writeFileSync(join(root, "outside.js"), "outside\n");
		symlinkSync("../outside.js", join(pkg, "escape.js"));
		expect(() => treeDigest(pkg)).toThrow(/Symlink escapes package/u);
	});
});