or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

tessl/npm-tar-fs

Filesystem bindings for tar-stream providing directory packing/extraction capabilities

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/tar-fs@3.1.x

To install, run

npx @tessl/cli install tessl/npm-tar-fs@3.1.0

index.mddocs/

tar-fs

tar-fs provides filesystem bindings for tar-stream, enabling developers to pack directories into tarballs and extract tarballs into directories with a simple streaming API. It offers comprehensive tar file manipulation capabilities including selective file packing/extraction, header modification, stream transformation, and permission control.

Package Information

  • Package Name: tar-fs
  • Package Type: npm
  • Language: JavaScript
  • Installation: npm install tar-fs

Core Imports

const tar = require('tar-fs');

For ES modules:

import tar from 'tar-fs';

Basic Usage

const tar = require('tar-fs');
const fs = require('fs');

// Pack a directory into a tarball
tar.pack('./my-directory').pipe(fs.createWriteStream('my-tarball.tar'));

// Extract a tarball into a directory
fs.createReadStream('my-other-tarball.tar').pipe(tar.extract('./my-other-directory'));

// Copy a directory (with permissions and timestamps intact)
tar.pack('source-directory').pipe(tar.extract('dest-directory'));

Architecture

tar-fs is built around two core streaming functions that work with tar-stream instances:

  • Pack Function: Creates readable streams from filesystem directories, converting files and folders into tar entries
  • Extract Function: Creates writable streams that consume tar entries and recreate filesystem structures
  • Options System: Extensive configuration for filtering, transforming, and controlling permissions
  • Stream Integration: Direct compatibility with tar-stream instances for advanced use cases
  • Cross-platform Support: Works on Windows, macOS, Linux with platform-specific handling

Capabilities

Directory Packing

Packs a directory into a tar stream with extensive filtering and transformation options.

/**
 * Packs a directory into a tar stream
 * @param cwd - Directory to pack (defaults to '.')
 * @param opts - Packing options
 * @returns tar-stream pack instance (readable stream)
 */
function pack(cwd, opts);

Options:

interface PackOptions {
  /** Custom filesystem implementation */
  fs?: object;
  /** Function to ignore/filter files: (name) => boolean */
  ignore?: (name: string) => boolean;
  /** Alias for ignore */
  filter?: (name: string) => boolean;
  /** Function to transform file streams: (stream, header) => stream */
  mapStream?: (stream: ReadableStream, header: object) => ReadableStream;
  /** Dereference symlinks (pack contents instead of links) */
  dereference?: boolean;
  /** Array of specific entries to pack */
  entries?: string[];
  /** Sort entries alphabetically */
  sort?: boolean;
  /** Strict mode - fail on unsupported file types (default: true) */
  strict?: boolean;
  /** Permission umask */
  umask?: number;
  /** Existing pack stream to use */
  pack?: object;
  /** Callback function on completion */
  finish?: (pack: object) => void;
  /** Function to modify tar headers: (header) => header */
  map?: (header: object) => object;
  /** Directory mode permissions */
  dmode?: number;
  /** File mode permissions */
  fmode?: number;
  /** Number of path levels to strip */
  strip?: number;
  /** Make files readable (adds 444 to files, 555 to directories) */
  readable?: boolean;
  /** Make files writable (adds 222 to files, 333 to directories) */
  writable?: boolean;
  /** Finalize pack when done (default: true) */
  finalize?: boolean;
}

Usage Examples:

// Pack with file filtering
const pack = tar.pack('./my-directory', {
  ignore(name) {
    return path.extname(name) === '.bin'; // ignore .bin files
  }
});

// Pack specific entries only
const pack = tar.pack('./my-directory', {
  entries: ['file1.txt', 'subdir/file2.txt']
});

// Pack with header modification
const pack = tar.pack('./my-directory', {
  map(header) {
    header.name = 'prefixed/' + header.name;
    return header;
  }
});

// Pack with stream transformation
const pack = tar.pack('./my-directory', {
  mapStream(fileStream, header) {
    if (path.extname(header.name) === '.js') {
      return fileStream.pipe(someTransform);
    }
    return fileStream;
  }
});

// Pack with custom permissions
const pack = tar.pack('./my-directory', {
  dmode: parseInt('755', 8), // directory permissions
  fmode: parseInt('644', 8), // file permissions
  readable: true,
  writable: false
});

Tar Extraction

Extracts a tar stream into a directory with extensive filtering and transformation options.

