or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

comparison-functions.mdextension-points.mdfile-comparators.mdfilters-and-patterns.mdindex.md
tile.json

index.mddocs/

dir-compare

dir-compare provides comprehensive Node.js directory and file comparison functionality with extensive customization options. It offers both synchronous and asynchronous comparison methods with detailed statistics, difference reporting, and extensible architecture through custom comparators and filters.

Package Information

  • Package Name: dir-compare
  • Package Type: npm
  • Language: TypeScript
  • Installation: npm install dir-compare

Core Imports

import { compareSync, compare, Options, Result } from "dir-compare";

For CommonJS:

const { compareSync, compare } = require("dir-compare");

Additional handler imports:

import { 
  fileCompareHandlers, 
  compareNameHandlers, 
  filterHandlers 
} from "dir-compare";

Basic Usage

import { compareSync, compare, Options, Result } from "dir-compare";

// Synchronous comparison
const options: Options = { 
  compareSize: true,
  compareContent: true,
  excludeFilter: ".git,node_modules"
};

const result: Result = compareSync("/path/to/dir1", "/path/to/dir2", options);

console.log(`Directories are ${result.same ? 'identical' : 'different'}`);
console.log(`Statistics: ${result.equal} equal, ${result.distinct} distinct, ${result.differences} total differences`);

// Asynchronous comparison
compare("/path/to/dir1", "/path/to/dir2", options)
  .then(result => {
    console.log("Comparison completed:", result.same);
    result.diffSet?.forEach(diff => 
      console.log(`${diff.relativePath}: ${diff.state}`)
    );
  })
  .catch(error => console.error("Comparison failed:", error));

Architecture

dir-compare is built around several key architectural components:

  • Core Comparison Engine: Handles directory traversal, entry comparison, and result aggregation
  • Extension Points: Pluggable comparators and filters for customizing behavior
  • Statistics System: Comprehensive metrics about comparison results
  • Type Safety: Full TypeScript integration with detailed type definitions
  • Error Handling: Robust handling of permission errors, broken links, and edge cases

Capabilities

Core Comparison Functions

Primary functions for comparing directories and files with comprehensive options and detailed results.

function compareSync(path1: string, path2: string, options?: Options): Result;
function compare(path1: string, path2: string, options?: Options): Promise<Result>;

Comparison Functions

File Content Comparators

Built-in and extensible file content comparison handlers supporting binary and line-based comparison strategies.

interface FileCompareHandlers {
  defaultFileCompare: CompareFileHandler;
  lineBasedFileCompare: CompareFileHandler;
}

interface CompareFileHandler {
  compareSync: CompareFileSync;
  compareAsync: CompareFileAsync;
}

File Comparators

Filter System

Flexible filtering system using glob patterns and custom filter handlers to control which files and directories are included in comparisons.

interface FilterHandlers {
  defaultFilterHandler: FilterHandler;
}

type FilterHandler = (entry: Entry, relativePath: string, options: Options) => boolean;

Filters and Patterns

Extension Points

Comprehensive extension system allowing custom result builders, name comparators, and filter handlers for specialized comparison needs.

type ResultBuilder = (
  entry1: Entry | undefined, 
  entry2: Entry | undefined, 
  state: DifferenceState, 
  level: number,
  relativePath: string, 
  options: Options, 
  statistics: InitialStatistics, 
  diffSet: DiffSet | undefined,
  reason: Reason | undefined, 
  permissionDeniedState: PermissionDeniedState
) => void;

type CompareNameHandler = (name1: string, name2: string, options: Options) => 0 | 1 | -1;

Extension Points

Types

Core Result Types

interface Result extends Statistics {
  diffSet?: DiffSet;
}

interface Statistics extends InitialStatistics {
  same: boolean;
  differences: number;
  total: number;
  differencesFiles: number;
  totalFiles: number;
  differencesDirs: number;
  totalDirs: number;
}

interface InitialStatistics {
  distinct: number;
  equal: number;
  left: number;
  right: number;
  distinctFiles: number;
  equalFiles: number;
  leftFiles: number;
  rightFiles: number;
  distinctDirs: number;
  equalDirs: number;
  leftDirs: number;
  rightDirs: number;
  brokenLinks: BrokenLinksStatistics;
  permissionDenied: PermissionDeniedStatistics;
  symlinks?: SymlinkStatistics;
}

Entry and Difference Types

interface Entry {
  name: string;
  absolutePath: string;
  path: string;
  origin: EntryOrigin;
  stat: fs.Stats;
  lstat: fs.Stats;
  isDirectory: boolean;
  isSymlink: boolean;
  isBrokenLink: boolean;
  isPermissionDenied: boolean;
}

interface Difference {
  path1?: string;
  path2?: string;
  relativePath: string;
  name1?: string;
  name2?: string;
  state: DifferenceState;
  permissionDeniedState: PermissionDeniedState;
  type1: DifferenceType;
  type2: DifferenceType;
  size1?: number;
  size2?: number;
  date1?: Date;
  date2?: Date;
  level: number;
  reason: Reason;
}

Type Aliases

type DiffSet = Array<Difference>;
type EntryOrigin = 'left' | 'right';
type DifferenceState = "equal" | "left" | "right" | "distinct";
type PermissionDeniedState = "access-ok" | "access-error-both" | "access-error-left" | "access-error-right";
type DifferenceType = "missing" | "file" | "directory" | "broken-link";
type Reason = undefined | "different-size" | "different-date" | "different-content" | "broken-link" | "different-symlink" | "permission-denied";

Statistics Sub-types

interface BrokenLinksStatistics {
  leftBrokenLinks: number;
  rightBrokenLinks: number;
  distinctBrokenLinks: number;
  totalBrokenLinks: number;
}

interface PermissionDeniedStatistics {
  leftPermissionDenied: number;
  rightPermissionDenied: number;
  distinctPermissionDenied: number;
  totalPermissionDenied: number;
}

interface SymlinkStatistics {
  distinctSymlinks: number;
  equalSymlinks: number;
  leftSymlinks: number;
  rightSymlinks: number;
  differencesSymlinks: number;
  totalSymlinks: number;
}