Prune a pnpm-lock.yaml by removing unused package entries and optimizing lockfile structure.
npx @tessl/cli install tessl/npm-pnpm--lockfile-pruner@1001.0.0PNPM 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.
pnpm add @pnpm/lockfile.prunerimport { 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";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)
});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 }
}
}
);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)
});/**
* 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 }>;/**
* 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;
}// Optimize lockfile before deployment
const optimizedLockfile = pruneSharedLockfile(lockfile, {
warn: (msg) => console.log(`[CI] ${msg}`)
});// Remove unused dev dependencies from production lockfile
const productionLockfile = pruneLockfile(
lockfile,
{ ...pkg, devDependencies: {} }, // Remove dev deps
"." as ProjectId,
{ warn: console.warn }
);// Clean up workspace lockfile
const cleanWorkspace = pruneSharedLockfile(workspaceLockfile, {
warn: (msg) => logger.info(`Workspace cleanup: ${msg}`)
});