@pnpm/installing.deps-resolver 1100.1.6 → 1100.2.0
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/lib/index.js +28 -2
- package/lib/resolveDependencies.d.ts +14 -2
- package/lib/resolveDependencies.js +33 -0
- package/lib/resolveDependencyTree.js +2 -0
- package/lib/resolvePeers.d.ts +4 -0
- package/lib/resolvePeers.js +99 -7
- package/package.json +25 -22
package/lib/index.js
CHANGED
|
@@ -84,7 +84,14 @@ export async function resolveDependencies(importers, opts) {
|
|
|
84
84
|
}
|
|
85
85
|
return {
|
|
86
86
|
binsDir: project.binsDir,
|
|
87
|
+
declaredDirectDependencies: new Set([
|
|
88
|
+
...Object.keys(project.manifest == null ? {} : getAllDependenciesFromManifest(project.manifest)),
|
|
89
|
+
...project.wantedDependencies.flatMap(({ alias, isNew }) => isNew && alias != null ? [alias] : []),
|
|
90
|
+
]),
|
|
87
91
|
directNodeIdsByAlias: resolvedImporter.directNodeIdsByAlias,
|
|
92
|
+
explicitlyRequestedDirectDependencies: new Set(project.wantedDependencies.flatMap(({ alias, bareSpecifier, isNew, prevSpecifier, updateSpec }) => alias != null && (isNew === true || updateSpec === true || (prevSpecifier != null && bareSpecifier !== prevSpecifier))
|
|
93
|
+
? [alias]
|
|
94
|
+
: [])),
|
|
88
95
|
id: project.id,
|
|
89
96
|
linkedDependencies: resolvedImporter.linkedDependencies,
|
|
90
97
|
manifest: project.manifest,
|
|
@@ -93,7 +100,7 @@ export async function resolveDependencies(importers, opts) {
|
|
|
93
100
|
topParents,
|
|
94
101
|
};
|
|
95
102
|
}));
|
|
96
|
-
const
|
|
103
|
+
const peerResolutionOpts = {
|
|
97
104
|
allPeerDepNames,
|
|
98
105
|
dependenciesTree,
|
|
99
106
|
dedupePeerDependents: opts.dedupePeerDependents,
|
|
@@ -107,7 +114,19 @@ export async function resolveDependencies(importers, opts) {
|
|
|
107
114
|
resolvedImporters,
|
|
108
115
|
peersSuffixMaxLength: opts.peersSuffixMaxLength,
|
|
109
116
|
workspaceProjectIds: new Set([...opts.allProjectIds, ...Object.keys(opts.wantedLockfile.importers)]),
|
|
110
|
-
}
|
|
117
|
+
};
|
|
118
|
+
const initiallyResolvedPeers = await resolvePeers(peerResolutionOpts);
|
|
119
|
+
// A second pass reuses the peer contexts already recorded in the lockfile so a
|
|
120
|
+
// writable install does not rewrite dependency instances whose locked provider
|
|
121
|
+
// is still valid and present. It can only differ from the first pass for nodes
|
|
122
|
+
// that carry a locked peer context, so it is skipped when none do (e.g. a fresh
|
|
123
|
+
// install) to avoid resolving peers twice for no benefit.
|
|
124
|
+
const { dependenciesGraph, dependenciesByProjectId, peerDependencyIssuesByProjects, } = treeHasLockedPeerContexts(dependenciesTree)
|
|
125
|
+
? await resolvePeers({
|
|
126
|
+
...peerResolutionOpts,
|
|
127
|
+
resolvedPeerProviderPaths: initiallyResolvedPeers.pathsByNodeId,
|
|
128
|
+
})
|
|
129
|
+
: initiallyResolvedPeers;
|
|
111
130
|
const linkedDependenciesByProjectId = {};
|
|
112
131
|
await Promise.all(projectsToResolve.map(async (project, index) => {
|
|
113
132
|
const resolvedImporter = resolvedImporters[project.id];
|
|
@@ -237,6 +256,13 @@ export async function resolveDependencies(importers, opts) {
|
|
|
237
256
|
resolutionPolicyViolations,
|
|
238
257
|
};
|
|
239
258
|
}
|
|
259
|
+
function treeHasLockedPeerContexts(dependenciesTree) {
|
|
260
|
+
for (const node of dependenciesTree.values()) {
|
|
261
|
+
if (node.lockedPeerContext != null)
|
|
262
|
+
return true;
|
|
263
|
+
}
|
|
264
|
+
return false;
|
|
265
|
+
}
|
|
240
266
|
function addDirectDependenciesToLockfile(newManifest, projectSnapshot, linkedPackages, directDependencies, excludeLinksFromLockfile) {
|
|
241
267
|
const newProjectSnapshot = {
|
|
242
268
|
dependencies: {},
|
|
@@ -4,7 +4,7 @@ import { type PatchGroupRecord } from '@pnpm/patching.config';
|
|
|
4
4
|
import type { PatchInfo } from '@pnpm/patching.types';
|
|
5
5
|
import { type DirectoryResolution, type PkgResolutionId, type PreferredVersions, type Resolution, type ResolutionPolicyViolation, type WorkspacePackages } from '@pnpm/resolving.resolver-base';
|
|
6
6
|
import type { PackageResponse, PkgRequestFetchResult, StoreController } from '@pnpm/store.controller-types';
|
|
7
|
-
import type { AllowBuild, AllowedDeprecatedVersions, PackageManifest, PackageVersionPolicy, PinnedVersion, PkgIdWithPatchHash, ReadPackageHook, Registries, SupportedArchitectures, TrustPolicy } from '@pnpm/types';
|
|
7
|
+
import type { AllowBuild, AllowedDeprecatedVersions, DepPath, PackageManifest, PackageVersionPolicy, PinnedVersion, PkgIdWithPatchHash, ReadPackageHook, Registries, SupportedArchitectures, TrustPolicy } from '@pnpm/types';
|
|
8
8
|
import { type WantedDependency } from './getNonDevWantedDependencies.js';
|
|
9
9
|
import { type NodeId } from './nextNodeId.js';
|
|
10
10
|
import type { CatalogLookupMetadata } from './resolveDependencyTree.js';
|
|
@@ -20,6 +20,9 @@ export interface ChildrenMap {
|
|
|
20
20
|
export type DependenciesTreeNode<T> = {
|
|
21
21
|
children: (() => ChildrenMap) | ChildrenMap;
|
|
22
22
|
installable: boolean;
|
|
23
|
+
dependencyNamesWhoseCurrentProviderMustWin?: Set<string>;
|
|
24
|
+
lockedPeerContext?: LockedPeerContext;
|
|
25
|
+
previousDepPath?: DepPath;
|
|
23
26
|
} & ({
|
|
24
27
|
resolvedPackage: T & {
|
|
25
28
|
name: string;
|
|
@@ -56,6 +59,8 @@ export interface PendingNode {
|
|
|
56
59
|
resolvedPackage: ResolvedPackage;
|
|
57
60
|
depth: number;
|
|
58
61
|
installable: boolean;
|
|
62
|
+
lockedPeerContext?: LockedPeerContext;
|
|
63
|
+
previousDepPath?: DepPath;
|
|
59
64
|
parentIds: PkgResolutionId[];
|
|
60
65
|
}
|
|
61
66
|
export interface ChildrenByParentId {
|
|
@@ -153,6 +158,8 @@ export interface PkgAddress extends PkgAddressOrLinkBase {
|
|
|
153
158
|
missingPeersOfChildren?: MissingPeersOfChildren;
|
|
154
159
|
publishedAt?: string;
|
|
155
160
|
saveCatalogName?: string;
|
|
161
|
+
lockedPeerContext?: LockedPeerContext;
|
|
162
|
+
previousDepPath?: DepPath;
|
|
156
163
|
}
|
|
157
164
|
export type PkgAddressOrLink = PkgAddress | LinkedDependency;
|
|
158
165
|
export interface PeerDependency {
|
|
@@ -192,7 +199,7 @@ export interface ResolvedPackage {
|
|
|
192
199
|
libc?: string[];
|
|
193
200
|
};
|
|
194
201
|
}
|
|
195
|
-
type ParentPkg = Pick<PkgAddress, 'nodeId' | 'installable' | 'rootDir' | 'optional' | 'pkgId' | 'resolvedVia'>;
|
|
202
|
+
type ParentPkg = Pick<PkgAddress, 'nodeId' | 'installable' | 'rootDir' | 'optional' | 'pkgId' | 'resolvedVia' | 'lockedPeerContext' | 'previousDepPath'>;
|
|
196
203
|
export type ParentPkgAliases = Record<string, PkgAddress | true>;
|
|
197
204
|
export type UpdateMatchingFunction = (pkgName: string, version?: string) => boolean;
|
|
198
205
|
interface ResolvedDependenciesOptions {
|
|
@@ -245,9 +252,14 @@ export declare function resolveDependencies(ctx: ResolutionContext, preferredVer
|
|
|
245
252
|
updateDepth?: number;
|
|
246
253
|
}>, options: ResolvedDependenciesOptions): Promise<ResolvedDependenciesResult>;
|
|
247
254
|
export declare function createNodeIdForLinkedLocalPkg(lockfileDir: string, pkgDir: string): NodeId;
|
|
255
|
+
export interface LockedPeerContext {
|
|
256
|
+
[peerName: string]: DepPath;
|
|
257
|
+
}
|
|
248
258
|
type InfoFromLockfile = {
|
|
259
|
+
depPath: DepPath;
|
|
249
260
|
pkgId: PkgResolutionId;
|
|
250
261
|
dependencyLockfile?: PackageSnapshot;
|
|
262
|
+
lockedPeerContext?: LockedPeerContext;
|
|
251
263
|
name?: string;
|
|
252
264
|
version?: string;
|
|
253
265
|
resolution?: Resolution;
|
|
@@ -505,6 +505,10 @@ async function resolveDependenciesOfDependency(ctx, preferredVersions, options,
|
|
|
505
505
|
});
|
|
506
506
|
return { resolveDependencyResult };
|
|
507
507
|
}
|
|
508
|
+
if (update === false && extendedWantedDep.infoFromLockfile != null) {
|
|
509
|
+
resolveDependencyResult.previousDepPath = extendedWantedDep.infoFromLockfile.depPath;
|
|
510
|
+
resolveDependencyResult.lockedPeerContext = extendedWantedDep.infoFromLockfile.lockedPeerContext;
|
|
511
|
+
}
|
|
508
512
|
if (!resolveDependencyResult.isNew) {
|
|
509
513
|
return {
|
|
510
514
|
resolveDependencyResult,
|
|
@@ -600,6 +604,17 @@ async function resolveChildren(ctx, { parentPkg, parentIds, dependencyLockfile,
|
|
|
600
604
|
}, {}),
|
|
601
605
|
depth: parentDepth,
|
|
602
606
|
installable: parentPkg.installable,
|
|
607
|
+
dependencyNamesWhoseCurrentProviderMustWin: new Set(pkgAddresses
|
|
608
|
+
.filter((child) => {
|
|
609
|
+
const previousRef = dependencyLockfile?.dependencies?.[child.alias] ??
|
|
610
|
+
dependencyLockfile?.optionalDependencies?.[child.alias];
|
|
611
|
+
if (previousRef == null || child.isLinkedDependency)
|
|
612
|
+
return true;
|
|
613
|
+
return child.previousDepPath !== dp.refToRelative(previousRef, child.alias);
|
|
614
|
+
})
|
|
615
|
+
.map(({ alias }) => alias)),
|
|
616
|
+
lockedPeerContext: parentPkg.lockedPeerContext,
|
|
617
|
+
previousDepPath: parentPkg.previousDepPath,
|
|
603
618
|
resolvedPackage: ctx.resolvedPkgsById[parentPkg.pkgId],
|
|
604
619
|
});
|
|
605
620
|
return resolvingPeers;
|
|
@@ -678,6 +693,18 @@ function referenceSatisfiesWantedSpec(opts, wantedDep, preferredRef) {
|
|
|
678
693
|
}
|
|
679
694
|
return semver.satisfies(version, wantedDep.bareSpecifier, true);
|
|
680
695
|
}
|
|
696
|
+
function getLockedPeerContext(dependencyLockfile) {
|
|
697
|
+
if (dependencyLockfile.peerDependencies == null)
|
|
698
|
+
return undefined;
|
|
699
|
+
const lockedPeerContext = {};
|
|
700
|
+
for (const peerName of Object.keys(dependencyLockfile.peerDependencies)) {
|
|
701
|
+
const ref = dependencyLockfile.dependencies?.[peerName] ?? dependencyLockfile.optionalDependencies?.[peerName];
|
|
702
|
+
const depPath = ref == null ? null : dp.refToRelative(ref, peerName);
|
|
703
|
+
if (depPath != null)
|
|
704
|
+
lockedPeerContext[peerName] = depPath;
|
|
705
|
+
}
|
|
706
|
+
return Object.keys(lockedPeerContext).length === 0 ? undefined : lockedPeerContext;
|
|
707
|
+
}
|
|
681
708
|
function getInfoFromLockfile(lockfile, registries, reference, alias) {
|
|
682
709
|
if (!reference || !alias) {
|
|
683
710
|
return undefined;
|
|
@@ -688,6 +715,7 @@ function getInfoFromLockfile(lockfile, registries, reference, alias) {
|
|
|
688
715
|
}
|
|
689
716
|
let dependencyLockfile = lockfile.packages?.[depPath];
|
|
690
717
|
if (dependencyLockfile != null) {
|
|
718
|
+
const lockedPeerContext = getLockedPeerContext(dependencyLockfile);
|
|
691
719
|
if ((dependencyLockfile.peerDependencies != null) && (dependencyLockfile.dependencies != null)) {
|
|
692
720
|
// This is done to guarantee that the dependency will be relinked with the
|
|
693
721
|
// up-to-date peer dependencies
|
|
@@ -705,9 +733,11 @@ function getInfoFromLockfile(lockfile, registries, reference, alias) {
|
|
|
705
733
|
}
|
|
706
734
|
const { name, version, nonSemverVersion } = nameVerFromPkgSnapshot(depPath, dependencyLockfile);
|
|
707
735
|
return {
|
|
736
|
+
depPath,
|
|
708
737
|
name,
|
|
709
738
|
version,
|
|
710
739
|
dependencyLockfile,
|
|
740
|
+
lockedPeerContext,
|
|
711
741
|
pkgId: nonSemverVersion ?? `${name}@${version}`,
|
|
712
742
|
// resolution may not exist if lockfile is broken, and an unexpected error will be thrown
|
|
713
743
|
// if resolution does not exist, return undefined so it can be autofixed later
|
|
@@ -717,6 +747,7 @@ function getInfoFromLockfile(lockfile, registries, reference, alias) {
|
|
|
717
747
|
else {
|
|
718
748
|
const parsed = dp.parse(depPath);
|
|
719
749
|
return {
|
|
750
|
+
depPath,
|
|
720
751
|
pkgId: parsed.nonSemverVersion ?? (parsed.name && parsed.version ? `${parsed.name}@${parsed.version}` : depPath), // Does it make sense to set pkgId when we're not sure?
|
|
721
752
|
};
|
|
722
753
|
}
|
|
@@ -1027,6 +1058,8 @@ async function resolveDependency(wantedDependency, ctx, options) {
|
|
|
1027
1058
|
depth: options.currentDepth,
|
|
1028
1059
|
parentIds: options.parentIds,
|
|
1029
1060
|
installable,
|
|
1061
|
+
lockedPeerContext: currentPkg.lockedPeerContext,
|
|
1062
|
+
previousDepPath: currentPkg.depPath,
|
|
1030
1063
|
nodeId,
|
|
1031
1064
|
resolvedPackage: ctx.resolvedPkgsById[pkgResponse.body.id],
|
|
1032
1065
|
});
|
|
@@ -132,6 +132,8 @@ export async function resolveDependencyTree(importers, opts) {
|
|
|
132
132
|
children: () => buildTree(ctx, pendingNode.resolvedPackage.id, pendingNode.parentIds, ctx.childrenByParentId[pendingNode.resolvedPackage.id], pendingNode.depth + 1, pendingNode.installable),
|
|
133
133
|
depth: pendingNode.depth,
|
|
134
134
|
installable: pendingNode.installable,
|
|
135
|
+
lockedPeerContext: pendingNode.lockedPeerContext,
|
|
136
|
+
previousDepPath: pendingNode.previousDepPath,
|
|
135
137
|
resolvedPackage: pendingNode.resolvedPackage,
|
|
136
138
|
});
|
|
137
139
|
}
|
package/lib/resolvePeers.d.ts
CHANGED
|
@@ -30,6 +30,8 @@ export interface GenericDependenciesGraphWithResolvedChildren<T extends PartialR
|
|
|
30
30
|
}
|
|
31
31
|
export interface ProjectToResolve {
|
|
32
32
|
directNodeIdsByAlias: Map<string, NodeId>;
|
|
33
|
+
declaredDirectDependencies?: Set<string>;
|
|
34
|
+
explicitlyRequestedDirectDependencies?: Set<string>;
|
|
33
35
|
topParents: Array<{
|
|
34
36
|
name: string;
|
|
35
37
|
version: string;
|
|
@@ -53,8 +55,10 @@ export declare function resolvePeers<T extends PartialResolvedPackage>(opts: {
|
|
|
53
55
|
resolvedImporters: ResolvedImporters;
|
|
54
56
|
peersSuffixMaxLength: number;
|
|
55
57
|
workspaceProjectIds: Set<string>;
|
|
58
|
+
resolvedPeerProviderPaths?: Map<NodeId, DepPath>;
|
|
56
59
|
}): Promise<{
|
|
57
60
|
dependenciesGraph: GenericDependenciesGraphWithResolvedChildren<T>;
|
|
58
61
|
dependenciesByProjectId: DependenciesByProjectId;
|
|
59
62
|
peerDependencyIssuesByProjects: PeerDependencyIssuesByProjects;
|
|
63
|
+
pathsByNodeId: Map<NodeId, DepPath>;
|
|
60
64
|
}>;
|
package/lib/resolvePeers.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
|
-
import { createPeerDepGraphHash, depPathToFilename } from '@pnpm/deps.path';
|
|
2
|
+
import { createPeerDepGraphHash, depPathToFilename, parseDepPath } from '@pnpm/deps.path';
|
|
3
3
|
import * as semverUtils from '@yarnpkg/core/semverUtils';
|
|
4
4
|
import { analyzeGraph } from 'graph-cycles';
|
|
5
5
|
import pDefer, {} from 'p-defer';
|
|
@@ -13,13 +13,31 @@ export async function resolvePeers(opts) {
|
|
|
13
13
|
const pathsByNodeId = new Map();
|
|
14
14
|
const pathsByNodeIdPromises = new Map();
|
|
15
15
|
const depPathsByPkgId = new Map();
|
|
16
|
+
const nodeIdsByPreviousDepPath = opts.resolvedPeerProviderPaths == null
|
|
17
|
+
? new Map()
|
|
18
|
+
: getNodeIdsByPreviousDepPath(opts.dependenciesTree);
|
|
16
19
|
const _createPkgsByName = createPkgsByName.bind(null, opts.dependenciesTree);
|
|
17
|
-
const
|
|
20
|
+
const workspaceRootProject = opts.resolvePeersFromWorkspaceRoot && opts.projects.length > 1
|
|
21
|
+
? opts.projects.find(({ id }) => id === '.')
|
|
22
|
+
: undefined;
|
|
23
|
+
const rootPkgsByName = workspaceRootProject == null ? {} : _createPkgsByName(workspaceRootProject);
|
|
18
24
|
const peerDependencyIssuesByProjects = {};
|
|
19
25
|
const finishingList = [];
|
|
20
26
|
const peersCache = new Map();
|
|
21
27
|
const purePkgs = new Set();
|
|
22
|
-
for (const { directNodeIdsByAlias, topParents, rootDir, id } of opts.projects) {
|
|
28
|
+
for (const { directNodeIdsByAlias, declaredDirectDependencies, explicitlyRequestedDirectDependencies, topParents, rootDir, id } of opts.projects) {
|
|
29
|
+
const currentProviderSources = [{
|
|
30
|
+
directNodeIdsByAlias,
|
|
31
|
+
declaredDirectDependencies: declaredDirectDependencies ?? new Set(),
|
|
32
|
+
explicitlyRequestedDirectDependencies: explicitlyRequestedDirectDependencies ?? new Set(),
|
|
33
|
+
}];
|
|
34
|
+
if (workspaceRootProject != null && workspaceRootProject.id !== id) {
|
|
35
|
+
currentProviderSources.push({
|
|
36
|
+
directNodeIdsByAlias: workspaceRootProject.directNodeIdsByAlias,
|
|
37
|
+
declaredDirectDependencies: workspaceRootProject.declaredDirectDependencies ?? new Set(),
|
|
38
|
+
explicitlyRequestedDirectDependencies: workspaceRootProject.explicitlyRequestedDirectDependencies ?? new Set(),
|
|
39
|
+
});
|
|
40
|
+
}
|
|
23
41
|
const peerDependencyIssues = { bad: {}, missing: {} };
|
|
24
42
|
const pkgsByName = Object.fromEntries(Object.entries({
|
|
25
43
|
...rootPkgsByName,
|
|
@@ -42,6 +60,9 @@ export async function resolvePeers(opts) {
|
|
|
42
60
|
pathsByNodeId,
|
|
43
61
|
pathsByNodeIdPromises,
|
|
44
62
|
depPathsByPkgId,
|
|
63
|
+
nodeIdsByPreviousDepPath,
|
|
64
|
+
resolvedPeerProviderPaths: opts.resolvedPeerProviderPaths,
|
|
65
|
+
currentProviderSources,
|
|
45
66
|
peersCache,
|
|
46
67
|
peerDependencyIssues,
|
|
47
68
|
purePkgs,
|
|
@@ -104,6 +125,7 @@ export async function resolvePeers(opts) {
|
|
|
104
125
|
dependenciesGraph: depGraphWithResolvedChildren,
|
|
105
126
|
dependenciesByProjectId,
|
|
106
127
|
peerDependencyIssuesByProjects,
|
|
128
|
+
pathsByNodeId,
|
|
107
129
|
};
|
|
108
130
|
}
|
|
109
131
|
function nodeDepsCount(node) {
|
|
@@ -177,10 +199,6 @@ function isCompatibleAndHasMoreDeps(depGraph, depPath1, depPath2) {
|
|
|
177
199
|
}
|
|
178
200
|
return true;
|
|
179
201
|
}
|
|
180
|
-
function getRootPkgsByName(dependenciesTree, projects) {
|
|
181
|
-
const rootProject = projects.length > 1 ? projects.find(({ id }) => id === '.') : null;
|
|
182
|
-
return rootProject == null ? {} : createPkgsByName(dependenciesTree, rootProject);
|
|
183
|
-
}
|
|
184
202
|
function createPkgsByName(dependenciesTree, { directNodeIdsByAlias, topParents }) {
|
|
185
203
|
const parentRefs = toPkgByName(Array.from(directNodeIdsByAlias.entries())
|
|
186
204
|
.map(([alias, nodeId]) => ({
|
|
@@ -255,6 +273,46 @@ async function resolvePeersOfNode(currentAlias, nodeId, parentParentPkgs, ctx) {
|
|
|
255
273
|
}
|
|
256
274
|
}
|
|
257
275
|
}
|
|
276
|
+
if (node.lockedPeerContext != null && ctx.resolvedPeerProviderPaths != null) {
|
|
277
|
+
for (const [peerName, previousPeerDepPath] of Object.entries(node.lockedPeerContext)) {
|
|
278
|
+
const peerNodeId = ctx.nodeIdsByPreviousDepPath.get(previousPeerDepPath);
|
|
279
|
+
const peerDependency = resolvedPackage.peerDependencies[peerName];
|
|
280
|
+
if (peerNodeId == null || peerDependency == null)
|
|
281
|
+
continue;
|
|
282
|
+
if (ctx.resolvedPeerProviderPaths?.get(peerNodeId) !== previousPeerDepPath)
|
|
283
|
+
continue;
|
|
284
|
+
// Only pin providers that have no peer context of their own. A provider
|
|
285
|
+
// whose locked depPath carries a peer suffix is itself context-dependent
|
|
286
|
+
// — and self-referential for cyclic peers — so reusing it can re-expand
|
|
287
|
+
// cyclic suffixes and break the deterministic resolution that
|
|
288
|
+
// https://github.com/pnpm/pnpm/issues/8155 established. Stable leaf
|
|
289
|
+
// providers are the ones worth pinning; anything else falls back to
|
|
290
|
+
// fresh resolution.
|
|
291
|
+
if (parseDepPath(previousPeerDepPath).peerDepGraphHash !== '')
|
|
292
|
+
continue;
|
|
293
|
+
// A provider that already resolved to a different path this pass no longer
|
|
294
|
+
// matches its locked context; pinning it would leave pathsByNodeId
|
|
295
|
+
// pointing at a depPath that was never added to the graph.
|
|
296
|
+
const currentPeerDepPath = ctx.pathsByNodeId.get(peerNodeId);
|
|
297
|
+
if (currentPeerDepPath != null && currentPeerDepPath !== previousPeerDepPath)
|
|
298
|
+
continue;
|
|
299
|
+
if (hasCurrentPeerProviderThatMustWin(peerName, parentPkgs, ctx))
|
|
300
|
+
continue;
|
|
301
|
+
const lockedPeer = toPkgByName([{
|
|
302
|
+
alias: peerName,
|
|
303
|
+
node: ctx.dependenciesTree.get(peerNodeId),
|
|
304
|
+
nodeId: peerNodeId,
|
|
305
|
+
parentNodeIds,
|
|
306
|
+
}])[peerName];
|
|
307
|
+
if (!semverUtils.satisfiesWithPrereleases(lockedPeer.version, peerDependency.version.replace(/^workspace:/, ''), true))
|
|
308
|
+
continue;
|
|
309
|
+
const peerPathPromise = ctx.pathsByNodeIdPromises.get(peerNodeId) ?? pDefer();
|
|
310
|
+
ctx.pathsByNodeIdPromises.set(peerNodeId, peerPathPromise);
|
|
311
|
+
ctx.pathsByNodeId.set(peerNodeId, previousPeerDepPath);
|
|
312
|
+
peerPathPromise.resolve(previousPeerDepPath);
|
|
313
|
+
parentPkgs[peerName] = lockedPeer;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
258
316
|
const hit = findHit(ctx, parentPkgs, resolvedPackage.pkgIdWithPatchHash);
|
|
259
317
|
if (hit != null) {
|
|
260
318
|
for (const [peerName, { range: wantedRange, optional }] of hit.missingPeers.entries()) {
|
|
@@ -440,6 +498,40 @@ async function resolvePeersOfNode(currentAlias, nodeId, parentParentPkgs, ctx) {
|
|
|
440
498
|
}
|
|
441
499
|
}
|
|
442
500
|
}
|
|
501
|
+
function getNodeIdsByPreviousDepPath(dependenciesTree) {
|
|
502
|
+
const nodeIdsByPreviousDepPath = new Map();
|
|
503
|
+
for (const [nodeId, node] of dependenciesTree.entries()) {
|
|
504
|
+
if (node.previousDepPath != null && !nodeIdsByPreviousDepPath.has(node.previousDepPath)) {
|
|
505
|
+
nodeIdsByPreviousDepPath.set(node.previousDepPath, nodeId);
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
return nodeIdsByPreviousDepPath;
|
|
509
|
+
}
|
|
510
|
+
function hasCurrentPeerProviderThatMustWin(peerName, parentPkgs, ctx) {
|
|
511
|
+
const peerNodeId = parentPkgs[peerName]?.nodeId;
|
|
512
|
+
if (peerNodeId == null)
|
|
513
|
+
return false;
|
|
514
|
+
for (const source of ctx.currentProviderSources) {
|
|
515
|
+
for (const [alias, directNodeId] of source.directNodeIdsByAlias) {
|
|
516
|
+
if (directNodeId === peerNodeId &&
|
|
517
|
+
(alias !== peerName ||
|
|
518
|
+
source.explicitlyRequestedDirectDependencies.has(alias) ||
|
|
519
|
+
(source.declaredDirectDependencies.has(alias) &&
|
|
520
|
+
ctx.dependenciesTree.get(peerNodeId)?.previousDepPath == null)))
|
|
521
|
+
return true;
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
for (const parentNodeId of ctx.parentNodeIds) {
|
|
525
|
+
const parentNode = ctx.dependenciesTree.get(parentNodeId);
|
|
526
|
+
if (parentNode == null)
|
|
527
|
+
continue;
|
|
528
|
+
const children = typeof parentNode.children === 'function' ? parentNode.children() : parentNode.children;
|
|
529
|
+
parentNode.children = children;
|
|
530
|
+
if ([...(parentNode.dependencyNamesWhoseCurrentProviderMustWin ?? [])].some((alias) => children[alias] === peerNodeId))
|
|
531
|
+
return true;
|
|
532
|
+
}
|
|
533
|
+
return false;
|
|
534
|
+
}
|
|
443
535
|
function parentPkgsMatch(dependenciesTree, currentParentPkg, newParentPkg) {
|
|
444
536
|
if (currentParentPkg.version !== newParentPkg.version ||
|
|
445
537
|
currentParentPkg.alias !== newParentPkg.alias) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pnpm/installing.deps-resolver",
|
|
3
|
-
"version": "1100.
|
|
3
|
+
"version": "1100.2.0",
|
|
4
4
|
"description": "Resolves dependency graph of a package",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pnpm",
|
|
@@ -8,7 +8,10 @@
|
|
|
8
8
|
],
|
|
9
9
|
"license": "MIT",
|
|
10
10
|
"funding": "https://opencollective.com/pnpm",
|
|
11
|
-
"repository":
|
|
11
|
+
"repository": {
|
|
12
|
+
"type": "git",
|
|
13
|
+
"url": "https://github.com/pnpm/pnpm/tree/main/installing/deps-resolver"
|
|
14
|
+
},
|
|
12
15
|
"homepage": "https://github.com/pnpm/pnpm/tree/main/installing/deps-resolver#readme",
|
|
13
16
|
"bugs": {
|
|
14
17
|
"url": "https://github.com/pnpm/pnpm/issues"
|
|
@@ -40,30 +43,30 @@
|
|
|
40
43
|
"semver-range-intersect": "^0.3.1",
|
|
41
44
|
"validate-npm-package-name": "7.0.2",
|
|
42
45
|
"version-selector-type": "^3.0.0",
|
|
43
|
-
"@pnpm/catalogs.resolver": "1100.0.0",
|
|
44
46
|
"@pnpm/catalogs.types": "1100.0.0",
|
|
45
|
-
"@pnpm/
|
|
46
|
-
"@pnpm/
|
|
47
|
+
"@pnpm/catalogs.resolver": "1100.0.0",
|
|
48
|
+
"@pnpm/config.version-policy": "1100.1.3",
|
|
47
49
|
"@pnpm/constants": "1100.0.0",
|
|
48
|
-
"@pnpm/
|
|
50
|
+
"@pnpm/core-loggers": "1100.1.3",
|
|
51
|
+
"@pnpm/deps.path": "1100.0.6",
|
|
52
|
+
"@pnpm/deps.graph-hasher": "1100.2.3",
|
|
49
53
|
"@pnpm/error": "1100.0.0",
|
|
50
|
-
"@pnpm/
|
|
51
|
-
"@pnpm/fetching.pick-fetcher": "1100.0.
|
|
52
|
-
"@pnpm/lockfile.
|
|
53
|
-
"@pnpm/
|
|
54
|
-
"@pnpm/lockfile.
|
|
55
|
-
"@pnpm/
|
|
54
|
+
"@pnpm/deps.peer-range": "1100.0.1",
|
|
55
|
+
"@pnpm/fetching.pick-fetcher": "1100.0.10",
|
|
56
|
+
"@pnpm/lockfile.types": "1100.0.9",
|
|
57
|
+
"@pnpm/patching.config": "1100.0.6",
|
|
58
|
+
"@pnpm/lockfile.preferred-versions": "1100.0.13",
|
|
59
|
+
"@pnpm/pkg-manifest.utils": "1100.2.2",
|
|
60
|
+
"@pnpm/lockfile.utils": "1100.0.11",
|
|
61
|
+
"@pnpm/resolving.resolver-base": "1100.4.0",
|
|
62
|
+
"@pnpm/pkg-manifest.reader": "1100.0.6",
|
|
56
63
|
"@pnpm/patching.types": "1100.0.0",
|
|
57
|
-
"@pnpm/
|
|
58
|
-
"@pnpm/lockfile.
|
|
59
|
-
"@pnpm/pkg-manifest.reader": "1100.0.5",
|
|
60
|
-
"@pnpm/resolving.npm-resolver": "1101.4.0",
|
|
61
|
-
"@pnpm/types": "1101.2.0",
|
|
62
|
-
"@pnpm/store.controller-types": "1100.1.2",
|
|
63
|
-
"@pnpm/deps.path": "1100.0.5",
|
|
64
|
+
"@pnpm/hooks.types": "1100.0.10",
|
|
65
|
+
"@pnpm/lockfile.pruner": "1100.0.9",
|
|
64
66
|
"@pnpm/workspace.spec-parser": "1100.0.0",
|
|
65
|
-
"@pnpm/
|
|
66
|
-
"@pnpm/resolving.resolver
|
|
67
|
+
"@pnpm/types": "1101.3.0",
|
|
68
|
+
"@pnpm/resolving.npm-resolver": "1101.5.0",
|
|
69
|
+
"@pnpm/store.controller-types": "1100.1.3"
|
|
67
70
|
},
|
|
68
71
|
"peerDependencies": {
|
|
69
72
|
"@pnpm/logger": "^1001.0.1"
|
|
@@ -75,7 +78,7 @@
|
|
|
75
78
|
"@types/semver": "7.7.1",
|
|
76
79
|
"@types/validate-npm-package-name": "^4.0.2",
|
|
77
80
|
"@pnpm/logger": "1100.0.0",
|
|
78
|
-
"@pnpm/installing.deps-resolver": "1100.
|
|
81
|
+
"@pnpm/installing.deps-resolver": "1100.2.0"
|
|
79
82
|
},
|
|
80
83
|
"engines": {
|
|
81
84
|
"node": ">=22.13"
|