0
# Package Management Integration
1
2
Package manager detection, version resolution, and lockfile integration for npm, yarn, and npm-shrinkwrap environments. This module provides comprehensive support for different package managers and their specific behaviors, lockfile formats, and resolution strategies.
3
4
## Capabilities
5
6
### Package Manager Detection
7
8
Automatic detection of package manager based on lockfiles and project configuration.
9
10
```typescript { .api }
11
/**
12
* Detect which package manager is being used
13
* @param appRootPath - Application root directory path
14
* @param overridePackageManager - Force specific package manager
15
* @returns Detected or overridden package manager
16
*/
17
function detectPackageManager(
18
appRootPath: string,
19
overridePackageManager: PackageManager | null
20
): PackageManager;
21
22
type PackageManager = "yarn" | "npm" | "npm-shrinkwrap";
23
```
24
25
The detection logic checks for:
26
- `yarn.lock` → yarn
27
- `package-lock.json` → npm
28
- `npm-shrinkwrap.json` → npm-shrinkwrap
29
- Falls back to npm if no lockfile is found
30
31
**Usage Examples:**
32
33
```typescript
34
import { detectPackageManager } from "patch-package/dist/detectPackageManager";
35
36
// Auto-detect package manager
37
const packageManager = detectPackageManager(process.cwd(), null);
38
console.log(`Using package manager: ${packageManager}`);
39
40
// Force yarn usage
41
const forcedYarn = detectPackageManager(process.cwd(), "yarn");
42
43
// Use in patch creation
44
import { makePatch } from "patch-package/dist/makePatch";
45
makePatch({
46
packagePathSpecifier: "lodash",
47
appPath: process.cwd(),
48
packageManager: detectPackageManager(process.cwd(), null),
49
// ... other options
50
});
51
```
52
53
### Package Resolution
54
55
Resolution of package versions and locations from lockfiles.
56
57
```typescript { .api }
58
/**
59
* Get package resolution from lockfiles
60
* @param options - Package resolution options
61
* @returns Resolved package version string
62
*/
63
function getPackageResolution(options: PackageResolutionOptions): string;
64
65
interface PackageResolutionOptions {
66
/** Package details for resolution */
67
packageDetails: PackageDetails;
68
/** Package manager type */
69
packageManager: PackageManager;
70
/** Application path */
71
appPath: string;
72
}
73
```
74
75
Resolution behavior varies by package manager:
76
- **npm**: Reads `package-lock.json` for exact versions
77
- **yarn**: Parses `yarn.lock` for resolution info
78
- **npm-shrinkwrap**: Uses `npm-shrinkwrap.json` for locked versions
79
80
**Usage Examples:**
81
82
```typescript
83
import { getPackageResolution } from "patch-package/dist/getPackageResolution";
84
import { getPatchDetailsFromCliString } from "patch-package/dist/PackageDetails";
85
86
const packageDetails = getPatchDetailsFromCliString("lodash");
87
const resolution = getPackageResolution({
88
packageDetails,
89
packageManager: "yarn",
90
appPath: process.cwd()
91
});
92
93
console.log(`Resolved version: ${resolution}`);
94
```
95
96
### Version Utilities
97
98
Utilities for working with package versions and semver.
99
100
```typescript { .api }
101
/**
102
* Get package version from package.json
103
* @param packageJsonPath - Path to package.json file
104
* @returns Package version string
105
*/
106
function getPackageVersion(packageJsonPath: string): string;
107
108
/**
109
* Coerce version string to valid semver
110
* @param version - Version string to coerce
111
* @returns Valid semver string or null if invalid
112
*/
113
function coerceSemVer(version: string): string | null;
114
```
115
116
**Usage Examples:**
117
118
```typescript
119
import { getPackageVersion, coerceSemVer } from "patch-package/dist/getPackageVersion";
120
121
// Read version from package.json
122
const version = getPackageVersion("./node_modules/lodash/package.json");
123
124
// Coerce non-standard version to semver
125
const coercedVersion = coerceSemVer("1.0.0-beta.1+build.123");
126
// Returns: "1.0.0-beta.1"
127
128
const invalidVersion = coerceSemVer("not-a-version");
129
// Returns: null
130
```
131
132
## Dependency Analysis
133
134
### Development Dependency Detection
135
136
Determine if a package is a development dependency to optimize patch application.
137
138
```typescript { .api }
139
/**
140
* Check if package is development dependency
141
* @param options - Development dependency check options
142
* @returns True if package is dev dependency
143
*/
144
function packageIsDevDependency(options: DevDepOptions): boolean;
145
146
interface DevDepOptions {
147
/** Application path */
148
appPath: string;
149
/** Patch details for the package */
150
patchDetails: PatchedPackageDetails;
151
}
152
```
153
154
This function checks:
155
- `devDependencies` in package.json
156
- Nested dependency relationships
157
- Package installation context
158
159
**Usage Examples:**
160
161
```typescript
162
import { packageIsDevDependency } from "patch-package/dist/packageIsDevDependency";
163
164
const isDevDep = packageIsDevDependency({
165
appPath: process.cwd(),
166
patchDetails: {
167
name: "typescript",
168
version: "4.5.0",
169
// ... other patch details
170
}
171
});
172
173
if (isDevDep) {
174
console.log("This is a development dependency");
175
}
176
```
177
178
### File Dependency Resolution
179
180
Handle relative file dependencies in package resolutions.
181
182
```typescript { .api }
183
/**
184
* Resolve relative file dependencies in package resolutions
185
* @param appRootPath - Application root path
186
* @param resolutions - Package resolutions map
187
* @returns Updated resolutions with resolved file paths
188
*/
189
function resolveRelativeFileDependencies(
190
appRootPath: string,
191
resolutions: Record<string, string>
192
): Record<string, string>;
193
```
194
195
Handles cases like:
196
- `"my-package": "file:../local-package"`
197
- `"utils": "file:./packages/utils"`
198
- Relative path resolution across different project structures
199
200
**Usage Examples:**
201
202
```typescript
203
import { resolveRelativeFileDependencies } from "patch-package/dist/resolveRelativeFileDependencies";
204
205
const resolutions = {
206
"local-utils": "file:../utils",
207
"shared-lib": "file:./packages/shared",
208
"regular-dep": "^1.0.0"
209
};
210
211
const resolved = resolveRelativeFileDependencies(process.cwd(), resolutions);
212
// Converts relative file: paths to absolute paths
213
```
214
215
## Application Root Detection
216
217
### App Root Discovery
218
219
Find application root by locating package.json files in the directory hierarchy.
220
221
```typescript { .api }
222
/**
223
* Find application root by locating package.json
224
* @returns Application root path
225
* @throws Error if no package.json found
226
*/
227
function getAppRootPath(): string;
228
```
229
230
The function searches up the directory tree from the current working directory until it finds a `package.json` file, indicating the project root.
231
232
**Usage Examples:**
233
234
```typescript
235
import { getAppRootPath } from "patch-package/dist/getAppRootPath";
236
237
try {
238
const appRoot = getAppRootPath();
239
console.log(`Application root: ${appRoot}`);
240
} catch (error) {
241
console.error("Could not find application root");
242
}
243
```
244
245
## Package Manager-Specific Behaviors
246
247
### npm Integration
248
249
npm-specific handling including:
250
- `package-lock.json` parsing
251
- npm v5+ compatibility
252
- Shrinkwrap file support
253
- npm workspace detection
254
255
### yarn Integration
256
257
yarn v1-specific handling including:
258
- `yarn.lock` parsing
259
- Yarn workspace detection
260
- Resolution strategy differences
261
- Version constraint handling
262
263
### Workspace Support
264
265
Support for monorepo structures:
266
- npm workspaces
267
- yarn workspaces
268
- Lerna integration
269
- Relative dependency resolution
270
271
**Workspace Example:**
272
273
```typescript
274
import { detectPackageManager } from "patch-package/dist/detectPackageManager";
275
import { getAppRootPath } from "patch-package/dist/getAppRootPath";
276
277
// Works in monorepo workspaces
278
const appRoot = getAppRootPath(); // Finds workspace root
279
const packageManager = detectPackageManager(appRoot, null);
280
281
// Will correctly detect yarn workspaces or npm workspaces
282
console.log(`Workspace uses ${packageManager}`);
283
```
284
285
## Integration Examples
286
287
### Complete Package Manager Workflow
288
289
```typescript
290
import {
291
detectPackageManager,
292
getPackageResolution,
293
packageIsDevDependency,
294
getAppRootPath
295
} from "patch-package/dist";
296
297
// Full workflow example
298
async function analyzePackage(packageName: string) {
299
// Find application root
300
const appPath = getAppRootPath();
301
302
// Detect package manager
303
const packageManager = detectPackageManager(appPath, null);
304
console.log(`Using ${packageManager}`);
305
306
// Get package details
307
const packageDetails = getPatchDetailsFromCliString(packageName);
308
if (!packageDetails) {
309
throw new Error(`Invalid package: ${packageName}`);
310
}
311
312
// Resolve package version
313
const resolution = getPackageResolution({
314
packageDetails,
315
packageManager,
316
appPath
317
});
318
console.log(`Resolved version: ${resolution}`);
319
320
// Check if development dependency
321
const isDevDep = packageIsDevDependency({
322
appPath,
323
patchDetails: {
324
...packageDetails,
325
version: resolution,
326
patchFilename: `${packageName}+${resolution}.patch`,
327
isDevOnly: false
328
}
329
});
330
331
console.log(`Development dependency: ${isDevDep}`);
332
333
return {
334
packageManager,
335
resolution,
336
isDevDep,
337
appPath
338
};
339
}
340
```
341
342
This integration layer ensures patch-package works seamlessly across different package manager environments while respecting each manager's specific behaviors and conventions.