CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-vinyl-fs

Vinyl adapter for the file system providing streaming file operations.

Pending
Overview
Eval results
Files

symlink.mddocs/

Symbolic Links (symlink)

Stream-based symbolic link creation functionality that accepts Vinyl File objects and creates symbolic links pointing to their original locations. Supports both file and directory symlinks with platform-specific optimizations.

Capabilities

symlink Function

Creates a writable stream that creates symbolic links from Vinyl File objects with comprehensive options for link creation behavior.

/**
 * Creates a writable stream that creates symbolic links from Vinyl File objects
 * @param {string|function} outFolder - Destination folder path or function returning path
 * @param {Object} [options] - Configuration options
 * @returns {Transform} Transform stream that consumes Vinyl File objects
 * @throws {Error} When outFolder argument is invalid
 */
function symlink(outFolder, options);

interface SymlinkOptions {
  /** Working directory for relative paths (default: process.cwd()) */
  cwd?: string;
  /** Directory permissions mode */
  dirMode?: number | ((file: File) => number);
  /** Overwrite existing symlinks (default: true) */
  overwrite?: boolean;
  /** Create relative symlinks (default: false) */
  relativeSymlinks?: boolean;
  /** Use junctions on Windows (default: true) */
  useJunctions?: boolean;
}

Symbolic Link Behavior

The symlink function modifies Vinyl File objects after processing:

  • Path properties: cwd, base, and path are updated to match the destination
  • Stat information: Updated to reflect the symlink on filesystem
  • Contents: Set to null (symlinks don't have contents)
  • Symlink property: Added or replaced with the original file path

Folder Path Resolution

The outFolder parameter can be a string or function:

// Static folder path
vfs.symlink('./links');

// Dynamic folder based on file properties
vfs.symlink((file) => {
  return file.extname === '.exe' ? './bin' : './lib';
});

Platform-Specific Behavior

Windows:

  • Directory symlinks are created as junctions by default (requires no special permissions)
  • Standard symlinks may require elevated permissions
  • useJunctions option controls this behavior

Unix-like systems:

  • Standard symbolic links for all file types
  • No special permissions required
  • useJunctions option is ignored

Option Details

dirMode

Controls directory permissions when creating parent directories.

// Set directory permissions
vfs.symlink('./links', { dirMode: 0o755 });

// Dynamic permissions based on file
vfs.symlink('./links', {
  dirMode: (file) => file.isDirectory() ? 0o755 : 0o644
});

overwrite

Controls behavior when symlinks already exist at the destination.

// Overwrite existing symlinks (default)
vfs.symlink('./links', { overwrite: true });

// Skip existing symlinks
vfs.symlink('./links', { overwrite: false });

relativeSymlinks

Controls whether symlinks are created as relative or absolute paths.

// Create absolute symlinks (default)
vfs.symlink('./links', { relativeSymlinks: false });

// Create relative symlinks
vfs.symlink('./links', { relativeSymlinks: true });

Note: Relative symlinks are automatically converted to absolute when creating junctions on Windows.

useJunctions

Windows-specific option controlling directory symlink creation.

// Use junctions for directory symlinks on Windows (default)
vfs.symlink('./links', { useJunctions: true });

// Use standard symlinks (may require elevated permissions on Windows)
vfs.symlink('./links', { useJunctions: false });

Error Handling

The symlink function throws errors for invalid inputs:

// Throws: "Invalid symlink() folder argument..."
try {
  vfs.symlink('');
} catch (error) {
  console.error(error.message);
}

Usage Examples

Basic symbolic link creation:

const vfs = require('vinyl-fs');

// Create symlinks for all JavaScript files
vfs.src('src/**/*.js')
  .pipe(vfs.symlink('./links'));

Advanced configuration:

vfs.src('src/**/*')
  .pipe(vfs.symlink('./links', {
    relativeSymlinks: true,  // Create relative symlinks
    dirMode: 0o755,         // Set directory permissions
    overwrite: true         // Replace existing symlinks
  }));

Platform-aware symlink creation:

const os = require('os');

vfs.src('bin/**/*')
  .pipe(vfs.symlink('./links', {
    // Use junctions on Windows, regular symlinks elsewhere
    useJunctions: os.platform() === 'win32',
    relativeSymlinks: os.platform() !== 'win32'
  }));

Dynamic symlink organization:

vfs.src(['src/**/*.js', 'src/**/*.css', 'src/**/*.html'])
  .pipe(vfs.symlink((file) => {
    // Organize symlinks by file type
    const ext = file.extname.slice(1); // Remove leading dot
    return `./links/${ext}`;
  }));

Conditional symlink creation:

const path = require('path');

vfs.src('src/**/*')
  .pipe(vfs.symlink('./links', {
    // Only overwrite if original file is newer
    overwrite: (file) => {
      const linkPath = path.join('./links', file.relative);
      if (!fs.existsSync(linkPath)) return true;
      
      const linkStat = fs.lstatSync(linkPath);
      return file.stat.mtime > linkStat.mtime;
    }
  }));

Creating backup symlinks:

const through = require('through2');

vfs.src('important/**/*')
  .pipe(through.obj((file, enc, cb) => {
    // Add timestamp to symlink name for versioning
    const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
    file.basename = `${file.stem}-${timestamp}${file.extname}`;
    cb(null, file);
  }))
  .pipe(vfs.symlink('./backups', {
    relativeSymlinks: true,
    overwrite: false  // Keep all versions
  }));

Working with Existing Symlinks

When processing existing symlinks with resolveSymlinks: false:

// Preserve existing symlinks and create symlinks to symlinks
vfs.src('**/*', { resolveSymlinks: false })
  .pipe(vfs.symlink('./mirror-links', {
    relativeSymlinks: true
  }));

Install with Tessl CLI

npx tessl i tessl/npm-vinyl-fs

docs

dest.md

index.md

src.md

symlink.md

tile.json