CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-pnpm--lockfile-pruner

Prune a pnpm-lock.yaml by removing unused package entries and optimizing lockfile structure.

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

index.mddocs/

PNPM Lockfile Pruner

PNPM Lockfile Pruner provides utilities for removing unused package entries and optimizing pnpm-lock.yaml files. It maintains lockfile integrity while removing dependencies that are no longer referenced, supporting both individual projects and workspace/monorepo environments.

Package Information

  • Package Name: @pnpm/lockfile.pruner
  • Package Type: npm
  • Language: TypeScript
  • Installation: pnpm add @pnpm/lockfile.pruner

Core Imports

import { pruneSharedLockfile, pruneLockfile } from "@pnpm/lockfile.pruner";

For CommonJS:

const { pruneSharedLockfile, pruneLockfile } = require("@pnpm/lockfile.pruner");

Import types (also re-exported from this package):

import { 
  LockfileObject, 
  PackageSnapshots, 
  ProjectSnapshot, 
  ResolvedDependencies 
} from "@pnpm/lockfile.pruner";

Basic Usage

import { pruneLockfile, pruneSharedLockfile } from "@pnpm/lockfile.pruner";
import { ProjectId } from "@pnpm/types";

// Prune a single project's lockfile
const prunedLockfile = pruneLockfile(
  originalLockfile,
  packageManifest,
  "." as ProjectId,
  {
    warn: (msg: string) => console.warn(msg)
  }
);

// Prune a shared lockfile (workspace/monorepo)
const prunedSharedLockfile = pruneSharedLockfile(originalLockfile, {
  warn: (msg: string) => console.warn(msg)
});

Capabilities

Single Project Lockfile Pruning

Prunes a lockfile based on specific package manifest requirements, handling development, production, and optional dependencies appropriately.

/**
 * Prune lockfile based on specific package manifest and project requirements
 * @param lockfile - The lockfile object to prune
 * @param pkg - Package manifest (package.json content) to base pruning on
 * @param importerId - Project identifier within the lockfile
 * @param opts - Pruning options including warning callback and dependencies graph
 * @returns Pruned lockfile object tailored to the specific package requirements
 */
function pruneLockfile(
  lockfile: LockfileObject,
  pkg: PackageManifest,
  importerId: ProjectId,
  opts: {
    warn?: (msg: string) => void;
    dependenciesGraph?: DependenciesGraph;
  }
): LockfileObject;

Usage Examples:

import { pruneLockfile } from "@pnpm/lockfile.pruner";
import { ProjectId } from "@pnpm/types";

// Basic pruning for a single project
const result = pruneLockfile(
  lockfile,
  {
    name: "my-app",
    version: "1.0.0",
    dependencies: {
      "lodash": "^4.17.21",
      "express": "^4.18.0"
    },
    devDependencies: {
      "typescript": "^4.8.0"
    }
  },
  "." as ProjectId,
  {
    warn: (msg) => console.warn(`Warning: ${msg}`)
  }
);

// Pruning with dependencies graph for advanced scenarios
const advancedResult = pruneLockfile(
  lockfile,
  packageManifest,
  "packages/frontend" as ProjectId,
  {
    warn: (msg) => logger.warn(msg),
    dependenciesGraph: {
      "package@1.0.0": { optional: false },
      "optional-package@2.0.0": { optional: true }
    }
  }
);

Shared Lockfile Pruning

Removes unused packages from shared/workspace lockfiles by analyzing all importers and keeping only referenced packages.

/**
 * Remove unused packages from shared/workspace lockfiles
 * @param lockfile - The lockfile object to prune
 * @param opts - Optional pruning options
 * @returns Pruned lockfile object with unused packages removed
 */
function pruneSharedLockfile(
  lockfile: LockfileObject,
  opts?: {
    dependenciesGraph?: DependenciesGraph;
    warn?: (msg: string) => void;
  }
): LockfileObject;

Usage Examples:

import { pruneSharedLockfile } from "@pnpm/lockfile.pruner";

// Basic shared lockfile pruning
const pruned = pruneSharedLockfile(workspaceLockfile);

// With warning callback
const prunedWithWarnings = pruneSharedLockfile(workspaceLockfile, {
  warn: (msg) => console.warn(`Lockfile pruning: ${msg}`)
});

