// @vitest-environment node import { describe, expect, it } from "vitest"; import { createZipArchive, readZipArchive } from "./zip"; function readUint16(bytes: Uint8Array, offset: number) { return bytes[offset]! | (bytes[offset + 1]! << 8); } function readUint32(bytes: Uint8Array, offset: number) { return ( bytes[offset]! | (bytes[offset + 1]! << 8) | (bytes[offset + 2]! << 16) | (bytes[offset + 3]! << 24) ) >>> 0; } function readString(bytes: Uint8Array, offset: number, length: number) { return new TextDecoder().decode(bytes.slice(offset, offset + length)); } describe("createZipArchive", () => { it("writes a zip archive with the export root path prefixed into each entry", () => { const archive = createZipArchive( { "COMPANY.md": "# Company\n", "agents/ceo/AGENTS.md": "# CEO\n", }, "paperclip-demo", ); expect(readUint32(archive, 0)).toBe(0x04034b50); const firstNameLength = readUint16(archive, 26); const firstBodyLength = readUint32(archive, 18); expect(readString(archive, 30, firstNameLength)).toBe("paperclip-demo/agents/ceo/AGENTS.md"); expect(readString(archive, 30 + firstNameLength, firstBodyLength)).toBe("# CEO\n"); const secondOffset = 30 + firstNameLength + firstBodyLength; expect(readUint32(archive, secondOffset)).toBe(0x04034b50); const secondNameLength = readUint16(archive, secondOffset + 26); const secondBodyLength = readUint32(archive, secondOffset + 18); expect(readString(archive, secondOffset + 30, secondNameLength)).toBe("paperclip-demo/COMPANY.md"); expect(readString(archive, secondOffset + 30 + secondNameLength, secondBodyLength)).toBe("# Company\n"); const endOffset = archive.length - 22; expect(readUint32(archive, endOffset)).toBe(0x06054b50); expect(readUint16(archive, endOffset + 8)).toBe(2); expect(readUint16(archive, endOffset + 10)).toBe(2); }); it("reads a Paperclip zip archive back into rootPath and file contents", () => { const archive = createZipArchive( { "COMPANY.md": "# Company\n", "agents/ceo/AGENTS.md": "# CEO\n", ".paperclip.yaml": "schema: paperclip/v1\n", }, "paperclip-demo", ); expect(readZipArchive(archive)).toEqual({ rootPath: "paperclip-demo", files: { "COMPANY.md": "# Company\n", "agents/ceo/AGENTS.md": "# CEO\n", ".paperclip.yaml": "schema: paperclip/v1\n", }, }); }); });