/**
 * Extracts a tar stream into a directory
 * @param cwd - Directory to extract to (defaults to '.')
 * @param opts - Extraction options
 * @returns tar-stream extract instance (writable stream)
 */
function extract(cwd, opts);

Options:

interface ExtractOptions {
  /** Custom filesystem implementation */
  fs?: object;
  /** Function to ignore/filter files: (name, header) => boolean */
  ignore?: (name: string, header?: object) => boolean;
  /** Alias for ignore */
  filter?: (name: string, header?: object) => boolean;
  /** Function to transform file streams: (stream, header) => stream */
  mapStream?: (stream: ReadableStream, header: object) => ReadableStream;
  /** Change file ownership (default: true on Unix as root) */
  chown?: boolean;
  /** Existing extract stream to use */
  extract?: object;
  /** Function to modify tar headers: (header) => header */
  map?: (header: object) => object;
  /** Directory mode permissions */
  dmode?: number;
  /** File mode permissions */
  fmode?: number;
  /** Number of path levels to strip */
  strip?: number;
  /** Make files readable (adds 444 to files, 555 to directories) */
  readable?: boolean;
  /** Make files writable (adds 222 to files, 333 to directories) */
  writable?: boolean;
  /** Strict mode - fail on unsupported entry types (default: true) */
  strict?: boolean;
  /** Validate symlinks are within extraction directory (default: true) */
  validateSymlinks?: boolean;
  /** Set file modification times (default: true) */
  utimes?: boolean;
  /** Permission umask */
  umask?: number;
  /** Callback function on completion */
  finish?: () => void;
  /** Fallback hard links as file copies on permission errors */
  hardlinkAsFilesFallback?: boolean;
}

Usage Examples:

// Extract with file filtering
const extract = tar.extract('./my-directory', {
  ignore(name) {
    return path.extname(name) === '.bin'; // ignore .bin files
  }
});

// Extract with type filtering using header
const extract = tar.extract('./my-directory', {
  ignore(name, header) {
    // Only extract files and directories, ignore symlinks
    return header.type !== 'file' && header.type !== 'directory';
  }
});

// Extract with header modification
const extract = tar.extract('./my-directory', {
  map(header) {
    header.name = 'another-prefix/' + header.name;
    return header;
  }
});

// Extract with stream transformation
const extract = tar.extract('./my-directory', {
  mapStream(fileStream, header) {
    if (path.extname(header.name) === '.js') {
      return fileStream.pipe(someTransform);
    }
    return fileStream;
  }
});

// Extract with custom permissions
const extract = tar.extract('./my-directory', {
  dmode: parseInt('755', 8), // directory permissions
  fmode: parseInt('644', 8), // file permissions
  readable: true,
  writable: true
});

Advanced tar-stream Integration

For advanced use cases, tar-fs integrates seamlessly with tar-stream instances.

// Using custom pack stream
const mypack = tar.pack('./my-directory', {
  finalize: false,
  finish(pack) {
    // Add custom entry
    pack.entry({name: 'generated-file.txt'}, 'Hello World');
    // Pack another directory into same stream
    tar.pack('./other-directory', { pack: pack });
  }
});

// Using custom extract stream  
const tarStream = require('tar-stream');
const extract = tarStream.extract();
extract.on('entry', (header, stream, next) => {
  // Custom entry processing
  console.log('Extracting:', header.name);
  stream.resume();
  next();
});

tar.extract('./output', { extract: extract });

Types

interface TarHeader {
  /** File/directory name */
  name: string;
  /** File mode/permissions */
  mode: number;
  /** User ID */
  uid: number;
  /** Group ID */
  gid: number;
  /** File size in bytes */
  size: number;
  /** Modification time */
  mtime: Date;
  /** Entry type: 'file', 'directory', 'symlink', 'link' */
  type: string;
  /** Link target for symlinks and hard links */
  linkname?: string;
}

Platform Considerations

  • Windows: Symlinks and hard links are skipped due to platform limitations
  • Unix-like systems: Full symlink and hard link support with security validation
  • Bare.js: Alternative filesystem bindings through optional dependencies (bare-fs, bare-path)
  • Permissions: Automatic umask handling and cross-platform permission management

Error Handling

Common error scenarios:

  • ENOENT: File not found during packing (ignored for dynamically deleted files)
  • EPERM: Permission denied during extraction (handled with hardlinkAsFilesFallback)
  • Invalid symlinks: Prevented by validateSymlinks option (default: true)
  • Unsupported file types: Controlled by strict option (default: true)
  • Path traversal: Prevented by built-in path validation