// With dependencies graph for advanced dependency tracking
const advancedPruned = pruneSharedLockfile(workspaceLockfile, {
  dependenciesGraph: dependencyGraph,
  warn: (msg) => logger.warn(msg)
});

Types

Core Types

/**
 * Main lockfile structure containing all project dependencies and metadata
 */
interface LockfileObject {
  /** Version of the lockfile format */
  lockfileVersion: string | number;
  /** Individual project/package dependency snapshots */
  importers: Record<ProjectId, ProjectSnapshot>;
  /** Package resolution snapshots with dependency information */
  packages?: PackageSnapshots;
  /** Checksum for pnpmfile.js if present */
  pnpmfileChecksum?: string;
  /** List of ignored optional dependencies */
  ignoredOptionalDependencies?: string[];
}

/**
 * Individual project snapshot within a lockfile
 */
interface ProjectSnapshot {
  /** Version specifiers from package.json */
  specifiers: ResolvedDependencies;
  /** Production dependencies */
  dependencies?: ResolvedDependencies;
  /** Optional dependencies */
  optionalDependencies?: ResolvedDependencies;
  /** Development dependencies */
  devDependencies?: ResolvedDependencies;
}

/**
 * Mapping of package names to their resolved versions/references
 */
interface ResolvedDependencies {
  [depName: string]: string;
}

/**
 * Collection of package snapshots indexed by dependency path
 */
interface PackageSnapshots {
  [depPath: DepPath]: PackageSnapshot;
}

/**
 * Individual package snapshot with resolution and dependency information
 */
interface PackageSnapshot {
  /** Package resolution information */
  resolution: Resolution;
  /** Runtime dependencies */
  dependencies?: ResolvedDependencies;
  /** Optional dependencies */
  optionalDependencies?: ResolvedDependencies;
  /** Development dependencies */
  devDependencies?: ResolvedDependencies;
  /** Whether this package is optional */
  optional?: boolean;
}

/**
 * Package manifest structure (package.json content)
 */
interface PackageManifest {
  name?: string;
  version?: string;
  dependencies?: Record<string, string>;
  devDependencies?: Record<string, string>;
  optionalDependencies?: Record<string, string>;
  [key: string]: any;
}

/**
 * Dependencies graph for advanced pruning scenarios
 * Maps dependency paths to their optional status
 */
type DependenciesGraph = Record<DepPath, { optional?: boolean }>;

Utility Types

/**
 * Dependency path identifier (from @pnpm/types)
 */
type DepPath = string & { readonly brand: unique symbol };

/**
 * Project identifier within a workspace (from @pnpm/types)
 */
type ProjectId = string & { readonly brand: unique symbol };

/**
 * Package resolution information
 */
interface Resolution {
  /** Package integrity hash */
  integrity?: string;
  /** Package tarball URL */
  tarball?: string;
  /** Git repository information */
  repo?: string;
  /** Git commit hash */
  commit?: string;
  [key: string]: any;
}

Key Features

Dependency Management

  • Optional Dependencies: Properly handles optional dependencies with correct flagging
  • Linked Dependencies: Preserves local and linked packages (link: protocol)
  • Workspace Support: Full support for monorepo/workspace environments
  • Multi-Project: Handles multiple projects within a single lockfile

Pruning Logic

  • Unused Package Removal: Removes packages not referenced by any project
  • Dependency Chain Analysis: Recursively analyzes dependency trees
  • Optional Flag Management: Correctly manages optional flags based on usage context
  • Specifier Preservation: Maintains version specifiers from package.json

Error Handling

  • Warning Callbacks: Provides warning notifications for missing resolutions
  • Missing Package Handling: Gracefully handles missing package entries
  • Validation: Ensures lockfile integrity during pruning operations

Common Use Cases

CI/CD Pipeline Optimization

// Optimize lockfile before deployment
const optimizedLockfile = pruneSharedLockfile(lockfile, {
  warn: (msg) => console.log(`[CI] ${msg}`)
});

Development Environment Cleanup

// Remove unused dev dependencies from production lockfile
const productionLockfile = pruneLockfile(
  lockfile,
  { ...pkg, devDependencies: {} }, // Remove dev deps
  "." as ProjectId,
  { warn: console.warn }
);

Workspace Maintenance

// Clean up workspace lockfile
const cleanWorkspace = pruneSharedLockfile(workspaceLockfile, {
  warn: (msg) => logger.info(`Workspace cleanup: ${msg}`)
});

docs

index.md

tile.json