Utilities for cleaning up node_modules directories in pnpm-managed projects
npx @tessl/cli install tessl/npm--pnpm--modules-cleaner@1000.0.00
# @pnpm/modules-cleaner
1
2
@pnpm/modules-cleaner provides utilities for cleaning up node_modules directories in pnpm-managed projects. It offers functionality to compare lockfiles and remove redundant packages from node_modules, helping maintain clean and optimized package installations within the pnpm ecosystem.
3
4
## Package Information
5
6
- **Package Name**: @pnpm/modules-cleaner
7
- **Package Type**: npm
8
- **Language**: TypeScript
9
- **Installation**: `pnpm install @pnpm/modules-cleaner`
10
- **Node.js**: >=18.12
11
- **License**: MIT
12
- **Peer Dependencies**: @pnpm/logger (>=5.1.0 <1001.0.0)
13
14
## Core Imports
15
16
```typescript
17
import { prune } from "@pnpm/modules-cleaner";
18
```
19
20
For CommonJS:
21
22
```javascript
23
const { prune } = require("@pnpm/modules-cleaner");
24
```
25
26
Advanced imports (for direct access to utility functions):
27
28
```typescript
29
import { removeDirectDependency, removeIfEmpty } from "@pnpm/modules-cleaner/lib/removeDirectDependency";
30
```
31
32
## Basic Usage
33
34
```typescript
35
import { prune } from "@pnpm/modules-cleaner";
36
import type {
37
Lockfile,
38
StoreController,
39
HoistedDependencies,
40
ProjectId,
41
ProjectRootDir,
42
DepPath
43
} from "@pnpm/types";
44
45
// Assume you have lockfile objects and store controller available
46
declare const wantedLockfile: Lockfile;
47
declare const currentLockfile: Lockfile;
48
declare const storeController: StoreController;
49
50
// Basic pruning operation
51
const removedPaths = await prune(
52
[
53
{
54
binsDir: "/project/node_modules/.bin",
55
id: "project-id" as ProjectId,
56
modulesDir: "/project/node_modules",
57
rootDir: "/project" as ProjectRootDir,
58
},
59
],
60
{
61
include: {
62
dependencies: true,
63
devDependencies: true,
64
optionalDependencies: true
65
},
66
hoistedDependencies: new Map() as HoistedDependencies,
67
wantedLockfile,
68
currentLockfile,
69
skipped: new Set<DepPath>(),
70
virtualStoreDir: "/project/node_modules/.pnpm",
71
virtualStoreDirMaxLength: 120,
72
lockfileDir: "/project",
73
storeController,
74
}
75
);
76
```
77
78
## Capabilities
79
80
### Package Pruning
81
82
Compares the wanted lockfile with the current one and removes redundant packages from node_modules that are no longer needed.
83
84
```typescript { .api }
85
/**
86
* Compares the wanted lockfile with the current one and removes redundant packages from node_modules
87
* @param importers - Array of project configurations to prune
88
* @param opts - Pruning options and configuration
89
* @returns Promise that resolves to a Set of removed package paths
90
*/
91
async function prune(
92
importers: Array<{
93
/** Directory containing binary files for the project */
94
binsDir: string;
95
/** Unique identifier for the project */
96
id: ProjectId;
97
/** Path to the node_modules directory */
98
modulesDir: string;
99
/** Whether to prune direct dependencies */
100
pruneDirectDependencies?: boolean;
101
/** Specific packages to remove */
102
removePackages?: string[];
103
/** Root directory of the project */
104
rootDir: ProjectRootDir;
105
}>,
106
opts: {
107
/** Whether to deduplicate direct dependencies */
108
dedupeDirectDeps?: boolean;
109
/** Run in dry-run mode without actually removing files */
110
dryRun?: boolean;
111
/** Specify which dependency types to include in pruning */
112
include: { [dependenciesField in DependenciesField]: boolean };
113
/** Map of hoisted dependencies */
114
hoistedDependencies: HoistedDependencies;
115
/** Directory for hoisted modules */
116
hoistedModulesDir?: string;
117
/** Directory for publicly hoisted modules */
118
publicHoistedModulesDir?: string;
119
/** The desired lockfile state */
120
wantedLockfile: Lockfile;
121
/** The current lockfile state */
122
currentLockfile: Lockfile;
123
/** Whether to prune the store */
124
pruneStore?: boolean;
125
/** Whether to prune the virtual store */
126
pruneVirtualStore?: boolean;
127
/** Set of dependency paths to skip */
128
skipped: Set<DepPath>;
129
/** Path to the virtual store directory */
130
virtualStoreDir: string;
131
/** Maximum length for virtual store directory paths */
132
virtualStoreDirMaxLength: number;
133
/** Directory containing the lockfile */
134
lockfileDir: string;
135
/** Store controller for package management */
136
storeController: StoreController;
137
}
138
): Promise<Set<string>>;
139
```
140
141
### Direct Dependency Removal
142
143
Specifically removes a single direct dependency from a project's node_modules directory, including its binary files.
144
145
```typescript { .api }
146
/**
147
* Removes a specific direct dependency from node_modules
148
* @param dependency - The dependency to remove with optional metadata
149
* @param opts - Configuration options for removal operation
150
* @returns Promise that resolves when removal is complete
151
*/
152
async function removeDirectDependency(
153
dependency: {
154
/** The type of dependency field this came from */
155
dependenciesField?: DependenciesField | undefined;
156
/** Name of the package to remove */
157
name: string;
158
},
159
opts: {
160
/** Directory containing binary files for the project */
161
binsDir: string;
162
/** Run in dry-run mode without actually removing files */
163
dryRun?: boolean;
164
/** Path to the node_modules directory */
165
modulesDir: string;
166
/** Whether to suppress removal logs */
167
muteLogs?: boolean;
168
/** Root directory of the project */
169
rootDir: ProjectRootDir;
170
}
171
): Promise<void>;
172
```
173
174
### Empty Directory Removal
175
176
Utility function to remove a directory only if it's empty.
177
178
```typescript { .api }
179
/**
180
* Removes a directory if it's empty
181
* @param dir - Path to directory to potentially remove
182
* @returns Promise that resolves when operation is complete
183
*/
184
async function removeIfEmpty(dir: string): Promise<void>;
185
```
186
187
## Types
188
189
```typescript { .api }
190
// Core type definitions used by the API
191
192
/** Unique identifier for a project */
193
type ProjectId = string & { readonly __brand: unique symbol };
194
195
/** Root directory path for a project */
196
type ProjectRootDir = string & { readonly __brand: unique symbol };
197
198
/** Dependency path identifier */
199
type DepPath = string & { readonly __brand: unique symbol };
200
201
/** Map of hoisted dependencies */
202
type HoistedDependencies = Map<string, string[]>;
203
204
/** Fields that can contain dependencies in package.json */
205
type DependenciesField = 'dependencies' | 'devDependencies' | 'optionalDependencies';
206
207
/** Lockfile structure containing package information */
208
interface Lockfile {
209
version: string;
210
packages?: PackageSnapshots;
211
importers?: Record<string, ProjectSnapshot>;
212
// Additional lockfile properties...
213
}
214
215
/** Package snapshots containing dependency information */
216
type PackageSnapshots = Record<string, PackageSnapshot>;
217
218
/** Individual package snapshot with dependency metadata */
219
interface PackageSnapshot {
220
resolution?: { integrity?: string; tarball?: string };
221
dependencies?: Record<string, string>;
222
optionalDependencies?: Record<string, string>;
223
// Additional snapshot properties...
224
}
225
226
/** Project snapshot containing project-specific dependency information */
227
interface ProjectSnapshot {
228
dependencies?: Record<string, string>;
229
devDependencies?: Record<string, string>;
230
optionalDependencies?: Record<string, string>;
231
// Additional project properties...
232
}
233
234
/** Store controller interface for package management operations */
235
interface StoreController {
236
close(): Promise<void>;
237
fetchPackage(fetchPackageOpts: any): Promise<any>;
238
requestPackage(requestPackageOpts: any): Promise<any>;
239
upload(builtPkgLocation: string, opts: any): Promise<void>;
240
}
241
```
242
243
## Related Modules
244
245
This package also includes additional utility functions that can be imported directly from their modules:
246
247
- `removeDirectDependency`: Available from `@pnpm/modules-cleaner/lib/removeDirectDependency` - Removes a specific direct dependency from node_modules
248
- `removeIfEmpty`: Available from `@pnpm/modules-cleaner/lib/removeDirectDependency` - Removes a directory if it's empty
249
250
The main `prune` function utilizes these utilities internally as part of its comprehensive cleanup process.