or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

index.md

index.mddocs/

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

```