CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-tar-fs

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

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

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
Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/tar-fs@3.1.x
Publish Source
CLI
Badge
tessl/npm-tar-fs badge