Modern Tar Archiver

0.7.6 · active · verified Sun Apr 19

modern-tar is a zero-dependency, cross-platform JavaScript library designed for efficient streaming of tar archives. It supports both parsing and writing tar files, leveraging the browser-native Web Streams API for optimal performance and memory efficiency across diverse JavaScript runtimes, including Node.js (requiring version 18.0.0 or higher), web browsers, and Cloudflare Workers. The library is currently at stable version 0.7.6, with a consistent release cadence that introduces bug fixes, performance optimizations, and crucial security patches. Its key differentiators include a robust streaming architecture capable of handling large archives without full memory loading, full compliance with USTAR format and PAX extensions, built-in helpers for gzip compression, a TypeScript-first design ensuring strong type safety, and a minimal footprint due to its zero external dependencies.

Common errors

Warnings

Install

Imports

Quickstart

Demonstrates streaming tar creation with `createTarPacker` and subsequent decoding with `createTarDecoder`, highlighting dynamic entry addition and the necessity of draining entry bodies.

import { createTarPacker, createTarDecoder } from 'modern-tar';

async function processTarStream() {
  // Create a tar packer
  const { readable, controller } = createTarPacker();

  // Add entries dynamically
  const fileStream = controller.add({
    name: "dynamic.txt",
    size: 5,
    type: "file"
  });

  // Write content to the stream
  const writer = fileStream.getWriter();
  await writer.write(new TextEncoder().encode("hello"));
  await writer.close();

  // Add another entry, maybe a directory
  controller.add({ name: "my-dir/", type: "directory", size: 0 });

  // When done adding entries, finalize the archive
  controller.finalize();

  // Pipe the archive right into a decoder
  const decodedStream = readable.pipeThrough(createTarDecoder());
  for await (const entry of decodedStream) {
    console.log(`Decoded: ${entry.header.name}`);

    const shouldSkip = entry.header.name.endsWith(".md");
    if (shouldSkip) {
      // You MUST drain the body with cancel() to proceed to the next entry or read it fully,
      // otherwise the stream will stall.
      await entry.body.cancel();
      continue;
    }

    // Example: Read the content for non-skipped files
    if (entry.header.type === 'file') {
      const reader = entry.body.getReader();
      let chunk = '';
      while (true) {
        const { done, value } = await reader.read();
        if (done) break;
        chunk += new TextDecoder().decode(value);
      }
      console.log(`Content of ${entry.header.name}: ${chunk}`);
    }
  }
  console.log('Tar stream processing complete.');
}

processTarStream().catch(console.error);

view raw JSON →