Prune a pnpm-lock.yaml by removing unused package entries and optimizing lockfile structure.
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
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.
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}`)
});