WebAssembly-compiled version of the libzip C library providing ZIP archive manipulation capabilities for JavaScript and TypeScript applications
Pluggable ZIP implementations providing different performance and compatibility characteristics for various environments and use cases. These classes implement the ZipImpl interface and can be used as custom ZIP backends.
WebAssembly-based ZIP implementation using the compiled libzip C library for full-featured ZIP archive manipulation.
/**
* WebAssembly-based ZIP implementation using compiled libzip
* Provides full ZIP functionality with high performance
*/
class LibZipImpl implements ZipImpl {
constructor(opts: ZipImplInput);
readonly filesShouldBeCached: boolean; // true - files should be cached for performance
// Entry management
deleteEntry(index: number): void;
addDirectory(path: string): number;
// File content operations
getFileSource(index: number): {data: Buffer, compressionMethod: number};
setFileSource(target: PortablePath, compression: CompressionData, buffer: Buffer): number;
// Metadata operations
setMtime(index: number, mtime: number): void;
setExternalAttributes(index: number, opsys: number, attributes: number): void;
getExternalAttributes(index: number): [opsys: number, attributes: number];
// Archive information
getSymlinkCount(): number;
getListings(): Array<string>;
stat(entry: number): Stat;
locate(name: string): number;
// Archive finalization
getBufferAndClose(): Buffer;
discard(): void;
}Usage Examples:
import { LibZipImpl } from "@yarnpkg/libzip";
import { ppath } from "@yarnpkg/fslib";
// Create from file path
const zipImpl = new LibZipImpl({
path: "/path/to/archive.zip" as ppath.PortablePath,
baseFs: require("fs"),
readOnly: false,
size: 1024
});
// Add a directory
const dirIndex = zipImpl.addDirectory("docs/");
// Add a file with content
const fileData = Buffer.from("Hello, World!");
const fileIndex = zipImpl.setFileSource(
"docs/hello.txt" as ppath.PortablePath,
[8, 6], // Deflate compression, level 6
fileData
);
// Set file modification time
zipImpl.setMtime(fileIndex, Math.floor(Date.now() / 1000));
// Set Unix permissions (0644)
zipImpl.setExternalAttributes(fileIndex, 3, 0o644 << 16);
// Get file content back
const {data, compressionMethod} = zipImpl.getFileSource(fileIndex);
// Get archive as buffer
const archiveBuffer = zipImpl.getBufferAndClose();Pure JavaScript ZIP implementation for read-only operations, providing compatibility without WebAssembly dependencies.
/**
* Pure JavaScript ZIP implementation (read-only)
* Provides compatibility without WebAssembly dependencies
*/
class JsZipImpl implements ZipImpl {
constructor(opts: ZipImplInput);
readonly filesShouldBeCached: boolean; // false - operates directly on file descriptors
// Entry management (read-only operations only)
deleteEntry(index: number): void; // Throws error - not supported
addDirectory(path: string): number; // Throws error - not supported
// File content operations
getFileSource(index: number): {data: Buffer, compressionMethod: number};
setFileSource(target: PortablePath, compression: CompressionData, buffer: Buffer): number; // Throws error
// Metadata operations (read-only)
setMtime(index: number, mtime: number): void; // Throws error - not supported
setExternalAttributes(index: number, opsys: number, attributes: number): void; // Throws error
getExternalAttributes(index: number): [opsys: number, attributes: number];
// Archive information
getSymlinkCount(): number;
getListings(): Array<string>;
stat(entry: number): Stat;
locate(name: string): number;
// Archive operations (read-only)
getBufferAndClose(): Buffer; // Throws error - not supported
discard(): void;
}Usage Examples:
import { JsZipImpl } from "@yarnpkg/libzip";
import { ppath } from "@yarnpkg/fslib";
// Create read-only implementation from file
const zipImpl = new JsZipImpl({
path: "/path/to/existing.zip" as ppath.PortablePath,
baseFs: require("fs"),
readOnly: true, // Must be true
size: 2048
});
// Read archive contents
const listings = zipImpl.getListings();
console.log("Archive contains:", listings);
// Get file index by name
const fileIndex = zipImpl.locate("readme.txt");
if (fileIndex >= 0) {
// Get file statistics
const stats = zipImpl.stat(fileIndex);
console.log(`File size: ${stats.size}, CRC: ${stats.crc}`);
// Get file content
const {data, compressionMethod} = zipImpl.getFileSource(fileIndex);
console.log("Content:", data.toString());
// Get file attributes
const [opsys, attributes] = zipImpl.getExternalAttributes(fileIndex);
console.log(`OS: ${opsys}, Attributes: ${attributes}`);
}
// Get symlink count
const symlinkCount = zipImpl.getSymlinkCount();
console.log(`Archive contains ${symlinkCount} symlinks`);
// Clean up
zipImpl.discard();Custom error class for libzip-specific errors with error codes.
/**
* Custom error class for libzip operations
* Provides structured error information with error codes
*/
class LibzipError extends Error {
readonly code: string;
constructor(message: string, code: string);
}Usage Example:
import { LibZipImpl, LibzipError } from "@yarnpkg/libzip";
try {
const zipImpl = new LibZipImpl({
path: "/nonexistent/archive.zip" as ppath.PortablePath,
baseFs: require("fs"),
readOnly: false,
size: 0
});
} catch (error) {
if (error instanceof LibzipError) {
console.error(`Libzip error [${error.code}]: ${error.message}`);
} else {
console.error("Other error:", error);
}
}Interface for ZIP entry statistics and metadata.
interface Stat {
/** File modification time as Unix timestamp */
mtime: number;
/** CRC32 checksum of file data */
crc: number;
/** Uncompressed file size in bytes */
size: number;
}
interface Entry {
/** Entry name/path within the archive */
name: string;
/** Compression method used (0 = store, 8 = deflate, etc.) */
compressionMethod: number;
/** Uncompressed size in bytes */
size: number;
/** Operating system that created the entry */
os: number;
/** Whether the entry is a symbolic link */
isSymbolicLink: boolean;
/** CRC32 checksum of the file data */
crc: number;
/** Compressed size in bytes */
compressedSize: number;
/** External file attributes (permissions, etc.) */
externalAttributes: number;
/** File modification time as Unix timestamp */
mtime: number;
/** Offset to local header in ZIP file */
localHeaderOffset: number;
}interface ZipImpl {
/** Whether files should be cached in memory for performance */
readonly filesShouldBeCached: boolean;
// Entry management
deleteEntry(index: number): void;
addDirectory(path: string): number;
// File operations
getFileSource(index: number): {data: Buffer, compressionMethod: number};
setFileSource(target: PortablePath, compression: CompressionData, buffer: Buffer): number;
// Metadata operations
setMtime(index: number, mtime: number): void;
setExternalAttributes(index: number, opsys: number, attributes: number): void;
getExternalAttributes(index: number): [opsys: number, attributes: number];
// Archive information
getSymlinkCount(): number;
getListings(): Array<string>;
stat(entry: number): Stat;
locate(name: string): number;
// Archive operations
getBufferAndClose(): Buffer;
discard(): void;
}
type ZipImplInput =
| {path: PortablePath, baseFs: FakeFS<PortablePath>, readOnly: boolean, size: number}
| {buffer: Buffer, readOnly: boolean};
interface ZipImplementationClass {
new(input: ZipImplInput): ZipImpl;
}Install with Tessl CLI
npx tessl i tessl/npm-yarnpkg--libzip