Skip to content

Commit 4c61623

Browse files
committed
fix: [OSM-2481] pnpm outofsync error fix for overlap dep in peer/dev deps
1 parent 2dedbdc commit 4c61623

File tree

13 files changed

+1771
-4
lines changed

13 files changed

+1771
-4
lines changed

lib/dep-graph-builders/pnpm/lockfile-parser/lockfile-parser.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ export abstract class PnpmLockfileParser {
9292
// Return early because dependencies were already normalized for this importer
9393
// as part of another's importer dependency and stored in extractedPackages
9494
this.extractedPackages[`${name}@${version}`] &&
95+
this.extractedPackages[`${name}@${version}`].localWorkspacePackage &&
9596
!isEmpty(this.extractedPackages[`${name}@${version}`].dependencies)
9697
) {
9798
return this.normalizedPkgToTopLevel(
@@ -134,6 +135,7 @@ export abstract class PnpmLockfileParser {
134135
devDependencies: this.topLevelDepsToNormalizedPkgs(devDeps),
135136
optionalDependencies: this.topLevelDepsToNormalizedPkgs(optionalDeps),
136137
isDev: false,
138+
localWorkspacePackage: true,
137139
};
138140
}
139141
return { ...prodDeps, ...devDeps, ...optionalDeps, ...peerDeps };
@@ -246,6 +248,7 @@ export abstract class PnpmLockfileParser {
246248
isDev,
247249
dependencies: {},
248250
devDependencies: {},
251+
localWorkspacePackage: true,
249252
};
250253

251254
const subDeps = this.rawPnpmLock.importers[resolvedPathDep] || {
@@ -280,6 +283,7 @@ export abstract class PnpmLockfileParser {
280283
dependencies: resolvedDeps,
281284
devDependencies: resolvedDevDeps,
282285
optionalDependencies: resolvedOptionalDeps,
286+
localWorkspacePackage: true,
283287
};
284288
}
285289
return version;

lib/dep-graph-builders/pnpm/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ export type NormalisedPnpmPkg = {
2929
dependencies: Record<string, string>;
3030
devDependencies: Record<string, string>;
3131
optionalDependencies?: Record<string, string>;
32+
localWorkspacePackage?: boolean;
3233
};
3334

3435
export type PnpmNode = {

lib/dep-graph-builders/util.ts

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,7 @@ export const getTopLevelDeps = (
5454
): Dependencies => {
5555
const prodDeps = getGraphDependencies(pkgJson.dependencies || {}, false);
5656

57-
const devDeps = options.includeDevDeps
58-
? getGraphDependencies(pkgJson.devDependencies || {}, true)
59-
: {};
57+
const devDeps = getGraphDependencies(pkgJson.devDependencies || {}, true);
6058

6159
const optionalDeps = options.includeOptionalDeps
6260
? getGraphDependencies(pkgJson.optionalDependencies || {}, false)
@@ -66,7 +64,24 @@ export const getTopLevelDeps = (
6664
? getGraphDependencies(pkgJson.peerDependencies || {}, false)
6765
: {};
6866

69-
return { ...prodDeps, ...devDeps, ...optionalDeps, ...peerDeps };
67+
const deps = { ...prodDeps, ...optionalDeps, ...peerDeps };
68+
69+
if (options.includeDevDeps) {
70+
// Ensure dev dependency 'isDev' flags are correctly set.
71+
// Dev dependencies are applied last to override shared keys with regular dependencies.
72+
return { ...deps, ...devDeps };
73+
}
74+
75+
// For includeDevDeps option set to false, simulate pnpm install --prod
76+
// by excluding all devDependencies,
77+
// ignoring potential duplicates in other dependency lists.
78+
// https://pnpm.io/cli/install#--prod--p
79+
return Object.keys(deps)
80+
.filter((packageName) => !devDeps.hasOwnProperty(packageName))
81+
.reduce((result, packageName) => {
82+
result[packageName] = deps[packageName];
83+
return result;
84+
}, {});
7085
};
7186

7287
/**
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
{
2+
"schemaVersion": "1.3.0",
3+
"pkgManager": {
4+
"name": "pnpm"
5+
},
6+
"pkgs": [
7+
{
8+
9+
"info": {
10+
"name": "duplicate-dev-peer-deps",
11+
"version": "1.0.0"
12+
}
13+
},
14+
{
15+
16+
"info": {
17+
"name": "react",
18+
"version": "18.3.1"
19+
}
20+
},
21+
{
22+
23+
"info": {
24+
"name": "loose-envify",
25+
"version": "1.4.0"
26+
}
27+
},
28+
{
29+
30+
"info": {
31+
"name": "js-tokens",
32+
"version": "4.0.0"
33+
}
34+
}
35+
],
36+
"graph": {
37+
"rootNodeId": "root-node",
38+
"nodes": [
39+
{
40+
"nodeId": "root-node",
41+
"pkgId": "[email protected]",
42+
"deps": [
43+
{
44+
"nodeId": "[email protected]"
45+
}
46+
]
47+
},
48+
{
49+
"nodeId": "[email protected]",
50+
"pkgId": "[email protected]",
51+
"deps": [
52+
{
53+
"nodeId": "[email protected]"
54+
}
55+
],
56+
"info": {
57+
"labels": {
58+
"scope": "prod"
59+
}
60+
}
61+
},
62+
{
63+
"nodeId": "[email protected]",
64+
"pkgId": "[email protected]",
65+
"deps": [
66+
{
67+
"nodeId": "[email protected]"
68+
}
69+
],
70+
"info": {
71+
"labels": {
72+
"scope": "prod"
73+
}
74+
}
75+
},
76+
{
77+
"nodeId": "[email protected]",
78+
"pkgId": "[email protected]",
79+
"deps": [],
80+
"info": {
81+
"labels": {
82+
"scope": "prod"
83+
}
84+
}
85+
}
86+
]
87+
}
88+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"name": "duplicate-dev-peer-deps",
3+
"version": "1.0.0",
4+
"peerDependencies": {
5+
"@emotion/react": "^11.13.5",
6+
"react": "^18.3.1"
7+
},
8+
"devDependencies": {
9+
"@emotion/react": "^11.13.5",
10+
"typescript": "5.7.2"
11+
}
12+
}

0 commit comments

Comments
 (0)