@pnpm/installing.deps-resolver 1100.2.3 → 1100.2.4
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/dedupeInjectedDeps.js +16 -9
- package/lib/resolveDependencies.js +62 -1
- package/lib/resolvePeers.js +15 -3
- package/lib/toResolveImporter.js +1 -1
- package/lib/updateProjectManifest.js +16 -1
- package/package.json +12 -12
|
@@ -27,19 +27,26 @@ function getDedupeMap(injectedDepsByProjects, opts) {
|
|
|
27
27
|
for (const [id, deps] of injectedDepsByProjects.entries()) {
|
|
28
28
|
const dedupedInjectedDeps = new Map();
|
|
29
29
|
for (const [alias, dep] of deps.entries()) {
|
|
30
|
-
|
|
31
|
-
// The injected project in the workspace may have dev deps
|
|
32
|
-
const children = Object.entries(opts.depGraph[dep.depPath].children);
|
|
30
|
+
const node = opts.depGraph[dep.depPath];
|
|
33
31
|
const targetProjectDeps = opts.dependenciesByProjectId[dep.id];
|
|
34
|
-
//
|
|
35
|
-
//
|
|
36
|
-
// injected dep
|
|
32
|
+
// In single-project operations (e.g. `pnpm rm` from inside a workspace package) the target
|
|
33
|
+
// workspace project isn't being resolved, so its children aren't in
|
|
34
|
+
// `dependenciesByProjectId`. The injected dep was resolved against the same workspace
|
|
35
|
+
// package source, so dedupe is safe. The exception is peer-suffixed depPaths, whose
|
|
36
|
+
// resolution depends on the importer's peer context. A plain `link:` would lose that, so
|
|
37
|
+
// we skip dedupe for those. A depPath is `${pkgIdWithPatchHash}${peerDepGraphHash}`, so it
|
|
38
|
+
// carries a peer suffix exactly when it differs from its peer-free `pkgIdWithPatchHash`.
|
|
37
39
|
if (!targetProjectDeps) {
|
|
38
|
-
if (
|
|
39
|
-
|
|
40
|
+
if (node.pkgIdWithPatchHash === dep.depPath) {
|
|
41
|
+
dedupedInjectedDeps.set(alias, dep.id);
|
|
42
|
+
}
|
|
43
|
+
continue;
|
|
40
44
|
}
|
|
45
|
+
// Check for subgroup not equal.
|
|
46
|
+
// The injected project in the workspace may have dev deps
|
|
47
|
+
const children = Object.entries(node.children);
|
|
41
48
|
const isSubset = children
|
|
42
|
-
.every(([alias, depPath]) => targetProjectDeps
|
|
49
|
+
.every(([alias, depPath]) => targetProjectDeps.get(alias) === depPath);
|
|
43
50
|
if (isSubset) {
|
|
44
51
|
dedupedInjectedDeps.set(alias, dep.id);
|
|
45
52
|
}
|
|
@@ -314,6 +314,7 @@ function getPublishedByDate(pkgAddresses, timeFromLockfile = {}) {
|
|
|
314
314
|
export async function resolveDependencies(ctx, preferredVersions, wantedDependencies, options) {
|
|
315
315
|
const extendedWantedDeps = getDepsToResolve(wantedDependencies, ctx.wantedLockfile, {
|
|
316
316
|
preferredDependencies: options.preferredDependencies,
|
|
317
|
+
preferredVersions,
|
|
317
318
|
prefix: options.prefix,
|
|
318
319
|
proceed: options.proceed || ctx.forceFullResolution,
|
|
319
320
|
registries: ctx.registries,
|
|
@@ -849,12 +850,33 @@ function getDepsToResolve(wantedDependencies, wantedLockfile, options) {
|
|
|
849
850
|
});
|
|
850
851
|
for (const wantedDependency of wantedDependencies) {
|
|
851
852
|
let reference = undefined;
|
|
853
|
+
let preferredVersion = undefined;
|
|
852
854
|
let proceed = proceedAll;
|
|
853
855
|
if (wantedDependency.alias) {
|
|
854
856
|
const satisfiesWanted = satisfiesWanted2Args.bind(null, wantedDependency);
|
|
855
857
|
if (resolvedDependencies[wantedDependency.alias] &&
|
|
856
858
|
(satisfiesWanted(resolvedDependencies[wantedDependency.alias]) || resolvedDependencies[wantedDependency.alias].startsWith('file:'))) {
|
|
857
|
-
|
|
859
|
+
const pinnedRef = resolvedDependencies[wantedDependency.alias];
|
|
860
|
+
// Reusing a lockfile pin verbatim bypasses the preferred-versions
|
|
861
|
+
// walk, so a transitive edge stays on a stale lower version even
|
|
862
|
+
// when a direct dependency resolved to a higher version in range.
|
|
863
|
+
const pinned = pinnedRef.startsWith('file:')
|
|
864
|
+
? undefined
|
|
865
|
+
: getPinnedNameVer(wantedLockfile, pinnedRef, wantedDependency.alias);
|
|
866
|
+
const higherDirectVersion = pinned == null
|
|
867
|
+
? undefined
|
|
868
|
+
: findHigherDirectDepVersion(options.preferredVersions, pinned.name, pinned.version, wantedDependency.bareSpecifier);
|
|
869
|
+
if (higherDirectVersion != null) {
|
|
870
|
+
// `preferredVersion` (singular) overrides the
|
|
871
|
+
// EXISTING_VERSION_SELECTOR_WEIGHT stability bias that would
|
|
872
|
+
// otherwise re-pick the lower version. The lower version is then
|
|
873
|
+
// never resolved or fetched.
|
|
874
|
+
proceed = true;
|
|
875
|
+
preferredVersion = higherDirectVersion;
|
|
876
|
+
}
|
|
877
|
+
else {
|
|
878
|
+
reference = pinnedRef;
|
|
879
|
+
}
|
|
858
880
|
}
|
|
859
881
|
else if (
|
|
860
882
|
// If dependencies that were used by the previous version of the package
|
|
@@ -885,6 +907,7 @@ function getDepsToResolve(wantedDependencies, wantedLockfile, options) {
|
|
|
885
907
|
}
|
|
886
908
|
extendedWantedDeps.push({
|
|
887
909
|
infoFromLockfile,
|
|
910
|
+
preferredVersion,
|
|
888
911
|
proceed,
|
|
889
912
|
wantedDependency,
|
|
890
913
|
});
|
|
@@ -909,6 +932,44 @@ function referenceSatisfiesWantedSpec(opts, wantedDep, preferredRef) {
|
|
|
909
932
|
}
|
|
910
933
|
return semver.satisfies(version, wantedDep.bareSpecifier, true);
|
|
911
934
|
}
|
|
935
|
+
function getPinnedNameVer(lockfile, reference, alias) {
|
|
936
|
+
const depPath = dp.refToRelative(reference, alias);
|
|
937
|
+
if (depPath === null)
|
|
938
|
+
return undefined;
|
|
939
|
+
const pkgSnapshot = lockfile.packages?.[depPath];
|
|
940
|
+
if (pkgSnapshot == null)
|
|
941
|
+
return undefined;
|
|
942
|
+
return nameVerFromPkgSnapshot(depPath, pkgSnapshot);
|
|
943
|
+
}
|
|
944
|
+
// The highest version a direct dependency (the only deterministic,
|
|
945
|
+
// resolved-first anchor) resolved to that is higher than the
|
|
946
|
+
// lockfile-pinned `pinnedVersion` and still satisfies the edge's range, or
|
|
947
|
+
// `undefined` when none exists. Direct-dependency versions are marked with
|
|
948
|
+
// DIRECT_DEP_SELECTOR_WEIGHT in preferredVersions.
|
|
949
|
+
function findHigherDirectDepVersion(preferredVersions, pinnedName, pinnedVersion, bareSpecifier) {
|
|
950
|
+
if (preferredVersions == null)
|
|
951
|
+
return undefined;
|
|
952
|
+
if (!semver.valid(pinnedVersion))
|
|
953
|
+
return undefined;
|
|
954
|
+
if (semver.validRange(bareSpecifier) === null)
|
|
955
|
+
return undefined;
|
|
956
|
+
const selectors = preferredVersions[pinnedName];
|
|
957
|
+
if (selectors == null)
|
|
958
|
+
return undefined;
|
|
959
|
+
let best;
|
|
960
|
+
for (const [candidate, selector] of Object.entries(selectors)) {
|
|
961
|
+
if (typeof selector === 'object' &&
|
|
962
|
+
selector.selectorType === 'version' &&
|
|
963
|
+
selector.weight === DIRECT_DEP_SELECTOR_WEIGHT &&
|
|
964
|
+
semver.valid(candidate) &&
|
|
965
|
+
semver.gt(candidate, pinnedVersion) &&
|
|
966
|
+
semver.satisfies(candidate, bareSpecifier, true) &&
|
|
967
|
+
(best == null || semver.gt(candidate, best))) {
|
|
968
|
+
best = candidate;
|
|
969
|
+
}
|
|
970
|
+
}
|
|
971
|
+
return best;
|
|
972
|
+
}
|
|
912
973
|
function getLockedPeerContext(dependencyLockfile) {
|
|
913
974
|
if (dependencyLockfile.peerDependencies == null)
|
|
914
975
|
return undefined;
|
package/lib/resolvePeers.js
CHANGED
|
@@ -259,10 +259,11 @@ async function resolvePeersOfNode(currentAlias, nodeId, parentParentPkgs, ctx) {
|
|
|
259
259
|
parentPkgs = { ...parentParentPkgs };
|
|
260
260
|
const parentPkgNodes = [];
|
|
261
261
|
for (const [alias, nodeId] of Object.entries(children)) {
|
|
262
|
-
|
|
262
|
+
const childNode = ctx.dependenciesTree.get(nodeId);
|
|
263
|
+
if (ctx.allPeerDepNames.has(alias) || (alias !== childNode.resolvedPackage.name && ctx.allPeerDepNames.has(childNode.resolvedPackage.name))) {
|
|
263
264
|
parentPkgNodes.push({
|
|
264
265
|
alias,
|
|
265
|
-
node:
|
|
266
|
+
node: childNode,
|
|
266
267
|
nodeId,
|
|
267
268
|
parentNodeIds,
|
|
268
269
|
});
|
|
@@ -391,7 +392,18 @@ async function resolvePeersOfNode(currentAlias, nodeId, parentParentPkgs, ctx) {
|
|
|
391
392
|
}
|
|
392
393
|
let cache;
|
|
393
394
|
const isPure = allResolvedPeers.size === 0 && allMissingPeers.size === 0;
|
|
394
|
-
|
|
395
|
+
// A cycle re-entry resolves against truncated children (the cycle is broken by
|
|
396
|
+
// dropping the repeated package's subtree), so its empty/partial peer sets are
|
|
397
|
+
// not authoritative for the package as a whole. Recording that verdict — as
|
|
398
|
+
// pure or in peersCache — lets it short-circuit other occurrences that *can*
|
|
399
|
+
// see the full subtree, dropping their transitivePeerDependencies depending on
|
|
400
|
+
// traversal order and churning the lockfile (https://github.com/pnpm/pnpm/issues/5108).
|
|
401
|
+
const resolvedThroughCycle = ctx.parentDepPathsChain.includes(resolvedPackage.pkgIdWithPatchHash);
|
|
402
|
+
if (resolvedThroughCycle) {
|
|
403
|
+
// Leave both caches untouched so later occurrences re-resolve (or hit the
|
|
404
|
+
// authoritative entry of the same package) instead of reusing this partial one.
|
|
405
|
+
}
|
|
406
|
+
else if (isPure) {
|
|
395
407
|
ctx.purePkgs.add(resolvedPackage.pkgIdWithPatchHash);
|
|
396
408
|
}
|
|
397
409
|
else {
|
package/lib/toResolveImporter.js
CHANGED
|
@@ -48,7 +48,7 @@ export async function toResolveImporter(opts, project) {
|
|
|
48
48
|
...project.wantedDependencies.map(defaultUpdateDepth < 0
|
|
49
49
|
? updateLocalTarballs
|
|
50
50
|
: (dep) => ({ ...dep, updateDepth: defaultUpdateDepth })),
|
|
51
|
-
...existingDeps.map(
|
|
51
|
+
...existingDeps.map(project.updateMatching != null
|
|
52
52
|
? updateLocalTarballs
|
|
53
53
|
: (dep) => ({ ...dep, updateDepth: -1 })),
|
|
54
54
|
];
|
|
@@ -10,7 +10,7 @@ export async function updateProjectManifest(importer, opts) {
|
|
|
10
10
|
return {
|
|
11
11
|
alias: rdd.alias,
|
|
12
12
|
peer: importer.peer,
|
|
13
|
-
bareSpecifier:
|
|
13
|
+
bareSpecifier: getBareSpecifierToSave(wantedDep, rdd, opts.preserveWorkspaceProtocol),
|
|
14
14
|
resolvedVersion: rdd.version,
|
|
15
15
|
pinnedVersion: importer.pinnedVersion,
|
|
16
16
|
saveType: importer.targetDependenciesField,
|
|
@@ -31,4 +31,19 @@ export async function updateProjectManifest(importer, opts) {
|
|
|
31
31
|
: undefined;
|
|
32
32
|
return [hookedManifest, originalManifest];
|
|
33
33
|
}
|
|
34
|
+
function getBareSpecifierToSave(wantedDep, resolvedDep, preserveWorkspaceProtocol) {
|
|
35
|
+
if (resolvedDep.catalogLookup != null) {
|
|
36
|
+
return resolvedDep.catalogLookup.userSpecifiedBareSpecifier;
|
|
37
|
+
}
|
|
38
|
+
if (preserveWorkspaceProtocol && isWorkspaceLocalPathSpecifier(wantedDep.bareSpecifier)) {
|
|
39
|
+
return wantedDep.bareSpecifier;
|
|
40
|
+
}
|
|
41
|
+
return resolvedDep.normalizedBareSpecifier ?? wantedDep.bareSpecifier;
|
|
42
|
+
}
|
|
43
|
+
function isWorkspaceLocalPathSpecifier(bareSpecifier) {
|
|
44
|
+
if (!bareSpecifier.startsWith('workspace:'))
|
|
45
|
+
return false;
|
|
46
|
+
const pref = bareSpecifier.slice('workspace:'.length);
|
|
47
|
+
return pref.startsWith('.') || pref.startsWith('/') || pref.startsWith('~/') || /^[A-Z]:/i.test(pref);
|
|
48
|
+
}
|
|
34
49
|
//# sourceMappingURL=updateProjectManifest.js.map
|
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.4",
|
|
4
4
|
"description": "Resolves dependency graph of a package",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pnpm",
|
|
@@ -43,30 +43,30 @@
|
|
|
43
43
|
"semver-range-intersect": "^0.3.1",
|
|
44
44
|
"validate-npm-package-name": "7.0.2",
|
|
45
45
|
"version-selector-type": "^3.0.0",
|
|
46
|
-
"@pnpm/catalogs.resolver": "1100.0.0",
|
|
47
|
-
"@pnpm/catalogs.types": "1100.0.0",
|
|
48
|
-
"@pnpm/config.version-policy": "1100.1.5",
|
|
49
46
|
"@pnpm/constants": "1100.0.0",
|
|
50
47
|
"@pnpm/core-loggers": "1100.2.1",
|
|
51
48
|
"@pnpm/deps.graph-hasher": "1100.2.5",
|
|
52
|
-
"@pnpm/deps.path": "1100.0.8",
|
|
53
49
|
"@pnpm/error": "1100.0.0",
|
|
54
|
-
"@pnpm/deps.peer-range": "1100.0.2",
|
|
55
50
|
"@pnpm/fetching.pick-fetcher": "1100.0.12",
|
|
51
|
+
"@pnpm/deps.peer-range": "1100.0.2",
|
|
56
52
|
"@pnpm/hooks.types": "1100.0.12",
|
|
53
|
+
"@pnpm/deps.path": "1100.0.8",
|
|
54
|
+
"@pnpm/config.version-policy": "1100.1.5",
|
|
57
55
|
"@pnpm/lockfile.preferred-versions": "1100.0.16",
|
|
58
|
-
"@pnpm/lockfile.pruner": "1100.0.11",
|
|
59
56
|
"@pnpm/lockfile.types": "1100.0.11",
|
|
60
57
|
"@pnpm/lockfile.utils": "1100.0.13",
|
|
61
58
|
"@pnpm/patching.config": "1100.0.8",
|
|
62
|
-
"@pnpm/
|
|
63
|
-
"@pnpm/pkg-manifest.utils": "1100.2.5",
|
|
59
|
+
"@pnpm/catalogs.types": "1100.0.0",
|
|
64
60
|
"@pnpm/pkg-manifest.reader": "1100.0.8",
|
|
65
|
-
"@pnpm/
|
|
61
|
+
"@pnpm/pkg-manifest.utils": "1100.2.5",
|
|
62
|
+
"@pnpm/resolving.npm-resolver": "1102.0.1",
|
|
63
|
+
"@pnpm/resolving.resolver-base": "1100.4.2",
|
|
66
64
|
"@pnpm/store.controller-types": "1100.1.5",
|
|
67
65
|
"@pnpm/types": "1101.3.2",
|
|
68
66
|
"@pnpm/workspace.spec-parser": "1100.0.0",
|
|
69
|
-
"@pnpm/
|
|
67
|
+
"@pnpm/patching.types": "1100.0.0",
|
|
68
|
+
"@pnpm/catalogs.resolver": "1100.0.0",
|
|
69
|
+
"@pnpm/lockfile.pruner": "1100.0.11"
|
|
70
70
|
},
|
|
71
71
|
"peerDependencies": {
|
|
72
72
|
"@pnpm/logger": "^1100.0.0"
|
|
@@ -77,7 +77,7 @@
|
|
|
77
77
|
"@types/ramda": "0.31.1",
|
|
78
78
|
"@types/semver": "7.7.1",
|
|
79
79
|
"@types/validate-npm-package-name": "^4.0.2",
|
|
80
|
-
"@pnpm/installing.deps-resolver": "1100.2.
|
|
80
|
+
"@pnpm/installing.deps-resolver": "1100.2.4",
|
|
81
81
|
"@pnpm/logger": "1100.0.0"
|
|
82
82
|
},
|
|
83
83
|
"engines": {
|