@pnpm/installing.deps-resolver 1100.2.7 → 1100.2.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +4437 -0
- package/lib/dedupeInjectedDeps.js +20 -1
- package/lib/depPathCompatibility.d.ts +4 -0
- package/lib/depPathCompatibility.js +28 -0
- package/lib/hoistPeers.d.ts +7 -2
- package/lib/hoistPeers.js +18 -12
- package/lib/resolveDependencies.js +36 -2
- package/lib/resolvePeers.js +82 -17
- package/package.json +30 -30
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
2
|
import normalize from 'normalize-path';
|
|
3
|
+
import { isCompatibleAndHasMoreDeps } from './depPathCompatibility.js';
|
|
3
4
|
export function dedupeInjectedDeps(opts) {
|
|
4
5
|
const injectedDepsByProjects = getInjectedDepsByProjects(opts);
|
|
5
6
|
const dedupeMap = getDedupeMap(injectedDepsByProjects, opts);
|
|
@@ -46,7 +47,25 @@ function getDedupeMap(injectedDepsByProjects, opts) {
|
|
|
46
47
|
// The injected project in the workspace may have dev deps
|
|
47
48
|
const children = Object.entries(node.children);
|
|
48
49
|
const isSubset = children
|
|
49
|
-
.every(([alias, depPath]) =>
|
|
50
|
+
.every(([alias, depPath]) => {
|
|
51
|
+
const targetDepPath = targetProjectDeps.get(alias);
|
|
52
|
+
if (targetDepPath === depPath)
|
|
53
|
+
return true;
|
|
54
|
+
if (targetDepPath == null)
|
|
55
|
+
return false;
|
|
56
|
+
// A shared dep can resolve peer-suffixed on one side and peer-free on
|
|
57
|
+
// the other (e.g. an existing lockfile pinned debug's optional
|
|
58
|
+
// supports-color for the target project but not the injected
|
|
59
|
+
// occurrence). Accept the target's variant when it's the same package
|
|
60
|
+
// identity and a compatible superset. See pnpm/pnpm#10433.
|
|
61
|
+
const targetNode = opts.depGraph[targetDepPath];
|
|
62
|
+
const injectedChildNode = opts.depGraph[depPath];
|
|
63
|
+
if (targetNode == null || injectedChildNode == null)
|
|
64
|
+
return false;
|
|
65
|
+
if (targetNode.pkgIdWithPatchHash !== injectedChildNode.pkgIdWithPatchHash)
|
|
66
|
+
return false;
|
|
67
|
+
return isCompatibleAndHasMoreDeps(opts.depGraph, targetDepPath, depPath);
|
|
68
|
+
});
|
|
50
69
|
if (isSubset) {
|
|
51
70
|
dedupedInjectedDeps.set(alias, dep.id);
|
|
52
71
|
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { DepPath } from '@pnpm/types';
|
|
2
|
+
import type { GenericDependenciesGraphNodeWithResolvedChildren, GenericDependenciesGraphWithResolvedChildren, PartialResolvedPackage } from './resolvePeers.js';
|
|
3
|
+
export declare function nodeDepsCount(node: GenericDependenciesGraphNodeWithResolvedChildren): number;
|
|
4
|
+
export declare function isCompatibleAndHasMoreDeps<T extends PartialResolvedPackage>(depGraph: GenericDependenciesGraphWithResolvedChildren<T>, depPath1: DepPath, depPath2: DepPath): boolean;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// Shared helpers used by both resolvePeers (dedupePeerDependents) and
|
|
2
|
+
// dedupeInjectedDeps. Lives in its own module so neither consumer has to import
|
|
3
|
+
// the other, which would create a runtime cycle. The type imports above are
|
|
4
|
+
// erased at build time, so no cycle exists at runtime.
|
|
5
|
+
export function nodeDepsCount(node) {
|
|
6
|
+
return Object.keys(node.children).length + node.resolvedPeerNames.size;
|
|
7
|
+
}
|
|
8
|
+
// Whether `depPath1` is a superset-or-equal of `depPath2`: same-or-more resolved
|
|
9
|
+
// children and peers. Compares dependency/peer *sets* only, not package
|
|
10
|
+
// identity, so callers must pass depPaths already known to share a
|
|
11
|
+
// `pkgIdWithPatchHash` — otherwise two unrelated leaf packages (both with empty
|
|
12
|
+
// sets) would count as compatible.
|
|
13
|
+
export function isCompatibleAndHasMoreDeps(depGraph, depPath1, depPath2) {
|
|
14
|
+
const node1 = depGraph[depPath1];
|
|
15
|
+
const node2 = depGraph[depPath2];
|
|
16
|
+
if (nodeDepsCount(node1) < nodeDepsCount(node2))
|
|
17
|
+
return false;
|
|
18
|
+
const node1DepPathsSet = new Set(Object.values(node1.children));
|
|
19
|
+
const node2DepPaths = Object.values(node2.children);
|
|
20
|
+
if (!node2DepPaths.every((depPath) => node1DepPathsSet.has(depPath)))
|
|
21
|
+
return false;
|
|
22
|
+
for (const depPath of node2.resolvedPeerNames) {
|
|
23
|
+
if (!node1.resolvedPeerNames.has(depPath))
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
return true;
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=depPathCompatibility.js.map
|
package/lib/hoistPeers.d.ts
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
import type { PreferredVersions } from '@pnpm/resolving.resolver-base';
|
|
2
|
-
|
|
2
|
+
/** One workspace-root dependency that a missing peer can be satisfied with. */
|
|
3
|
+
export interface HoistableRootDep {
|
|
4
|
+
alias: string;
|
|
5
|
+
pkgName: string;
|
|
6
|
+
normalizedBareSpecifier?: string;
|
|
7
|
+
}
|
|
3
8
|
export declare function hoistPeers(opts: {
|
|
4
9
|
autoInstallPeers: boolean;
|
|
5
10
|
allPreferredVersions?: PreferredVersions;
|
|
6
|
-
workspaceRootDeps:
|
|
11
|
+
workspaceRootDeps: HoistableRootDep[];
|
|
7
12
|
}, missingRequiredPeers: Array<[string, {
|
|
8
13
|
range: string;
|
|
9
14
|
}]>): Record<string, string>;
|
package/lib/hoistPeers.js
CHANGED
|
@@ -9,7 +9,7 @@ export function hoistPeers(opts, missingRequiredPeers) {
|
|
|
9
9
|
continue;
|
|
10
10
|
}
|
|
11
11
|
const rootDep = opts.workspaceRootDeps
|
|
12
|
-
.filter((rootDep) => rootDep.
|
|
12
|
+
.filter((rootDep) => rootDep.pkgName === peerName)
|
|
13
13
|
.sort((rootDep1, rootDep2) => lexCompare(rootDep1.alias, rootDep2.alias))[0];
|
|
14
14
|
if (rootDep?.normalizedBareSpecifier) {
|
|
15
15
|
dependencies[peerName] = rootDep.normalizedBareSpecifier;
|
|
@@ -27,22 +27,28 @@ export function hoistPeers(opts, missingRequiredPeers) {
|
|
|
27
27
|
nonVersions.push(spec);
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
|
-
//
|
|
31
|
-
//
|
|
32
|
-
//
|
|
33
|
-
//
|
|
34
|
-
//
|
|
35
|
-
|
|
36
|
-
|
|
30
|
+
// Dedupe onto a preferred version only when it actually satisfies the
|
|
31
|
+
// wanted peer range. Picking the highest preferred version regardless of
|
|
32
|
+
// the range lets a version resolved for one importer be auto-installed as
|
|
33
|
+
// another importer's peer even though nothing in that importer's closure
|
|
34
|
+
// accepts it, silently producing a peer graph that mixes incompatible
|
|
35
|
+
// majors. Ranges that are not semver (workspace:, npm: aliases, dist-tags)
|
|
36
|
+
// cannot be checked, so they keep the dedupe-to-highest behavior.
|
|
37
|
+
const isSemverRange = semver.validRange(range, { includePrerelease: true }) != null;
|
|
38
|
+
const satisfyingVersion = isSemverRange
|
|
37
39
|
? semver.maxSatisfying(versions, range, { includePrerelease: true })
|
|
38
40
|
: null;
|
|
39
41
|
if (satisfyingVersion) {
|
|
40
42
|
dependencies[peerName] = [satisfyingVersion, ...nonVersions].join(' || ');
|
|
41
43
|
}
|
|
42
|
-
else if (
|
|
43
|
-
//
|
|
44
|
-
// Use the range directly so pnpm resolves it from the registry
|
|
45
|
-
|
|
44
|
+
else if (isSemverRange && versions.length > 0) {
|
|
45
|
+
// Preferred versions exist but none satisfies the wanted range.
|
|
46
|
+
// Use the range directly so pnpm resolves it from the registry rather
|
|
47
|
+
// than installing a version the peer explicitly rejects. Without
|
|
48
|
+
// autoInstallPeers, hoist nothing and leave the peer missing.
|
|
49
|
+
if (opts.autoInstallPeers) {
|
|
50
|
+
dependencies[peerName] = range;
|
|
51
|
+
}
|
|
46
52
|
}
|
|
47
53
|
else {
|
|
48
54
|
dependencies[peerName] = [semver.maxSatisfying(versions, '*', { includePrerelease: true }), ...nonVersions]
|
|
@@ -54,7 +54,7 @@ export async function resolveRootDependencies(ctx, importers) {
|
|
|
54
54
|
let workspaceRootDeps;
|
|
55
55
|
if (ctx.resolvePeersFromWorkspaceRoot) {
|
|
56
56
|
const rootImporterIndex = importers.findIndex(({ options }) => options.parentIds[0] === '.');
|
|
57
|
-
workspaceRootDeps = pkgAddressesByImportersWithoutPeers[rootImporterIndex]?.pkgAddresses ?? [];
|
|
57
|
+
workspaceRootDeps = getHoistableRootDeps(importers[rootImporterIndex], pkgAddressesByImportersWithoutPeers[rootImporterIndex]?.pkgAddresses ?? []);
|
|
58
58
|
}
|
|
59
59
|
else {
|
|
60
60
|
workspaceRootDeps = [];
|
|
@@ -150,6 +150,38 @@ export async function resolveRootDependencies(ctx, importers) {
|
|
|
150
150
|
time,
|
|
151
151
|
};
|
|
152
152
|
}
|
|
153
|
+
/**
|
|
154
|
+
* Lists the workspace-root dependencies that `hoistPeers` may satisfy a
|
|
155
|
+
* missing peer with. A root dependency reused from the lockfile skips full
|
|
156
|
+
* resolution, so it has no address (or an address without a
|
|
157
|
+
* normalizedBareSpecifier); its wanted specifier is used instead, so that
|
|
158
|
+
* re-resolving with a lockfile hoists the same version as a fresh install of
|
|
159
|
+
* the same manifest.
|
|
160
|
+
*/
|
|
161
|
+
function getHoistableRootDeps(rootImporter, rootPkgAddresses) {
|
|
162
|
+
const wantedSpecifierByAlias = new Map();
|
|
163
|
+
for (const wantedDep of rootImporter?.wantedDependencies ?? []) {
|
|
164
|
+
if (wantedDep.alias && wantedDep.bareSpecifier) {
|
|
165
|
+
wantedSpecifierByAlias.set(wantedDep.alias, wantedDep.bareSpecifier);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
const rootDeps = rootPkgAddresses.map((pkgAddress) => ({
|
|
169
|
+
alias: pkgAddress.alias,
|
|
170
|
+
pkgName: pkgAddress.pkg.name,
|
|
171
|
+
normalizedBareSpecifier: pkgAddress.normalizedBareSpecifier ?? wantedSpecifierByAlias.get(pkgAddress.alias),
|
|
172
|
+
}));
|
|
173
|
+
const coveredAliases = new Set(rootDeps.map(({ alias }) => alias));
|
|
174
|
+
for (const [alias, bareSpecifier] of wantedSpecifierByAlias) {
|
|
175
|
+
if (coveredAliases.has(alias))
|
|
176
|
+
continue;
|
|
177
|
+
rootDeps.push({
|
|
178
|
+
alias,
|
|
179
|
+
pkgName: unwrapPackageName(alias, bareSpecifier).pkgName,
|
|
180
|
+
normalizedBareSpecifier: bareSpecifier,
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
return rootDeps;
|
|
184
|
+
}
|
|
153
185
|
async function resolveDependenciesOfImporters(ctx, importers) {
|
|
154
186
|
const pickLowestVersion = ctx.resolutionMode === 'time-based' || ctx.resolutionMode === 'lowest-direct';
|
|
155
187
|
const resolveResults = await Promise.all(importers.map(async (importer) => {
|
|
@@ -1074,7 +1106,9 @@ async function resolveDependency(wantedDependency, ctx, options) {
|
|
|
1074
1106
|
currentPkg.dependencyLockfile &&
|
|
1075
1107
|
currentPkg.name &&
|
|
1076
1108
|
await pathExists(path.join(ctx.virtualStoreDir, dp.depPathToFilename(currentPkg.depPath, ctx.virtualStoreDirMaxLength), 'node_modules', currentPkg.name, 'package.json')));
|
|
1077
|
-
if (!options.update && !options.proceed &&
|
|
1109
|
+
if (!options.update && !options.proceed &&
|
|
1110
|
+
options.currentDepth === Math.max(0, options.updateDepth) &&
|
|
1111
|
+
(currentPkg.resolution != null) && depIsLinked) {
|
|
1078
1112
|
return null;
|
|
1079
1113
|
}
|
|
1080
1114
|
let pkgResponse;
|
package/lib/resolvePeers.js
CHANGED
|
@@ -7,12 +7,16 @@ import pDefer, {} from 'p-defer';
|
|
|
7
7
|
import { partition, pick } from 'ramda';
|
|
8
8
|
import semver from 'semver';
|
|
9
9
|
import { dedupeInjectedDeps } from './dedupeInjectedDeps.js';
|
|
10
|
+
import { isCompatibleAndHasMoreDeps, nodeDepsCount } from './depPathCompatibility.js';
|
|
10
11
|
import { linkPathToPeerVersion } from './linkPathToPeerVersion.js';
|
|
11
12
|
import { mergePeers } from './mergePeers.js';
|
|
12
13
|
export async function resolvePeers(opts) {
|
|
13
14
|
const depGraph = {};
|
|
14
15
|
const pathsByNodeId = new Map();
|
|
15
16
|
const pathsByNodeIdPromises = new Map();
|
|
17
|
+
const awaitedPeerNodeIdsByNodeId = new Map();
|
|
18
|
+
const peersCacheOwnerByNodeId = new Map();
|
|
19
|
+
const cycleBrokenNodeIds = new Set();
|
|
16
20
|
const depPathsByPkgId = new Map();
|
|
17
21
|
const nodeIdsByPreviousDepPath = opts.resolvedPeerProviderPaths == null
|
|
18
22
|
? new Map()
|
|
@@ -76,6 +80,9 @@ export async function resolvePeers(opts) {
|
|
|
76
80
|
parentDepPathsChain: [],
|
|
77
81
|
pathsByNodeId,
|
|
78
82
|
pathsByNodeIdPromises,
|
|
83
|
+
awaitedPeerNodeIdsByNodeId,
|
|
84
|
+
peersCacheOwnerByNodeId,
|
|
85
|
+
cycleBrokenNodeIds,
|
|
79
86
|
depPathsByPkgId,
|
|
80
87
|
nodeIdsByPreviousDepPath,
|
|
81
88
|
resolvedPeerProviderPaths: opts.resolvedPeerProviderPaths,
|
|
@@ -102,6 +109,9 @@ export async function resolvePeers(opts) {
|
|
|
102
109
|
// its cycle analysis only sees the children of one call, and providers
|
|
103
110
|
// frequently peer-depend on each other, so resolving them one by one
|
|
104
111
|
// would leave their dep path calculations awaiting each other forever.
|
|
112
|
+
// A peer cycle that spans this call and the traversal above is still
|
|
113
|
+
// invisible here; breakDepPathAwaitCycles resolves those before the
|
|
114
|
+
// finishing promises are awaited.
|
|
105
115
|
const prunedProviderChildren = {};
|
|
106
116
|
for (const [alias, nodeId] of Object.entries(hoistedProviderChildren)) {
|
|
107
117
|
if (parentPkgsOfNode.has(nodeId))
|
|
@@ -122,6 +132,14 @@ export async function resolvePeers(opts) {
|
|
|
122
132
|
};
|
|
123
133
|
}
|
|
124
134
|
}
|
|
135
|
+
breakDepPathAwaitCycles({
|
|
136
|
+
awaitedPeerNodeIdsByNodeId,
|
|
137
|
+
peersCacheOwnerByNodeId,
|
|
138
|
+
cycleBrokenNodeIds,
|
|
139
|
+
pathsByNodeId,
|
|
140
|
+
pathsByNodeIdPromises,
|
|
141
|
+
dependenciesTree: opts.dependenciesTree,
|
|
142
|
+
});
|
|
125
143
|
await Promise.all(finishingList);
|
|
126
144
|
const depGraphWithResolvedChildren = resolveChildren(depGraph);
|
|
127
145
|
function resolveChildren(depGraph) {
|
|
@@ -168,8 +186,61 @@ export async function resolvePeers(opts) {
|
|
|
168
186
|
pathsByNodeId,
|
|
169
187
|
};
|
|
170
188
|
}
|
|
171
|
-
|
|
172
|
-
|
|
189
|
+
// Cycle analysis inside resolvePeersOfChildren only sees the children of a
|
|
190
|
+
// single call, but a dep path calculation may await a node resolved in a
|
|
191
|
+
// different call or at a different tree level (a hoisted peer provider and
|
|
192
|
+
// a consumer that peer-depend on each other, https://github.com/pnpm/pnpm/issues/12921).
|
|
193
|
+
// Such an await cycle never settles on its own, so before the finishing
|
|
194
|
+
// promises are awaited, walk the recorded await edges and resolve every
|
|
195
|
+
// dep path promise on a cycle to the peer's `name@version` — the same
|
|
196
|
+
// collapse in-call cycle detection applies (see calculateDepPath).
|
|
197
|
+
// A node that hit the peers cache awaits its dep path from the node that
|
|
198
|
+
// created the cache entry, so it borrows that owner's await edges.
|
|
199
|
+
function breakDepPathAwaitCycles(opts) {
|
|
200
|
+
const isSettled = (nodeId) => opts.pathsByNodeId.has(nodeId) || opts.cycleBrokenNodeIds.has(nodeId);
|
|
201
|
+
const keysByNodeId = new Map();
|
|
202
|
+
const nodeIdsByKey = new Map();
|
|
203
|
+
function keyOf(nodeId) {
|
|
204
|
+
let key = keysByNodeId.get(nodeId);
|
|
205
|
+
if (key == null) {
|
|
206
|
+
key = String(keysByNodeId.size);
|
|
207
|
+
keysByNodeId.set(nodeId, key);
|
|
208
|
+
nodeIdsByKey.set(key, nodeId);
|
|
209
|
+
}
|
|
210
|
+
return key;
|
|
211
|
+
}
|
|
212
|
+
const graphEntries = [];
|
|
213
|
+
const awaitingNodeIds = new Set([
|
|
214
|
+
...opts.awaitedPeerNodeIdsByNodeId.keys(),
|
|
215
|
+
...opts.peersCacheOwnerByNodeId.keys(),
|
|
216
|
+
]);
|
|
217
|
+
for (const nodeId of awaitingNodeIds) {
|
|
218
|
+
if (isSettled(nodeId))
|
|
219
|
+
continue;
|
|
220
|
+
const cacheOwnerNodeId = opts.peersCacheOwnerByNodeId.get(nodeId);
|
|
221
|
+
const awaitedNodeIds = opts.awaitedPeerNodeIdsByNodeId.get(nodeId) ??
|
|
222
|
+
(cacheOwnerNodeId == null ? undefined : opts.awaitedPeerNodeIdsByNodeId.get(cacheOwnerNodeId));
|
|
223
|
+
if (awaitedNodeIds == null)
|
|
224
|
+
continue;
|
|
225
|
+
const liveTargets = [];
|
|
226
|
+
for (const awaitedNodeId of awaitedNodeIds) {
|
|
227
|
+
if (!isSettled(awaitedNodeId)) {
|
|
228
|
+
liveTargets.push(keyOf(awaitedNodeId));
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
if (liveTargets.length > 0) {
|
|
232
|
+
graphEntries.push([keyOf(nodeId), liveTargets]);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
if (graphEntries.length === 0)
|
|
236
|
+
return;
|
|
237
|
+
const { cycles } = analyzeGraph(graphEntries);
|
|
238
|
+
for (const key of new Set(cycles.flat())) {
|
|
239
|
+
const nodeId = nodeIdsByKey.get(key);
|
|
240
|
+
const { name, version } = opts.dependenciesTree.get(nodeId).resolvedPackage;
|
|
241
|
+
opts.cycleBrokenNodeIds.add(nodeId);
|
|
242
|
+
opts.pathsByNodeIdPromises.get(nodeId)?.resolve(`${name}@${version}`);
|
|
243
|
+
}
|
|
173
244
|
}
|
|
174
245
|
function deduplicateAll(depGraph, duplicates) {
|
|
175
246
|
const { depPathsMap, remainingDuplicates } = deduplicateDepPaths(duplicates, depGraph);
|
|
@@ -234,21 +305,6 @@ function deduplicateDepPaths(duplicates, depGraph) {
|
|
|
234
305
|
remainingDuplicates,
|
|
235
306
|
};
|
|
236
307
|
}
|
|
237
|
-
function isCompatibleAndHasMoreDeps(depGraph, depPath1, depPath2) {
|
|
238
|
-
const node1 = depGraph[depPath1];
|
|
239
|
-
const node2 = depGraph[depPath2];
|
|
240
|
-
if (nodeDepsCount(node1) < nodeDepsCount(node2))
|
|
241
|
-
return false;
|
|
242
|
-
const node1DepPathsSet = new Set(Object.values(node1.children));
|
|
243
|
-
const node2DepPaths = Object.values(node2.children);
|
|
244
|
-
if (!node2DepPaths.every((depPath) => node1DepPathsSet.has(depPath)))
|
|
245
|
-
return false;
|
|
246
|
-
for (const depPath of node2.resolvedPeerNames) {
|
|
247
|
-
if (!node1.resolvedPeerNames.has(depPath))
|
|
248
|
-
return false;
|
|
249
|
-
}
|
|
250
|
-
return true;
|
|
251
|
-
}
|
|
252
308
|
function createPkgsByName(dependenciesTree, { directNodeIdsByAlias, topParents }) {
|
|
253
309
|
const parentRefs = toPkgByName(Array.from(directNodeIdsByAlias.entries())
|
|
254
310
|
.map(([alias, nodeId]) => ({
|
|
@@ -389,6 +445,7 @@ async function resolvePeersOfNode(currentAlias, nodeId, parentParentPkgs, ctx) {
|
|
|
389
445
|
wantedRange,
|
|
390
446
|
});
|
|
391
447
|
}
|
|
448
|
+
ctx.peersCacheOwnerByNodeId.set(nodeId, hit.ownerNodeId);
|
|
392
449
|
return {
|
|
393
450
|
missingPeers: hit.missingPeers,
|
|
394
451
|
finishing: (async () => {
|
|
@@ -451,6 +508,7 @@ async function resolvePeersOfNode(currentAlias, nodeId, parentParentPkgs, ctx) {
|
|
|
451
508
|
missingPeers: allMissingPeers,
|
|
452
509
|
depPath: pDefer(),
|
|
453
510
|
resolvedPeers: allResolvedPeers,
|
|
511
|
+
ownerNodeId: nodeId,
|
|
454
512
|
};
|
|
455
513
|
if (ctx.peersCache.has(resolvedPackage.pkgIdWithPatchHash)) {
|
|
456
514
|
ctx.peersCache.get(resolvedPackage.pkgIdWithPatchHash).push(cache);
|
|
@@ -512,6 +570,7 @@ async function resolvePeersOfNode(currentAlias, nodeId, parentParentPkgs, ctx) {
|
|
|
512
570
|
if (cyclicPeerAliases.has(pendingPeer.alias)) {
|
|
513
571
|
const { name, version } = ctx.dependenciesTree.get(pendingPeer.nodeId)?.resolvedPackage;
|
|
514
572
|
const id = `${name}@${version}`;
|
|
573
|
+
ctx.cycleBrokenNodeIds.add(pendingPeer.nodeId);
|
|
515
574
|
ctx.pathsByNodeIdPromises.get(pendingPeer.nodeId)?.resolve(id);
|
|
516
575
|
return id;
|
|
517
576
|
}
|
|
@@ -521,6 +580,12 @@ async function resolvePeersOfNode(currentAlias, nodeId, parentParentPkgs, ctx) {
|
|
|
521
580
|
return { name: peerNode.resolvedPackage.name, version: peerNode.resolvedPackage.version };
|
|
522
581
|
}
|
|
523
582
|
}
|
|
583
|
+
let awaitedPeerNodeIds = ctx.awaitedPeerNodeIdsByNodeId.get(nodeId);
|
|
584
|
+
if (awaitedPeerNodeIds == null) {
|
|
585
|
+
awaitedPeerNodeIds = new Set();
|
|
586
|
+
ctx.awaitedPeerNodeIdsByNodeId.set(nodeId, awaitedPeerNodeIds);
|
|
587
|
+
}
|
|
588
|
+
awaitedPeerNodeIds.add(pendingPeer.nodeId);
|
|
524
589
|
return ctx.pathsByNodeIdPromises.get(pendingPeer.nodeId).promise;
|
|
525
590
|
})),
|
|
526
591
|
], ctx.peersSuffixMaxLength);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pnpm/installing.deps-resolver",
|
|
3
|
-
"version": "1100.2.
|
|
3
|
+
"version": "1100.2.9",
|
|
4
4
|
"description": "Resolves dependency graph of a package",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pnpm",
|
|
@@ -27,7 +27,32 @@
|
|
|
27
27
|
"!*.map"
|
|
28
28
|
],
|
|
29
29
|
"dependencies": {
|
|
30
|
+
"@pnpm/catalogs.resolver": "1100.0.0",
|
|
31
|
+
"@pnpm/catalogs.types": "1100.0.0",
|
|
32
|
+
"@pnpm/config.version-policy": "1100.1.7",
|
|
33
|
+
"@pnpm/constants": "1100.0.0",
|
|
34
|
+
"@pnpm/core-loggers": "1100.2.2",
|
|
35
|
+
"@pnpm/deps.graph-hasher": "1100.2.10",
|
|
36
|
+
"@pnpm/deps.path": "1100.0.9",
|
|
37
|
+
"@pnpm/deps.peer-range": "1100.0.2",
|
|
38
|
+
"@pnpm/error": "1100.0.1",
|
|
39
|
+
"@pnpm/fetching.pick-fetcher": "1100.1.1",
|
|
40
|
+
"@pnpm/fs.symlink-dependency": "1100.0.11",
|
|
41
|
+
"@pnpm/hooks.types": "1100.2.1",
|
|
42
|
+
"@pnpm/lockfile.preferred-versions": "1100.0.20",
|
|
43
|
+
"@pnpm/lockfile.pruner": "1100.0.14",
|
|
44
|
+
"@pnpm/lockfile.types": "1100.0.14",
|
|
45
|
+
"@pnpm/lockfile.utils": "1100.1.3",
|
|
46
|
+
"@pnpm/patching.config": "1100.0.10",
|
|
47
|
+
"@pnpm/patching.types": "1100.0.0",
|
|
48
|
+
"@pnpm/pkg-manifest.reader": "1100.0.10",
|
|
49
|
+
"@pnpm/pkg-manifest.utils": "1100.2.7",
|
|
50
|
+
"@pnpm/resolving.npm-resolver": "1102.1.3",
|
|
51
|
+
"@pnpm/resolving.resolver-base": "1100.5.2",
|
|
52
|
+
"@pnpm/store.controller-types": "1100.1.8",
|
|
53
|
+
"@pnpm/types": "1101.4.0",
|
|
30
54
|
"@pnpm/util.lex-comparator": "^4.0.1",
|
|
55
|
+
"@pnpm/workspace.spec-parser": "1100.0.0",
|
|
31
56
|
"@yarnpkg/core": "4.8.0",
|
|
32
57
|
"graph-cycles": "3.0.0",
|
|
33
58
|
"is-inner-link": "^5.0.0",
|
|
@@ -42,44 +67,19 @@
|
|
|
42
67
|
"semver": "^7.8.4",
|
|
43
68
|
"semver-range-intersect": "^0.3.1",
|
|
44
69
|
"validate-npm-package-name": "7.0.2",
|
|
45
|
-
"version-selector-type": "^3.0.0"
|
|
46
|
-
"@pnpm/catalogs.resolver": "1100.0.0",
|
|
47
|
-
"@pnpm/config.version-policy": "1100.1.6",
|
|
48
|
-
"@pnpm/catalogs.types": "1100.0.0",
|
|
49
|
-
"@pnpm/constants": "1100.0.0",
|
|
50
|
-
"@pnpm/deps.graph-hasher": "1100.2.8",
|
|
51
|
-
"@pnpm/core-loggers": "1100.2.1",
|
|
52
|
-
"@pnpm/deps.peer-range": "1100.0.2",
|
|
53
|
-
"@pnpm/deps.path": "1100.0.8",
|
|
54
|
-
"@pnpm/error": "1100.0.1",
|
|
55
|
-
"@pnpm/fetching.pick-fetcher": "1100.0.14",
|
|
56
|
-
"@pnpm/hooks.types": "1100.1.1",
|
|
57
|
-
"@pnpm/lockfile.preferred-versions": "1100.0.18",
|
|
58
|
-
"@pnpm/lockfile.pruner": "1100.0.13",
|
|
59
|
-
"@pnpm/fs.symlink-dependency": "1100.0.10",
|
|
60
|
-
"@pnpm/lockfile.types": "1100.0.13",
|
|
61
|
-
"@pnpm/lockfile.utils": "1100.1.1",
|
|
62
|
-
"@pnpm/patching.types": "1100.0.0",
|
|
63
|
-
"@pnpm/pkg-manifest.reader": "1100.0.9",
|
|
64
|
-
"@pnpm/pkg-manifest.utils": "1100.2.6",
|
|
65
|
-
"@pnpm/resolving.npm-resolver": "1102.1.2",
|
|
66
|
-
"@pnpm/resolving.resolver-base": "1100.5.1",
|
|
67
|
-
"@pnpm/store.controller-types": "1100.1.7",
|
|
68
|
-
"@pnpm/types": "1101.3.2",
|
|
69
|
-
"@pnpm/patching.config": "1100.0.9",
|
|
70
|
-
"@pnpm/workspace.spec-parser": "1100.0.0"
|
|
70
|
+
"version-selector-type": "^3.0.0"
|
|
71
71
|
},
|
|
72
72
|
"peerDependencies": {
|
|
73
73
|
"@pnpm/logger": "^1100.0.0"
|
|
74
74
|
},
|
|
75
75
|
"devDependencies": {
|
|
76
76
|
"@jest/globals": "30.4.1",
|
|
77
|
+
"@pnpm/installing.deps-resolver": "1100.2.9",
|
|
78
|
+
"@pnpm/logger": "1100.0.0",
|
|
77
79
|
"@types/normalize-path": "^3.0.2",
|
|
78
80
|
"@types/ramda": "0.31.1",
|
|
79
81
|
"@types/semver": "7.7.1",
|
|
80
|
-
"@types/validate-npm-package-name": "^4.0.2"
|
|
81
|
-
"@pnpm/installing.deps-resolver": "1100.2.7",
|
|
82
|
-
"@pnpm/logger": "1100.0.0"
|
|
82
|
+
"@types/validate-npm-package-name": "^4.0.2"
|
|
83
83
|
},
|
|
84
84
|
"engines": {
|
|
85
85
|
"node": ">=22.13"
|