CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-yarnpkg--libzip

WebAssembly-compiled version of the libzip C library providing ZIP archive manipulation capabilities for JavaScript and TypeScript applications

Overview
Eval results
Files

implementations.mddocs/

Implementation Classes

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.

Capabilities

LibZipImpl Class

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();

JsZipImpl Class

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();

LibzipError Class

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);
  }
}

ZIP Entry Metadata

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;
}

Core Interface Types

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

docs

filesystem.md

implementations.md

index.md

libzip-interface.md

utilities.md

tile.json