CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-patch-package

Fix broken node modules with no fuss - create and apply patches to npm dependencies instantly

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

patch-application.mddocs/

Patch Application

Robust patch application system that applies patches during package installation with support for error handling, partial application, reverse operations, and state management. This is the core functionality that makes patch-package integrate seamlessly into development workflows.

Capabilities

Main Application Functions

Core functions for applying patches to packages.

/**
 * Main function to apply all patches for an application
 * @param options - Application configuration options
 */
function applyPatchesForApp(options: ApplyPatchesForAppOptions): void;

interface ApplyPatchesForAppOptions {
  /** Root path of the application */
  appPath: string;
  /** Whether to reverse/un-apply patches */
  reverse: boolean;
  /** Directory containing patch files */
  patchDir: string;
  /** Exit process on error */
  shouldExitWithError: boolean;
  /** Exit process on warning */
  shouldExitWithWarning: boolean;
  /** Continue on partial failures */
  bestEffort: boolean;
}

/**
 * Apply patches for a specific package
 * @param options - Package-specific application options
 */
function applyPatchesForPackage(options: ApplyPatchesForPackageOptions): void;

interface ApplyPatchesForPackageOptions {
  /** Array of patch details to apply */
  patches: PatchedPackageDetails[];
  /** Application root path */
  appPath: string;
  /** Patch directory */
  patchDir: string;
  /** Reverse application */
  reverse: boolean;
  /** Warning messages array */
  warnings: string[];
  /** Error messages array */
  errors: string[];
  /** Best effort mode */
  bestEffort: boolean;
}

/**
 * Apply a single patch file
 * @param options - Single patch application options
 * @returns Success status
 */
function applyPatch(options: ApplyPatchOptions): boolean;

interface ApplyPatchOptions {
  /** Path to patch file */
  patchFilePath: string;
  /** Apply in reverse */
  reverse: boolean;
  /** Package details */
  patchDetails: PackageDetails;
  /** Patch directory */
  patchDir: string;
  /** Current working directory */
  cwd: string;
  /** Best effort mode */
  bestEffort: boolean;
}

Usage Examples:

import { applyPatchesForApp } from "patch-package/dist/applyPatches";

// Apply all patches for application
applyPatchesForApp({
  appPath: process.cwd(),
  reverse: false,
  patchDir: "patches",
  shouldExitWithError: true,
  shouldExitWithWarning: false,
  bestEffort: false
});

// Apply patches in reverse (un-apply)
applyPatchesForApp({
  appPath: process.cwd(),
  reverse: true,
  patchDir: "patches",
  shouldExitWithError: false,
  shouldExitWithWarning: false,
  bestEffort: true
});

Error Handling

Specialized error types and handling for patch application failures.

/**
 * Custom error for patch application failures
 */
class PatchApplicationError extends Error {
  constructor(msg: string);
}

Patch Processing

Patch File Operations

Core patch processing operations for reading, parsing, and applying patches.

/**
 * Read and parse patch file
 * @param options - Read patch options
 * @returns Parsed patch file parts
 */
function readPatch(options: ReadPatchOptions): PatchFilePart[];

interface ReadPatchOptions {
  /** Path to patch file */
  patchFilePath: string;
  /** Package details */
  patchDetails: PackageDetails;
  /** Patch directory */
  patchDir: string;
}

/**
 * Execute patch effects (file operations)
 * @param effects - Parsed patch operations
 * @param options - Execution options
 */
function executeEffects(effects: ParsedPatchFile, options: ExecuteEffectsOptions): void;

interface ExecuteEffectsOptions {
  /** Dry run mode - don't actually apply changes */
  dryRun: boolean;
  /** Current working directory */
  cwd?: string;
  /** Error messages array */
  errors?: string[];
  /** Best effort mode */
  bestEffort: boolean;
}

/**
 * Reverse a patch for un-applying
 * @param patch - Parsed patch file
 * @returns Reversed patch
 */
function reversePatch(patch: ParsedPatchFile): ParsedPatchFile;

Parse Operations

Detailed patch parsing functionality for understanding patch structure.

/**
 * Parse complete patch file content
 * @param file - Patch file content as string
 * @returns Parsed patch file structure
 */
function parsePatchFile(file: string): ParsedPatchFile;

/**
 * Parse hunk header from diff line
 * @param headerLine - Hunk header line from patch
 * @returns Parsed hunk header
 */
function parseHunkHeaderLine(headerLine: string): HunkHeader;

/**
 * Verify hunk integrity
 * @param hunk - Hunk to verify
 * @throws Error if hunk is invalid
 */
function verifyHunkIntegrity(hunk: Hunk): void;

/**
 * Interpret parsed patch file data
 * @param files - File details array
 * @returns Interpreted patch file
 */
function interpretParsedPatchFile(files: FileDeets[]): ParsedPatchFile;

Patch File Structure

Core Interfaces

Data structures representing parsed patch files and their components.

interface HunkHeader {
  original: { start: number; length: number };
  patched: { start: number; length: number };
}

interface FilePatch {
  type: "patch";
  path: string;
  hunks: Hunk[];
  beforeHash: string | null;
  afterHash: string | null;
}

