0
# PNPM Lockfile Pruner
1
2
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.
3
4
## Package Information
5
6
- **Package Name**: @pnpm/lockfile.pruner
7
- **Package Type**: npm
8
- **Language**: TypeScript
9
- **Installation**: `pnpm add @pnpm/lockfile.pruner`
10
11
## Core Imports
12
13
```typescript
14
import { pruneSharedLockfile, pruneLockfile } from "@pnpm/lockfile.pruner";
15
```
16
17
For CommonJS:
18
19
```javascript
20
const { pruneSharedLockfile, pruneLockfile } = require("@pnpm/lockfile.pruner");
21
```
22
23
Import types (also re-exported from this package):
24
25
```typescript
26
import {
27
LockfileObject,
28
PackageSnapshots,
29
ProjectSnapshot,
30
ResolvedDependencies
31
} from "@pnpm/lockfile.pruner";
32
```
33
34
## Basic Usage
35
36
```typescript
37
import { pruneLockfile, pruneSharedLockfile } from "@pnpm/lockfile.pruner";
38
import { ProjectId } from "@pnpm/types";
39
40
// Prune a single project's lockfile
41
const prunedLockfile = pruneLockfile(
42
originalLockfile,
43
packageManifest,
44
"." as ProjectId,
45
{
46
warn: (msg: string) => console.warn(msg)
47
}
48
);
49
50
// Prune a shared lockfile (workspace/monorepo)
51
const prunedSharedLockfile = pruneSharedLockfile(originalLockfile, {
52
warn: (msg: string) => console.warn(msg)
53
});
54
```
55
56
## Capabilities
57
58
### Single Project Lockfile Pruning
59
60
Prunes a lockfile based on specific package manifest requirements, handling development, production, and optional dependencies appropriately.
61
62
```typescript { .api }
63
/**
64
* Prune lockfile based on specific package manifest and project requirements
65
* @param lockfile - The lockfile object to prune
66
* @param pkg - Package manifest (package.json content) to base pruning on
67
* @param importerId - Project identifier within the lockfile
68
* @param opts - Pruning options including warning callback and dependencies graph
69
* @returns Pruned lockfile object tailored to the specific package requirements
70
*/
71
function pruneLockfile(
72
lockfile: LockfileObject,
73
pkg: PackageManifest,
74
importerId: ProjectId,
75
opts: {
76
warn?: (msg: string) => void;
77
dependenciesGraph?: DependenciesGraph;
78
}
79
): LockfileObject;
80
```
81
82
**Usage Examples:**
83
84
```typescript
85
import { pruneLockfile } from "@pnpm/lockfile.pruner";
86
import { ProjectId } from "@pnpm/types";
87
88
// Basic pruning for a single project
89
const result = pruneLockfile(
90
lockfile,
91
{
92
name: "my-app",
93
version: "1.0.0",
94
dependencies: {
95
"lodash": "^4.17.21",
96
"express": "^4.18.0"
97
},
98
devDependencies: {
99
"typescript": "^4.8.0"
100
}
101
},
102
"." as ProjectId,
103
{
104
warn: (msg) => console.warn(`Warning: ${msg}`)
105
}
106
);
107
108
// Pruning with dependencies graph for advanced scenarios
109
const advancedResult = pruneLockfile(
110
lockfile,
111
packageManifest,
112
"packages/frontend" as ProjectId,
113
{
114
warn: (msg) => logger.warn(msg),
115
dependenciesGraph: {
116
"package@1.0.0": { optional: false },
117
"optional-package@2.0.0": { optional: true }
118
}
119
}
120
);
121
```
122
123
### Shared Lockfile Pruning
124
125
Removes unused packages from shared/workspace lockfiles by analyzing all importers and keeping only referenced packages.
126
127
```typescript { .api }
128
/**
129
* Remove unused packages from shared/workspace lockfiles
130
* @param lockfile - The lockfile object to prune
131
* @param opts - Optional pruning options
132
* @returns Pruned lockfile object with unused packages removed
133
*/
134
function pruneSharedLockfile(
135
lockfile: LockfileObject,
136
opts?: {
137
dependenciesGraph?: DependenciesGraph;
138
warn?: (msg: string) => void;
139
}
140
): LockfileObject;
141
```
142
143
**Usage Examples:**
144
145
```typescript
146
import { pruneSharedLockfile } from "@pnpm/lockfile.pruner";
147
148
// Basic shared lockfile pruning
149
const pruned = pruneSharedLockfile(workspaceLockfile);
150
151
// With warning callback
152
const prunedWithWarnings = pruneSharedLockfile(workspaceLockfile, {
153
warn: (msg) => console.warn(`Lockfile pruning: ${msg}`)
154
});
155
156
// With dependencies graph for advanced dependency tracking
157
const advancedPruned = pruneSharedLockfile(workspaceLockfile, {
158
dependenciesGraph: dependencyGraph,
159
warn: (msg) => logger.warn(msg)
160
});
161
```
162
163
## Types
164
165
### Core Types
166
167
```typescript { .api }
168
/**
169
* Main lockfile structure containing all project dependencies and metadata
170
*/
171
interface LockfileObject {
172
/** Version of the lockfile format */
173
lockfileVersion: string | number;
174
/** Individual project/package dependency snapshots */
175
importers: Record<ProjectId, ProjectSnapshot>;
176
/** Package resolution snapshots with dependency information */
177
packages?: PackageSnapshots;
178
/** Checksum for pnpmfile.js if present */
179
pnpmfileChecksum?: string;
180
/** List of ignored optional dependencies */
181
ignoredOptionalDependencies?: string[];
182
}
183
184
/**
185
* Individual project snapshot within a lockfile
186
*/
187
interface ProjectSnapshot {
188
/** Version specifiers from package.json */
189
specifiers: ResolvedDependencies;
190
/** Production dependencies */
191
dependencies?: ResolvedDependencies;
192
/** Optional dependencies */
193
optionalDependencies?: ResolvedDependencies;
194
/** Development dependencies */
195
devDependencies?: ResolvedDependencies;
196
}
197
198
/**
199
* Mapping of package names to their resolved versions/references
200
*/
201
interface ResolvedDependencies {
202
[depName: string]: string;
203
}
204
205
/**
206
* Collection of package snapshots indexed by dependency path
207
*/
208
interface PackageSnapshots {
209
[depPath: DepPath]: PackageSnapshot;
210
}
211
212
/**
213
* Individual package snapshot with resolution and dependency information
214
*/
215
interface PackageSnapshot {
216
/** Package resolution information */
217
resolution: Resolution;
218
/** Runtime dependencies */
219
dependencies?: ResolvedDependencies;
220
/** Optional dependencies */
221
optionalDependencies?: ResolvedDependencies;
222
/** Development dependencies */
223
devDependencies?: ResolvedDependencies;
224
/** Whether this package is optional */
225
optional?: boolean;
226
}
227
228
/**
229
* Package manifest structure (package.json content)
230
*/
231
interface PackageManifest {
232
name?: string;
233
version?: string;
234
dependencies?: Record<string, string>;
235
devDependencies?: Record<string, string>;
236
optionalDependencies?: Record<string, string>;
237
[key: string]: any;
238
}
239
240
/**
241
* Dependencies graph for advanced pruning scenarios
242
* Maps dependency paths to their optional status
243
*/
244
type DependenciesGraph = Record<DepPath, { optional?: boolean }>;
245
```
246
247
### Utility Types
248
249
```typescript { .api }
250
/**
251
* Dependency path identifier (from @pnpm/types)
252
*/
253
type DepPath = string & { readonly brand: unique symbol };
254
255
/**
256
* Project identifier within a workspace (from @pnpm/types)
257
*/
258
type ProjectId = string & { readonly brand: unique symbol };
259
260
/**
261
* Package resolution information
262
*/
263
interface Resolution {
264
/** Package integrity hash */
265
integrity?: string;
266
/** Package tarball URL */
267
tarball?: string;
268
/** Git repository information */
269
repo?: string;
270
/** Git commit hash */
271
commit?: string;
272
[key: string]: any;
273
}
274
```
275
276
## Key Features
277
278
### Dependency Management
279
- **Optional Dependencies**: Properly handles optional dependencies with correct flagging
280
- **Linked Dependencies**: Preserves local and linked packages (link: protocol)
281
- **Workspace Support**: Full support for monorepo/workspace environments
282
- **Multi-Project**: Handles multiple projects within a single lockfile
283
284
### Pruning Logic
285
- **Unused Package Removal**: Removes packages not referenced by any project
286
- **Dependency Chain Analysis**: Recursively analyzes dependency trees
287
- **Optional Flag Management**: Correctly manages optional flags based on usage context
288
- **Specifier Preservation**: Maintains version specifiers from package.json
289
290
### Error Handling
291
- **Warning Callbacks**: Provides warning notifications for missing resolutions
292
- **Missing Package Handling**: Gracefully handles missing package entries
293
- **Validation**: Ensures lockfile integrity during pruning operations
294
295
## Common Use Cases
296
297
### CI/CD Pipeline Optimization
298
```typescript
299
// Optimize lockfile before deployment
300
const optimizedLockfile = pruneSharedLockfile(lockfile, {
301
warn: (msg) => console.log(`[CI] ${msg}`)
302
});
303
```
304
305
### Development Environment Cleanup
306
```typescript
307
// Remove unused dev dependencies from production lockfile
308
const productionLockfile = pruneLockfile(
309
lockfile,
310
{ ...pkg, devDependencies: {} }, // Remove dev deps
311
"." as ProjectId,
312
{ warn: console.warn }
313
);
314
```
315
316
### Workspace Maintenance
317
```typescript
318
// Clean up workspace lockfile
319
const cleanWorkspace = pruneSharedLockfile(workspaceLockfile, {
320
warn: (msg) => logger.info(`Workspace cleanup: ${msg}`)
321
});
322
```