interface Hunk {
  header: HunkHeader;
  parts: PatchMutationPart[];
  source: string;
}

type ParsedPatchFile = PatchFilePart[];
type PatchFilePart = FilePatch | FileRename | FileCreation | FileDeletion | FileModeChange;
type PatchMutationPart = AdditionPart | DeletionPart | ContextPart;

File Mode Constants

Standard file mode constants used in patch operations.

/** Default file mode for non-executable files */
const NON_EXECUTABLE_FILE_MODE: 0o644;

/** File mode for executable files */  
const EXECUTABLE_FILE_MODE: 0o755;

State Management

Patch State Tracking

Comprehensive state management for tracking applied patches and handling sequences.

/**
 * Get current patch application state
 * @param packageDetails - Package details
 * @returns Current state or null if none exists
 */
function getPatchApplicationState(packageDetails: PackageDetails): PatchApplicationState | null;

/**
 * Save patch application state
 * @param options - State save options
 */
function savePatchApplicationState(options: SaveStateOptions): void;

interface SaveStateOptions {
  packageDetails: PackageDetails;
  patches: PatchState[];
  isRebasing: boolean;
}

/**
 * Clear patch application state
 * @param packageDetails - Package details
 */
function clearPatchApplicationState(packageDetails: PackageDetails): void;

/**
 * Verify applied patches are still valid
 * @param options - Verification options
 */
function verifyAppliedPatches(options: VerifyPatchesOptions): void;

interface VerifyPatchesOptions {
  appPath: string;
  patchDir: string;
  state: PatchApplicationState;
}

State Data Structures

Data structures for managing patch application state.

interface PatchState {
  /** Patch file name */
  patchFilename: string;
  /** Content hash for validation */
  patchContentHash: string;
  /** Whether patch was successfully applied */
  didApply: boolean;
}

interface PatchApplicationState {
  /** State version for compatibility */
  version: number;
  /** Array of patch states */
  patches: PatchState[];
  /** Whether currently rebasing */
  isRebasing: boolean;
}

/** State file name */
const STATE_FILE_NAME: ".patch-package.json";

File System Integration

Patch File Discovery

Functions for discovering and organizing patch files.

/**
 * Get all patch files in directory
 * @param patchesDir - Directory containing patches
 * @returns Array of patch file paths
 */
function getPatchFiles(patchesDir: string): string[];

/**
 * Get patches grouped by package
 * @param patchesDirectory - Patches directory
 * @returns Grouped patches with metadata
 */
function getGroupedPatches(patchesDirectory: string): GroupedPatches;

interface GroupedPatches {
  /** Total number of patch files */
  numPatchFiles: number;
  /** Patches organized by package path specifier */
  pathSpecifierToPatchFiles: Record<string, PatchedPackageDetails[]>;
  /** Warning messages */
  warnings: string[];
}

Advanced Application Features

Rebase Operations

Advanced functionality for rebasing patch sequences.

/**
 * Rebase patches to specific target
 * @param options - Rebase configuration options
 */
function rebase(options: RebaseOptions): void;

interface RebaseOptions {
  /** Application path */
  appPath: string;
  /** Patch directory */
  patchDir: string;
  /** Package specifier */
  packagePathSpecifier: string;
  /** Target patch identifier */
  targetPatch: string;
}

Safe Process Execution

Secure process spawning for patch application operations.

/**
 * Safely execute shell commands
 * @param command - Command to execute
 * @param args - Command arguments
 * @param options - Spawn options
 * @returns Spawn result
 */
function spawnSafeSync(
  command: string, 
  args?: string[], 
  options?: SpawnSafeOptions
): SpawnResult;

interface SpawnSafeOptions extends SpawnOptions {
  // Additional safety options
}

interface SpawnResult {
  status: number | null;
  signal: string | null;
  stdout: Buffer;
  stderr: Buffer;
}

Application Workflow

The patch application workflow typically involves:

  1. Discovery: Find all relevant patch files in the patch directory
  2. Grouping: Organize patches by package and sequence
  3. State Validation: Check current application state against patches
  4. Dependency Resolution: Verify target packages exist and match versions
  5. Sequential Application: Apply patches in correct order
  6. State Tracking: Update application state for each successful patch
  7. Error Handling: Handle failures according to configuration

Complete Example:

import { applyPatchesForApp } from "patch-package/dist/applyPatches";
import { getPatchApplicationState } from "patch-package/dist/stateFile";
import { getGroupedPatches } from "patch-package/dist/patchFs";

// Check current state
const currentState = getPatchApplicationState({
  path: "/path/to/package",
  name: "my-package",
  // ... other package details
});

// Discover available patches
const groupedPatches = getGroupedPatches("patches");
console.log(`Found ${groupedPatches.numPatchFiles} patch files`);

// Apply patches with comprehensive error handling
applyPatchesForApp({
  appPath: process.cwd(),
  reverse: false,
  patchDir: "patches",
  shouldExitWithError: false,
  shouldExitWithWarning: false,
  bestEffort: true // Continue on individual failures
});

Install with Tessl CLI

npx tessl i tessl/npm-patch-package

docs

cli-interface.md

index.md

package-management.md

patch-application.md

patch-creation.md

rebase-operations.md

utility-apis.md

tile.json