@pnpm/installing.deps-resolver 1100.2.2 → 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/index.d.ts +1 -0
- package/lib/index.js +1 -0
- package/lib/resolveDependencies.d.ts +35 -0
- package/lib/resolveDependencies.js +587 -317
- package/lib/resolveDependencyTree.d.ts +1 -1
- package/lib/resolveDependencyTree.js +9 -29
- package/lib/resolvePeers.js +24 -3
- package/lib/toResolveImporter.js +1 -1
- package/lib/updateProjectManifest.js +16 -1
- package/package.json +29 -29
|
@@ -9,6 +9,7 @@ import { logger } from '@pnpm/logger';
|
|
|
9
9
|
import { getPatchInfo } from '@pnpm/patching.config';
|
|
10
10
|
import { convertEnginesRuntimeToDependencies } from '@pnpm/pkg-manifest.utils';
|
|
11
11
|
import { DIRECT_DEP_SELECTOR_WEIGHT, } from '@pnpm/resolving.resolver-base';
|
|
12
|
+
import { lexCompare } from '@pnpm/util.lex-comparator';
|
|
12
13
|
import normalizePath from 'normalize-path';
|
|
13
14
|
import pDefer from 'p-defer';
|
|
14
15
|
import { pathExists } from 'path-exists';
|
|
@@ -313,6 +314,7 @@ function getPublishedByDate(pkgAddresses, timeFromLockfile = {}) {
|
|
|
313
314
|
export async function resolveDependencies(ctx, preferredVersions, wantedDependencies, options) {
|
|
314
315
|
const extendedWantedDeps = getDepsToResolve(wantedDependencies, ctx.wantedLockfile, {
|
|
315
316
|
preferredDependencies: options.preferredDependencies,
|
|
317
|
+
preferredVersions,
|
|
316
318
|
prefix: options.prefix,
|
|
317
319
|
proceed: options.proceed || ctx.forceFullResolution,
|
|
318
320
|
registries: ctx.registries,
|
|
@@ -522,6 +524,7 @@ async function resolveDependenciesOfDependency(ctx, preferredVersions, options,
|
|
|
522
524
|
}
|
|
523
525
|
const postponedResolution = resolveChildren.bind(null, ctx, {
|
|
524
526
|
parentPkg: resolveDependencyResult,
|
|
527
|
+
childrenResolutionId: resolveDependencyResult.childrenResolutionId,
|
|
525
528
|
dependencyLockfile: extendedWantedDep.infoFromLockfile?.dependencyLockfile,
|
|
526
529
|
parentDepth: options.currentDepth,
|
|
527
530
|
parentIds: [...options.parentIds, resolveDependencyResult.pkgId],
|
|
@@ -534,7 +537,18 @@ async function resolveDependenciesOfDependency(ctx, preferredVersions, options,
|
|
|
534
537
|
return {
|
|
535
538
|
resolveDependencyResult,
|
|
536
539
|
postponedResolution: async (postponedResolutionOpts) => {
|
|
540
|
+
if (!isCurrentChildrenResolution(ctx, resolveDependencyResult.pkgId, resolveDependencyResult.childrenResolutionId)) {
|
|
541
|
+
setDependencyTreeNodeWithCurrentChildren(ctx, {
|
|
542
|
+
parentDepth: options.currentDepth,
|
|
543
|
+
parentIds: [...options.parentIds, resolveDependencyResult.pkgId],
|
|
544
|
+
parentPkg: resolveDependencyResult,
|
|
545
|
+
});
|
|
546
|
+
return resolveMissingPeersFromCurrentChildrenResolution(ctx, resolveDependencyResult.pkgId, postponedResolutionOpts.parentPkgAliases);
|
|
547
|
+
}
|
|
537
548
|
const { missingPeers, resolvedPeers } = await postponedResolution(postponedResolutionOpts);
|
|
549
|
+
if (!isCurrentChildrenResolution(ctx, resolveDependencyResult.pkgId, resolveDependencyResult.childrenResolutionId)) {
|
|
550
|
+
return resolveMissingPeersFromCurrentChildrenResolution(ctx, resolveDependencyResult.pkgId, postponedResolutionOpts.parentPkgAliases);
|
|
551
|
+
}
|
|
538
552
|
if (resolveDependencyResult.missingPeersOfChildren) {
|
|
539
553
|
resolveDependencyResult.missingPeersOfChildren.resolved = true;
|
|
540
554
|
resolveDependencyResult.missingPeersOfChildren.resolve(missingPeers);
|
|
@@ -563,7 +577,195 @@ function filterMissingPeers({ missingPeers, resolvedPeers }, parentPkgAliases) {
|
|
|
563
577
|
missingPeers: newMissing,
|
|
564
578
|
};
|
|
565
579
|
}
|
|
566
|
-
|
|
580
|
+
function startPackageResolution(ctx, depth) {
|
|
581
|
+
const activeCount = ctx.packageResolutionBarrier.activeByDepth.get(depth) ?? 0;
|
|
582
|
+
ctx.packageResolutionBarrier.activeByDepth.set(depth, activeCount + 1);
|
|
583
|
+
let finished = false;
|
|
584
|
+
return () => {
|
|
585
|
+
if (finished)
|
|
586
|
+
return;
|
|
587
|
+
finished = true;
|
|
588
|
+
const nextActiveCount = (ctx.packageResolutionBarrier.activeByDepth.get(depth) ?? 1) - 1;
|
|
589
|
+
if (nextActiveCount > 0) {
|
|
590
|
+
ctx.packageResolutionBarrier.activeByDepth.set(depth, nextActiveCount);
|
|
591
|
+
}
|
|
592
|
+
else {
|
|
593
|
+
ctx.packageResolutionBarrier.activeByDepth.delete(depth);
|
|
594
|
+
}
|
|
595
|
+
const waiters = ctx.packageResolutionBarrier.waiters.splice(0);
|
|
596
|
+
for (const resolve of waiters) {
|
|
597
|
+
resolve();
|
|
598
|
+
}
|
|
599
|
+
};
|
|
600
|
+
}
|
|
601
|
+
async function waitForPackageResolutionTurn(ctx, depth) {
|
|
602
|
+
if (!hasActivePackageResolutionBeforeDepth(ctx, depth))
|
|
603
|
+
return;
|
|
604
|
+
await new Promise((resolve) => ctx.packageResolutionBarrier.waiters.push(resolve));
|
|
605
|
+
return waitForPackageResolutionTurn(ctx, depth);
|
|
606
|
+
}
|
|
607
|
+
function hasActivePackageResolutionBeforeDepth(ctx, depth) {
|
|
608
|
+
for (const [activeDepth, activeCount] of ctx.packageResolutionBarrier.activeByDepth) {
|
|
609
|
+
if (activeDepth < depth && activeCount > 0)
|
|
610
|
+
return true;
|
|
611
|
+
}
|
|
612
|
+
return false;
|
|
613
|
+
}
|
|
614
|
+
function claimChildrenResolution(ctx, opts) {
|
|
615
|
+
const owner = {
|
|
616
|
+
depth: opts.currentDepth,
|
|
617
|
+
importerOrder: ctx.importerResolutionOrder[opts.parentIds[0]] ?? Number.MAX_SAFE_INTEGER,
|
|
618
|
+
parentPath: opts.parentIds,
|
|
619
|
+
};
|
|
620
|
+
const existing = ctx.childrenResolutionByPkgId[opts.pkgId];
|
|
621
|
+
if (existing == null || compareChildrenResolutionOwners(owner, existing.owner) < 0) {
|
|
622
|
+
const previousMissingPeersOfChildren = existing?.missingPeersOfChildren;
|
|
623
|
+
const missingPeersOfChildren = ctx.hoistPeers && !opts.parentIds.includes(opts.pkgId)
|
|
624
|
+
? createMissingPeersOfChildren()
|
|
625
|
+
: undefined;
|
|
626
|
+
const resolution = {
|
|
627
|
+
id: ++ctx.childrenResolutionId,
|
|
628
|
+
owner,
|
|
629
|
+
missingPeersOfChildren,
|
|
630
|
+
};
|
|
631
|
+
ctx.childrenResolutionByPkgId[opts.pkgId] = resolution;
|
|
632
|
+
if (missingPeersOfChildren) {
|
|
633
|
+
ctx.missingPeersOfChildrenByPkgId[opts.pkgId] = {
|
|
634
|
+
depth: owner.depth,
|
|
635
|
+
missingPeersOfChildren,
|
|
636
|
+
};
|
|
637
|
+
}
|
|
638
|
+
if (previousMissingPeersOfChildren) {
|
|
639
|
+
if (missingPeersOfChildren) {
|
|
640
|
+
missingPeersOfChildren.get().then((missingPeers) => {
|
|
641
|
+
previousMissingPeersOfChildren.resolved = true;
|
|
642
|
+
previousMissingPeersOfChildren.resolve(missingPeers);
|
|
643
|
+
}, previousMissingPeersOfChildren.reject);
|
|
644
|
+
}
|
|
645
|
+
else {
|
|
646
|
+
previousMissingPeersOfChildren.resolved = true;
|
|
647
|
+
previousMissingPeersOfChildren.resolve({});
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
return {
|
|
651
|
+
id: resolution.id,
|
|
652
|
+
isOwner: true,
|
|
653
|
+
missingPeersOfChildren,
|
|
654
|
+
};
|
|
655
|
+
}
|
|
656
|
+
let missingPeersOfChildren;
|
|
657
|
+
if (ctx.hoistPeers &&
|
|
658
|
+
!opts.parentIds.includes(opts.pkgId) &&
|
|
659
|
+
existing.missingPeersOfChildren &&
|
|
660
|
+
(existing.owner.depth >= opts.currentDepth ||
|
|
661
|
+
existing.missingPeersOfChildren.resolved)) {
|
|
662
|
+
missingPeersOfChildren = existing.missingPeersOfChildren;
|
|
663
|
+
}
|
|
664
|
+
return {
|
|
665
|
+
id: existing.id,
|
|
666
|
+
isOwner: false,
|
|
667
|
+
missingPeersOfChildren,
|
|
668
|
+
};
|
|
669
|
+
}
|
|
670
|
+
function compareChildrenResolutionOwners(owner1, owner2) {
|
|
671
|
+
if (owner1.depth !== owner2.depth)
|
|
672
|
+
return owner1.depth - owner2.depth;
|
|
673
|
+
if (owner1.importerOrder !== owner2.importerOrder)
|
|
674
|
+
return owner1.importerOrder - owner2.importerOrder;
|
|
675
|
+
const pathLength = Math.min(owner1.parentPath.length, owner2.parentPath.length);
|
|
676
|
+
for (let i = 0; i < pathLength; i++) {
|
|
677
|
+
const result = lexCompare(owner1.parentPath[i], owner2.parentPath[i]);
|
|
678
|
+
if (result !== 0)
|
|
679
|
+
return result;
|
|
680
|
+
}
|
|
681
|
+
return owner1.parentPath.length - owner2.parentPath.length;
|
|
682
|
+
}
|
|
683
|
+
function createMissingPeersOfChildren() {
|
|
684
|
+
const p = pDefer();
|
|
685
|
+
return {
|
|
686
|
+
resolve: p.resolve,
|
|
687
|
+
reject: p.reject,
|
|
688
|
+
get: pShare(p.promise),
|
|
689
|
+
};
|
|
690
|
+
}
|
|
691
|
+
function isCurrentChildrenResolution(ctx, pkgId, childrenResolutionId) {
|
|
692
|
+
return childrenResolutionId != null && ctx.childrenResolutionByPkgId[pkgId]?.id === childrenResolutionId;
|
|
693
|
+
}
|
|
694
|
+
async function resolveMissingPeersFromCurrentChildrenResolution(ctx, pkgId, parentPkgAliases) {
|
|
695
|
+
const missingPeersOfChildren = ctx.childrenResolutionByPkgId[pkgId]?.missingPeersOfChildren;
|
|
696
|
+
if (missingPeersOfChildren == null) {
|
|
697
|
+
return {
|
|
698
|
+
missingPeers: {},
|
|
699
|
+
resolvedPeers: {},
|
|
700
|
+
};
|
|
701
|
+
}
|
|
702
|
+
const missingPeers = await missingPeersOfChildren.get();
|
|
703
|
+
return filterMissingPeers({ missingPeers, resolvedPeers: {} }, parentPkgAliases);
|
|
704
|
+
}
|
|
705
|
+
function setDependencyTreeNodeWithCurrentChildren(ctx, { parentDepth, parentIds, parentPkg, }) {
|
|
706
|
+
ctx.dependenciesTree.set(parentPkg.nodeId, {
|
|
707
|
+
children: () => buildTree(ctx, parentPkg.pkgId, parentIds, ctx.childrenByParentId[parentPkg.pkgId] ?? [], parentDepth + 1, parentPkg.installable),
|
|
708
|
+
depth: parentDepth,
|
|
709
|
+
installable: parentPkg.installable,
|
|
710
|
+
lockedPeerContext: parentPkg.lockedPeerContext,
|
|
711
|
+
previousDepPath: parentPkg.previousDepPath,
|
|
712
|
+
resolvedPackage: ctx.resolvedPkgsById[parentPkg.pkgId],
|
|
713
|
+
});
|
|
714
|
+
ctx.nodeResolutionContextByNodeId.set(parentPkg.nodeId, {
|
|
715
|
+
depth: parentDepth,
|
|
716
|
+
installable: parentPkg.installable,
|
|
717
|
+
parentIds,
|
|
718
|
+
pkgId: parentPkg.pkgId,
|
|
719
|
+
});
|
|
720
|
+
}
|
|
721
|
+
function updateChildrenResolutionNodes(ctx, pkgId, currentNodeId) {
|
|
722
|
+
for (const [nodeId, nodeContext] of ctx.nodeResolutionContextByNodeId) {
|
|
723
|
+
if (nodeId === currentNodeId || nodeContext.pkgId !== pkgId)
|
|
724
|
+
continue;
|
|
725
|
+
const node = ctx.dependenciesTree.get(nodeId);
|
|
726
|
+
if (node == null || node.depth === -1)
|
|
727
|
+
continue;
|
|
728
|
+
node.children = () => buildTree(ctx, pkgId, nodeContext.parentIds, ctx.childrenByParentId[pkgId] ?? [], nodeContext.depth + 1, nodeContext.installable);
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
export function buildTree(ctx, parentId, parentIds, children, depth, installable) {
|
|
732
|
+
const childrenNodeIds = {};
|
|
733
|
+
for (const child of children) {
|
|
734
|
+
if (child.id.startsWith('link:')) {
|
|
735
|
+
childrenNodeIds[child.alias] = child.id;
|
|
736
|
+
continue;
|
|
737
|
+
}
|
|
738
|
+
if (parentIdsContainSequence(parentIds, parentId, child.id) || parentId === child.id) {
|
|
739
|
+
continue;
|
|
740
|
+
}
|
|
741
|
+
if (ctx.resolvedPkgsById[child.id].isLeaf) {
|
|
742
|
+
childrenNodeIds[child.alias] = child.id;
|
|
743
|
+
continue;
|
|
744
|
+
}
|
|
745
|
+
const childNodeId = nextNodeId();
|
|
746
|
+
childrenNodeIds[child.alias] = childNodeId;
|
|
747
|
+
installable = installable || !ctx.skipped.has(child.id);
|
|
748
|
+
ctx.dependenciesTree.set(childNodeId, {
|
|
749
|
+
children: () => buildTree(ctx, child.id, [...parentIds, child.id], ctx.childrenByParentId[child.id], depth + 1, installable),
|
|
750
|
+
depth,
|
|
751
|
+
installable,
|
|
752
|
+
resolvedPackage: ctx.resolvedPkgsById[child.id],
|
|
753
|
+
});
|
|
754
|
+
}
|
|
755
|
+
return childrenNodeIds;
|
|
756
|
+
}
|
|
757
|
+
async function resolveChildren(ctx, { parentPkg, childrenResolutionId, parentIds, dependencyLockfile, parentDepth, updateDepth, updateMatching, prefix, supportedArchitectures, }, { parentPkgAliases, preferredVersions, publishedBy, }) {
|
|
758
|
+
if (!isCurrentChildrenResolution(ctx, parentPkg.pkgId, childrenResolutionId)) {
|
|
759
|
+
setDependencyTreeNodeWithCurrentChildren(ctx, {
|
|
760
|
+
parentDepth,
|
|
761
|
+
parentIds,
|
|
762
|
+
parentPkg,
|
|
763
|
+
});
|
|
764
|
+
return {
|
|
765
|
+
missingPeers: {},
|
|
766
|
+
resolvedPeers: {},
|
|
767
|
+
};
|
|
768
|
+
}
|
|
567
769
|
const currentResolvedDependencies = (dependencyLockfile != null)
|
|
568
770
|
? {
|
|
569
771
|
...dependencyLockfile.dependencies,
|
|
@@ -593,6 +795,14 @@ async function resolveChildren(ctx, { parentPkg, parentIds, dependencyLockfile,
|
|
|
593
795
|
supportedArchitectures,
|
|
594
796
|
parentIds,
|
|
595
797
|
});
|
|
798
|
+
if (!isCurrentChildrenResolution(ctx, parentPkg.pkgId, childrenResolutionId)) {
|
|
799
|
+
setDependencyTreeNodeWithCurrentChildren(ctx, {
|
|
800
|
+
parentDepth,
|
|
801
|
+
parentIds,
|
|
802
|
+
parentPkg,
|
|
803
|
+
});
|
|
804
|
+
return resolvingPeers;
|
|
805
|
+
}
|
|
596
806
|
ctx.childrenByParentId[parentPkg.pkgId] = pkgAddresses.map((child) => ({
|
|
597
807
|
alias: child.alias,
|
|
598
808
|
id: child.pkgId,
|
|
@@ -617,6 +827,13 @@ async function resolveChildren(ctx, { parentPkg, parentIds, dependencyLockfile,
|
|
|
617
827
|
previousDepPath: parentPkg.previousDepPath,
|
|
618
828
|
resolvedPackage: ctx.resolvedPkgsById[parentPkg.pkgId],
|
|
619
829
|
});
|
|
830
|
+
ctx.nodeResolutionContextByNodeId.set(parentPkg.nodeId, {
|
|
831
|
+
depth: parentDepth,
|
|
832
|
+
installable: parentPkg.installable,
|
|
833
|
+
parentIds,
|
|
834
|
+
pkgId: parentPkg.pkgId,
|
|
835
|
+
});
|
|
836
|
+
updateChildrenResolutionNodes(ctx, parentPkg.pkgId, parentPkg.nodeId);
|
|
620
837
|
return resolvingPeers;
|
|
621
838
|
}
|
|
622
839
|
function getDepsToResolve(wantedDependencies, wantedLockfile, options) {
|
|
@@ -633,12 +850,33 @@ function getDepsToResolve(wantedDependencies, wantedLockfile, options) {
|
|
|
633
850
|
});
|
|
634
851
|
for (const wantedDependency of wantedDependencies) {
|
|
635
852
|
let reference = undefined;
|
|
853
|
+
let preferredVersion = undefined;
|
|
636
854
|
let proceed = proceedAll;
|
|
637
855
|
if (wantedDependency.alias) {
|
|
638
856
|
const satisfiesWanted = satisfiesWanted2Args.bind(null, wantedDependency);
|
|
639
857
|
if (resolvedDependencies[wantedDependency.alias] &&
|
|
640
858
|
(satisfiesWanted(resolvedDependencies[wantedDependency.alias]) || resolvedDependencies[wantedDependency.alias].startsWith('file:'))) {
|
|
641
|
-
|
|
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
|
+
}
|
|
642
880
|
}
|
|
643
881
|
else if (
|
|
644
882
|
// If dependencies that were used by the previous version of the package
|
|
@@ -669,6 +907,7 @@ function getDepsToResolve(wantedDependencies, wantedLockfile, options) {
|
|
|
669
907
|
}
|
|
670
908
|
extendedWantedDeps.push({
|
|
671
909
|
infoFromLockfile,
|
|
910
|
+
preferredVersion,
|
|
672
911
|
proceed,
|
|
673
912
|
wantedDependency,
|
|
674
913
|
});
|
|
@@ -693,6 +932,44 @@ function referenceSatisfiesWantedSpec(opts, wantedDep, preferredRef) {
|
|
|
693
932
|
}
|
|
694
933
|
return semver.satisfies(version, wantedDep.bareSpecifier, true);
|
|
695
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
|
+
}
|
|
696
973
|
function getLockedPeerContext(dependencyLockfile) {
|
|
697
974
|
if (dependencyLockfile.peerDependencies == null)
|
|
698
975
|
return undefined;
|
|
@@ -775,345 +1052,338 @@ async function resolveDependency(wantedDependency, ctx, options) {
|
|
|
775
1052
|
optional: true,
|
|
776
1053
|
};
|
|
777
1054
|
}
|
|
778
|
-
|
|
779
|
-
// (plural) options. If the singular option is passed through, it'll be used
|
|
780
|
-
// instead of the plural option.
|
|
781
|
-
const preferredVersions = !options.updateRequested && options.preferredVersion != null
|
|
782
|
-
? getExactSinglePreferredVersions(wantedDependency, options.preferredVersion)
|
|
783
|
-
: options.preferredVersions;
|
|
1055
|
+
const finishPackageResolution = startPackageResolution(ctx, options.currentDepth);
|
|
784
1056
|
try {
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
1057
|
+
await waitForPackageResolutionTurn(ctx, options.currentDepth);
|
|
1058
|
+
// Normalize the `preferredVersion` (singular) and `preferredVersions`
|
|
1059
|
+
// (plural) options. If the singular option is passed through, it'll be used
|
|
1060
|
+
// instead of the plural option.
|
|
1061
|
+
const preferredVersions = !options.updateRequested && options.preferredVersion != null
|
|
1062
|
+
? getExactSinglePreferredVersions(wantedDependency, options.preferredVersion)
|
|
1063
|
+
: options.preferredVersions;
|
|
1064
|
+
try {
|
|
1065
|
+
const calcSpecifier = options.currentDepth === 0;
|
|
1066
|
+
if (!options.update && currentPkg.version && currentPkg.pkgId?.endsWith(`@${currentPkg.version}`) && !calcSpecifier) {
|
|
1067
|
+
wantedDependency.bareSpecifier = replaceVersionInBareSpecifier(wantedDependency.bareSpecifier, currentPkg.version, ctx.namedRegistryPrefixes);
|
|
1068
|
+
}
|
|
1069
|
+
pkgResponse = await ctx.storeController.requestPackage(wantedDependency, {
|
|
1070
|
+
allowBuild: ctx.allowBuild,
|
|
1071
|
+
alwaysTryWorkspacePackages: ctx.linkWorkspacePackagesDepth >= options.currentDepth,
|
|
1072
|
+
currentPkg: currentPkg
|
|
1073
|
+
? {
|
|
1074
|
+
id: currentPkg.pkgId,
|
|
1075
|
+
name: currentPkg.name,
|
|
1076
|
+
resolution: currentPkg.resolution,
|
|
1077
|
+
version: currentPkg.version,
|
|
1078
|
+
publishedAt: currentPkg.pkgId ? ctx.wantedLockfile.time?.[currentPkg.pkgId] : undefined,
|
|
1079
|
+
}
|
|
1080
|
+
: undefined,
|
|
1081
|
+
expectedPkg: currentPkg,
|
|
1082
|
+
defaultTag: ctx.defaultTag,
|
|
1083
|
+
ignoreScripts: ctx.ignoreScripts,
|
|
1084
|
+
publishedBy: options.publishedBy,
|
|
1085
|
+
publishedByExclude: ctx.publishedByExclude,
|
|
1086
|
+
pickLowestVersion: options.pickLowestVersion,
|
|
1087
|
+
downloadPriority: -options.currentDepth,
|
|
1088
|
+
lockfileDir: ctx.lockfileDir,
|
|
1089
|
+
preferredVersions,
|
|
1090
|
+
preferWorkspacePackages: ctx.preferWorkspacePackages,
|
|
1091
|
+
projectDir: (options.currentDepth > 0 &&
|
|
1092
|
+
!wantedDependency.bareSpecifier.startsWith('file:'))
|
|
1093
|
+
? ctx.lockfileDir
|
|
1094
|
+
: options.parentPkg.rootDir,
|
|
1095
|
+
skipFetch: ctx.dryRun,
|
|
1096
|
+
trustPolicy: ctx.trustPolicy,
|
|
1097
|
+
trustPolicyExclude: ctx.trustPolicyExclude,
|
|
1098
|
+
trustPolicyIgnoreAfter: ctx.trustPolicyIgnoreAfter,
|
|
1099
|
+
update: options.update,
|
|
1100
|
+
updateChecksums: options.updateChecksums,
|
|
1101
|
+
workspacePackages: ctx.workspacePackages,
|
|
1102
|
+
supportedArchitectures: options.supportedArchitectures,
|
|
1103
|
+
onFetchError: (err) => {
|
|
1104
|
+
err.prefix = options.prefix;
|
|
1105
|
+
err.pkgsStack = getPkgsInfoFromIds(options.parentIds, ctx.resolvedPkgsById);
|
|
1106
|
+
return err;
|
|
1107
|
+
},
|
|
1108
|
+
injectWorkspacePackages: ctx.injectWorkspacePackages,
|
|
1109
|
+
calcSpecifier,
|
|
1110
|
+
pinnedVersion: options.pinnedVersion,
|
|
1111
|
+
});
|
|
788
1112
|
}
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
?
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
:
|
|
815
|
-
|
|
816
|
-
trustPolicy: ctx.trustPolicy,
|
|
817
|
-
trustPolicyExclude: ctx.trustPolicyExclude,
|
|
818
|
-
trustPolicyIgnoreAfter: ctx.trustPolicyIgnoreAfter,
|
|
819
|
-
update: options.update,
|
|
820
|
-
updateChecksums: options.updateChecksums,
|
|
821
|
-
workspacePackages: ctx.workspacePackages,
|
|
822
|
-
supportedArchitectures: options.supportedArchitectures,
|
|
823
|
-
onFetchError: (err) => {
|
|
824
|
-
err.prefix = options.prefix;
|
|
825
|
-
err.pkgsStack = getPkgsInfoFromIds(options.parentIds, ctx.resolvedPkgsById);
|
|
826
|
-
return err;
|
|
1113
|
+
catch (err) { // eslint-disable-line
|
|
1114
|
+
const wantedDependencyDetails = {
|
|
1115
|
+
name: wantedDependency.alias,
|
|
1116
|
+
bareSpecifier: wantedDependency.bareSpecifier,
|
|
1117
|
+
version: wantedDependency.alias ? wantedDependency.bareSpecifier : undefined,
|
|
1118
|
+
};
|
|
1119
|
+
if (wantedDependency.optional && err.code !== 'ERR_PNPM_TRUST_DOWNGRADE') {
|
|
1120
|
+
skippedOptionalDependencyLogger.debug({
|
|
1121
|
+
details: err.toString(),
|
|
1122
|
+
package: wantedDependencyDetails,
|
|
1123
|
+
parents: getPkgsInfoFromIds(options.parentIds, ctx.resolvedPkgsById),
|
|
1124
|
+
prefix: options.prefix,
|
|
1125
|
+
reason: 'resolution_failure',
|
|
1126
|
+
});
|
|
1127
|
+
return null;
|
|
1128
|
+
}
|
|
1129
|
+
err.package = wantedDependencyDetails;
|
|
1130
|
+
err.prefix = options.prefix;
|
|
1131
|
+
err.pkgsStack = getPkgsInfoFromIds(options.parentIds, ctx.resolvedPkgsById);
|
|
1132
|
+
throw err;
|
|
1133
|
+
}
|
|
1134
|
+
dependencyResolvedLogger.debug({
|
|
1135
|
+
resolution: pkgResponse.body.id,
|
|
1136
|
+
wanted: {
|
|
1137
|
+
dependentId: options.parentPkg.pkgId,
|
|
1138
|
+
name: wantedDependency.alias,
|
|
1139
|
+
rawSpec: wantedDependency.bareSpecifier,
|
|
827
1140
|
},
|
|
828
|
-
injectWorkspacePackages: ctx.injectWorkspacePackages,
|
|
829
|
-
calcSpecifier,
|
|
830
|
-
pinnedVersion: options.pinnedVersion,
|
|
831
1141
|
});
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
};
|
|
839
|
-
if (wantedDependency.optional && err.code !== 'ERR_PNPM_TRUST_DOWNGRADE') {
|
|
840
|
-
skippedOptionalDependencyLogger.debug({
|
|
841
|
-
details: err.toString(),
|
|
842
|
-
package: wantedDependencyDetails,
|
|
843
|
-
parents: getPkgsInfoFromIds(options.parentIds, ctx.resolvedPkgsById),
|
|
844
|
-
prefix: options.prefix,
|
|
845
|
-
reason: 'resolution_failure',
|
|
846
|
-
});
|
|
847
|
-
return null;
|
|
1142
|
+
// Resolver-inline policy violations (e.g. minimumReleaseAge) flow up
|
|
1143
|
+
// here; collect them onto the shared context so resolveDependencyTree
|
|
1144
|
+
// can hand the full set to the install command between
|
|
1145
|
+
// resolveDependencyTree and resolvePeers.
|
|
1146
|
+
if (pkgResponse.body.policyViolation) {
|
|
1147
|
+
ctx.resolutionPolicyViolations.push(pkgResponse.body.policyViolation);
|
|
848
1148
|
}
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
name: wantedDependency.alias,
|
|
859
|
-
rawSpec: wantedDependency.bareSpecifier,
|
|
860
|
-
},
|
|
861
|
-
});
|
|
862
|
-
// Resolver-inline policy violations (e.g. minimumReleaseAge) flow up
|
|
863
|
-
// here; collect them onto the shared context so resolveDependencyTree
|
|
864
|
-
// can hand the full set to the install command between
|
|
865
|
-
// resolveDependencyTree and resolvePeers.
|
|
866
|
-
if (pkgResponse.body.policyViolation) {
|
|
867
|
-
ctx.resolutionPolicyViolations.push(pkgResponse.body.policyViolation);
|
|
868
|
-
}
|
|
869
|
-
// Check if exotic dependencies are disallowed in subdependencies
|
|
870
|
-
if (ctx.blockExoticSubdeps &&
|
|
871
|
-
options.currentDepth > 0 &&
|
|
872
|
-
pkgResponse.body.resolvedVia != null && // This is already coming from the lockfile, we skip the check in this case for now. Should be fixed later.
|
|
873
|
-
isExoticDep(pkgResponse.body.resolvedVia)) {
|
|
874
|
-
const error = new PnpmError('EXOTIC_SUBDEP', `Exotic dependency "${wantedDependency.alias ?? wantedDependency.bareSpecifier}" (resolved via ${pkgResponse.body.resolvedVia}) is not allowed in subdependencies when blockExoticSubdeps is enabled`);
|
|
875
|
-
error.prefix = options.prefix;
|
|
876
|
-
error.pkgsStack = getPkgsInfoFromIds(options.parentIds, ctx.resolvedPkgsById);
|
|
877
|
-
throw error;
|
|
878
|
-
}
|
|
879
|
-
if (ctx.allPreferredVersions && pkgResponse.body.manifest?.version) {
|
|
880
|
-
if (!ctx.allPreferredVersions[pkgResponse.body.manifest.name]) {
|
|
881
|
-
ctx.allPreferredVersions[pkgResponse.body.manifest.name] = {};
|
|
1149
|
+
// Check if exotic dependencies are disallowed in subdependencies
|
|
1150
|
+
if (ctx.blockExoticSubdeps &&
|
|
1151
|
+
options.currentDepth > 0 &&
|
|
1152
|
+
pkgResponse.body.resolvedVia != null && // This is already coming from the lockfile, we skip the check in this case for now. Should be fixed later.
|
|
1153
|
+
isExoticDep(pkgResponse.body.resolvedVia)) {
|
|
1154
|
+
const error = new PnpmError('EXOTIC_SUBDEP', `Exotic dependency "${wantedDependency.alias ?? wantedDependency.bareSpecifier}" (resolved via ${pkgResponse.body.resolvedVia}) is not allowed in subdependencies when blockExoticSubdeps is enabled`);
|
|
1155
|
+
error.prefix = options.prefix;
|
|
1156
|
+
error.pkgsStack = getPkgsInfoFromIds(options.parentIds, ctx.resolvedPkgsById);
|
|
1157
|
+
throw error;
|
|
882
1158
|
}
|
|
883
|
-
ctx.allPreferredVersions
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
return null;
|
|
889
|
-
}
|
|
890
|
-
if (pkgResponse.body.isLocal) {
|
|
891
|
-
if (!pkgResponse.body.manifest) {
|
|
892
|
-
// This should actually never happen because the local-resolver returns a manifest
|
|
893
|
-
// even if no real manifest exists in the filesystem.
|
|
894
|
-
throw new PnpmError('MISSING_PACKAGE_JSON', `Can't install ${wantedDependency.bareSpecifier}: Missing package.json file`);
|
|
1159
|
+
if (ctx.allPreferredVersions && pkgResponse.body.manifest?.version) {
|
|
1160
|
+
if (!ctx.allPreferredVersions[pkgResponse.body.manifest.name]) {
|
|
1161
|
+
ctx.allPreferredVersions[pkgResponse.body.manifest.name] = {};
|
|
1162
|
+
}
|
|
1163
|
+
ctx.allPreferredVersions[pkgResponse.body.manifest.name][pkgResponse.body.manifest.version] = 'version';
|
|
895
1164
|
}
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
name: pkgResponse.body.manifest.name,
|
|
901
|
-
optional: wantedDependency.optional,
|
|
902
|
-
pkgId: pkgResponse.body.id,
|
|
903
|
-
resolution: pkgResponse.body.resolution,
|
|
904
|
-
version: pkgResponse.body.manifest.version,
|
|
905
|
-
normalizedBareSpecifier: pkgResponse.body.normalizedBareSpecifier,
|
|
906
|
-
pkg: pkgResponse.body.manifest,
|
|
907
|
-
};
|
|
908
|
-
}
|
|
909
|
-
let prepare;
|
|
910
|
-
let hasBin;
|
|
911
|
-
let pkg = getManifestFromResponse(pkgResponse, wantedDependency, currentPkg);
|
|
912
|
-
if (!pkg.dependencies) {
|
|
913
|
-
pkg.dependencies = {};
|
|
914
|
-
}
|
|
915
|
-
if (ctx.readPackageHook != null) {
|
|
916
|
-
pkg = await ctx.readPackageHook(pkg);
|
|
917
|
-
}
|
|
918
|
-
if (pkg.peerDependencies && pkg.dependencies) {
|
|
919
|
-
if (ctx.autoInstallPeers) {
|
|
920
|
-
pkg = {
|
|
921
|
-
...pkg,
|
|
922
|
-
dependencies: omit(Object.keys(pkg.peerDependencies), pkg.dependencies),
|
|
923
|
-
};
|
|
1165
|
+
if (!pkgResponse.body.updated &&
|
|
1166
|
+
options.currentDepth === Math.max(0, options.updateDepth) &&
|
|
1167
|
+
depIsLinked && !ctx.force && !options.proceed) {
|
|
1168
|
+
return null;
|
|
924
1169
|
}
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
1170
|
+
if (pkgResponse.body.isLocal) {
|
|
1171
|
+
if (!pkgResponse.body.manifest) {
|
|
1172
|
+
// This should actually never happen because the local-resolver returns a manifest
|
|
1173
|
+
// even if no real manifest exists in the filesystem.
|
|
1174
|
+
throw new PnpmError('MISSING_PACKAGE_JSON', `Can't install ${wantedDependency.bareSpecifier}: Missing package.json file`);
|
|
1175
|
+
}
|
|
1176
|
+
return {
|
|
1177
|
+
alias: wantedDependency.alias ?? pkgResponse.body.alias ?? pkgResponse.body.manifest.name ?? path.basename(pkgResponse.body.resolution.directory),
|
|
1178
|
+
dev: wantedDependency.dev,
|
|
1179
|
+
isLinkedDependency: true,
|
|
1180
|
+
name: pkgResponse.body.manifest.name,
|
|
1181
|
+
optional: wantedDependency.optional,
|
|
1182
|
+
pkgId: pkgResponse.body.id,
|
|
1183
|
+
resolution: pkgResponse.body.resolution,
|
|
1184
|
+
version: pkgResponse.body.manifest.version,
|
|
1185
|
+
normalizedBareSpecifier: pkgResponse.body.normalizedBareSpecifier,
|
|
1186
|
+
pkg: pkgResponse.body.manifest,
|
|
929
1187
|
};
|
|
930
1188
|
}
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
throw new PnpmError('MISSING_PACKAGE_NAME', `Can't install ${wantedDependency.bareSpecifier}: Missing package name`);
|
|
937
|
-
}
|
|
938
|
-
let pkgIdWithPatchHash = (pkgResponse.body.id.startsWith(`${pkg.name}@`) ? pkgResponse.body.id : `${pkg.name}@${pkgResponse.body.id}`);
|
|
939
|
-
const patch = getPatchInfo(ctx.patchedDependencies, pkg.name, pkg.version);
|
|
940
|
-
if (patch) {
|
|
941
|
-
ctx.appliedPatches.add(patch.key);
|
|
942
|
-
pkgIdWithPatchHash = `${pkgIdWithPatchHash}(patch_hash=${patch.hash})`;
|
|
943
|
-
}
|
|
944
|
-
// We are building the dependency tree only until there are new packages
|
|
945
|
-
// or the packages repeat in a unique order.
|
|
946
|
-
// This is needed later during peer dependencies resolution.
|
|
947
|
-
//
|
|
948
|
-
// So we resolve foo > bar > qar > foo
|
|
949
|
-
// But we stop on foo > bar > qar > foo > qar
|
|
950
|
-
// In the second example, there's no reason to walk qar again
|
|
951
|
-
// when qar is included the first time, the dependencies of foo
|
|
952
|
-
// are already resolved and included as parent dependencies of qar.
|
|
953
|
-
// So during peers resolution, qar cannot possibly get any new or different
|
|
954
|
-
// peers resolved, after the first occurrence.
|
|
955
|
-
//
|
|
956
|
-
// However, in the next example we would analyze the second qar as well,
|
|
957
|
-
// because zoo is a new parent package:
|
|
958
|
-
// foo > bar > qar > zoo > qar
|
|
959
|
-
if (parentIdsContainSequence(options.parentIds, options.parentPkg.pkgId, pkgResponse.body.id) || pkgResponse.body.id === options.parentPkg.pkgId) {
|
|
960
|
-
return null;
|
|
961
|
-
}
|
|
962
|
-
if (!options.update && (currentPkg.dependencyLockfile != null) && currentPkg.depPath &&
|
|
963
|
-
!pkgResponse.body.updated &&
|
|
964
|
-
// peerDependencies field is also used for transitive peer dependencies which should not be linked
|
|
965
|
-
// That's why we cannot omit reading package.json of such dependencies.
|
|
966
|
-
// This can be removed if we implement something like peerDependenciesMeta.transitive: true
|
|
967
|
-
(currentPkg.dependencyLockfile.peerDependencies == null)) {
|
|
968
|
-
hasBin = currentPkg.dependencyLockfile.hasBin === true;
|
|
969
|
-
pkg = {
|
|
970
|
-
...nameVerFromPkgSnapshot(currentPkg.depPath, currentPkg.dependencyLockfile),
|
|
971
|
-
...omitDepsFields(currentPkg.dependencyLockfile),
|
|
972
|
-
...pkg,
|
|
973
|
-
};
|
|
974
|
-
}
|
|
975
|
-
else {
|
|
976
|
-
prepare = Boolean(pkgResponse.body.resolvedVia === 'git-repository' &&
|
|
977
|
-
typeof pkg.scripts?.prepare === 'string');
|
|
978
|
-
if (currentPkg.dependencyLockfile?.deprecated &&
|
|
979
|
-
!pkgResponse.body.updated && !pkg.deprecated) {
|
|
980
|
-
pkg.deprecated = currentPkg.dependencyLockfile.deprecated;
|
|
1189
|
+
let prepare;
|
|
1190
|
+
let hasBin;
|
|
1191
|
+
let pkg = getManifestFromResponse(pkgResponse, wantedDependency, currentPkg);
|
|
1192
|
+
if (!pkg.dependencies) {
|
|
1193
|
+
pkg.dependencies = {};
|
|
981
1194
|
}
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
: Boolean((pkg.bin && !(pkg.bin === '' || Object.keys(pkg.bin).length === 0)) ?? pkg.directories?.bin);
|
|
985
|
-
}
|
|
986
|
-
if (options.currentDepth === 0 && pkgResponse.body.latest && pkgResponse.body.latest !== pkg.version) {
|
|
987
|
-
ctx.outdatedDependencies[pkgResponse.body.id] = pkgResponse.body.latest;
|
|
988
|
-
}
|
|
989
|
-
if (pkg.peerDependencies != null) {
|
|
990
|
-
for (const name in pkg.peerDependencies) {
|
|
991
|
-
ctx.allPeerDepNames.add(name);
|
|
1195
|
+
if (ctx.readPackageHook != null) {
|
|
1196
|
+
pkg = await ctx.readPackageHook(pkg);
|
|
992
1197
|
}
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
1198
|
+
if (pkg.peerDependencies && pkg.dependencies) {
|
|
1199
|
+
if (ctx.autoInstallPeers) {
|
|
1200
|
+
pkg = {
|
|
1201
|
+
...pkg,
|
|
1202
|
+
dependencies: omit(Object.keys(pkg.peerDependencies), pkg.dependencies),
|
|
1203
|
+
};
|
|
1204
|
+
}
|
|
1205
|
+
else {
|
|
1206
|
+
pkg = {
|
|
1207
|
+
...pkg,
|
|
1208
|
+
dependencies: omit(Object.keys(pkg.peerDependencies).filter((peerDep) => options.parentPkgAliases[peerDep]), pkg.dependencies),
|
|
1209
|
+
};
|
|
1210
|
+
}
|
|
997
1211
|
}
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
// we only ever need to analyze one leaf dep in a graph, so the nodeId can be short and stateless.
|
|
1001
|
-
const nodeId = pkgIsLeaf(pkg) ? pkgResponse.body.id : nextNodeId();
|
|
1002
|
-
const parentIsInstallable = options.parentPkg.installable === undefined || options.parentPkg.installable;
|
|
1003
|
-
const installable = parentIsInstallable && pkgResponse.body.isInstallable !== false;
|
|
1004
|
-
const isNew = !ctx.resolvedPkgsById[pkgResponse.body.id];
|
|
1005
|
-
const parentImporterId = options.parentIds[0];
|
|
1006
|
-
const currentIsOptional = wantedDependency.optional || options.parentPkg.optional;
|
|
1007
|
-
if (isNew) {
|
|
1008
|
-
if (pkg.deprecated &&
|
|
1009
|
-
(!ctx.allowedDeprecatedVersions[pkg.name] || !semver.satisfies(pkg.version, ctx.allowedDeprecatedVersions[pkg.name]))) {
|
|
1010
|
-
// Report deprecated packages only on first occurrence.
|
|
1011
|
-
deprecationLogger.debug({
|
|
1012
|
-
deprecated: pkg.deprecated,
|
|
1013
|
-
depth: options.currentDepth,
|
|
1014
|
-
pkgId: pkgResponse.body.id,
|
|
1015
|
-
pkgName: pkg.name,
|
|
1016
|
-
pkgVersion: pkg.version,
|
|
1017
|
-
prefix: options.prefix,
|
|
1018
|
-
});
|
|
1212
|
+
if (pkg.engines?.runtime != null) {
|
|
1213
|
+
convertEnginesRuntimeToDependencies(pkg, 'engines', 'dependencies');
|
|
1019
1214
|
}
|
|
1020
|
-
if (
|
|
1021
|
-
|
|
1215
|
+
if (!pkg.name) { // TODO: don't fail on optional dependencies
|
|
1216
|
+
throw new PnpmError('MISSING_PACKAGE_NAME', `Can't install ${wantedDependency.bareSpecifier}: Missing package name`);
|
|
1022
1217
|
}
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
//
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
ctx.resolvedPkgsById[pkgResponse.body.id].dev = ctx.resolvedPkgsById[pkgResponse.body.id].dev || wantedDependency.dev;
|
|
1047
|
-
ctx.resolvedPkgsById[pkgResponse.body.id].optional = ctx.resolvedPkgsById[pkgResponse.body.id].optional && currentIsOptional;
|
|
1048
|
-
if (ctx.resolvedPkgsById[pkgResponse.body.id].fetching == null && pkgResponse.fetching != null) {
|
|
1049
|
-
ctx.resolvedPkgsById[pkgResponse.body.id].fetching = pkgResponse.fetching;
|
|
1050
|
-
ctx.resolvedPkgsById[pkgResponse.body.id].filesIndexFile = pkgResponse.filesIndexFile;
|
|
1218
|
+
let pkgIdWithPatchHash = (pkgResponse.body.id.startsWith(`${pkg.name}@`) ? pkgResponse.body.id : `${pkg.name}@${pkgResponse.body.id}`);
|
|
1219
|
+
const patch = getPatchInfo(ctx.patchedDependencies, pkg.name, pkg.version);
|
|
1220
|
+
if (patch) {
|
|
1221
|
+
ctx.appliedPatches.add(patch.key);
|
|
1222
|
+
pkgIdWithPatchHash = `${pkgIdWithPatchHash}(patch_hash=${patch.hash})`;
|
|
1223
|
+
}
|
|
1224
|
+
// We are building the dependency tree only until there are new packages
|
|
1225
|
+
// or the packages repeat in a unique order.
|
|
1226
|
+
// This is needed later during peer dependencies resolution.
|
|
1227
|
+
//
|
|
1228
|
+
// So we resolve foo > bar > qar > foo
|
|
1229
|
+
// But we stop on foo > bar > qar > foo > qar
|
|
1230
|
+
// In the second example, there's no reason to walk qar again
|
|
1231
|
+
// when qar is included the first time, the dependencies of foo
|
|
1232
|
+
// are already resolved and included as parent dependencies of qar.
|
|
1233
|
+
// So during peers resolution, qar cannot possibly get any new or different
|
|
1234
|
+
// peers resolved, after the first occurrence.
|
|
1235
|
+
//
|
|
1236
|
+
// However, in the next example we would analyze the second qar as well,
|
|
1237
|
+
// because zoo is a new parent package:
|
|
1238
|
+
// foo > bar > qar > zoo > qar
|
|
1239
|
+
if (parentIdsContainSequence(options.parentIds, options.parentPkg.pkgId, pkgResponse.body.id) || pkgResponse.body.id === options.parentPkg.pkgId) {
|
|
1240
|
+
return null;
|
|
1051
1241
|
}
|
|
1052
|
-
if (
|
|
1053
|
-
|
|
1242
|
+
if (!options.update && (currentPkg.dependencyLockfile != null) && currentPkg.depPath &&
|
|
1243
|
+
!pkgResponse.body.updated &&
|
|
1244
|
+
// peerDependencies field is also used for transitive peer dependencies which should not be linked
|
|
1245
|
+
// That's why we cannot omit reading package.json of such dependencies.
|
|
1246
|
+
// This can be removed if we implement something like peerDependenciesMeta.transitive: true
|
|
1247
|
+
(currentPkg.dependencyLockfile.peerDependencies == null)) {
|
|
1248
|
+
hasBin = currentPkg.dependencyLockfile.hasBin === true;
|
|
1249
|
+
pkg = {
|
|
1250
|
+
...nameVerFromPkgSnapshot(currentPkg.depPath, currentPkg.dependencyLockfile),
|
|
1251
|
+
...omitDepsFields(currentPkg.dependencyLockfile),
|
|
1252
|
+
...pkg,
|
|
1253
|
+
};
|
|
1054
1254
|
}
|
|
1055
1255
|
else {
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
});
|
|
1256
|
+
prepare = Boolean(pkgResponse.body.resolvedVia === 'git-repository' &&
|
|
1257
|
+
typeof pkg.scripts?.prepare === 'string');
|
|
1258
|
+
if (currentPkg.dependencyLockfile?.deprecated &&
|
|
1259
|
+
!pkgResponse.body.updated && !pkg.deprecated) {
|
|
1260
|
+
pkg.deprecated = currentPkg.dependencyLockfile.deprecated;
|
|
1261
|
+
}
|
|
1262
|
+
hasBin = (currentPkg.dependencyLockfile?.hasBin != null && !pkg.bin)
|
|
1263
|
+
? currentPkg.dependencyLockfile.hasBin
|
|
1264
|
+
: Boolean((pkg.bin && !(pkg.bin === '' || Object.keys(pkg.bin).length === 0)) ?? pkg.directories?.bin);
|
|
1066
1265
|
}
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1266
|
+
if (options.currentDepth === 0 && pkgResponse.body.latest && pkgResponse.body.latest !== pkg.version) {
|
|
1267
|
+
ctx.outdatedDependencies[pkgResponse.body.id] = pkgResponse.body.latest;
|
|
1268
|
+
}
|
|
1269
|
+
if (pkg.peerDependencies != null) {
|
|
1270
|
+
for (const name in pkg.peerDependencies) {
|
|
1271
|
+
ctx.allPeerDepNames.add(name);
|
|
1272
|
+
}
|
|
1273
|
+
}
|
|
1274
|
+
if (pkg.peerDependenciesMeta != null) {
|
|
1275
|
+
for (const name in pkg.peerDependenciesMeta) {
|
|
1276
|
+
ctx.allPeerDepNames.add(name);
|
|
1277
|
+
}
|
|
1278
|
+
}
|
|
1279
|
+
// In case of leaf dependencies (dependencies that have no prod deps or peer deps),
|
|
1280
|
+
// we only ever need to analyze one leaf dep in a graph, so the nodeId can be short and stateless.
|
|
1281
|
+
const nodeId = pkgIsLeaf(pkg) ? pkgResponse.body.id : nextNodeId();
|
|
1282
|
+
const parentIsInstallable = options.parentPkg.installable === undefined || options.parentPkg.installable;
|
|
1283
|
+
const installable = parentIsInstallable && pkgResponse.body.isInstallable !== false;
|
|
1284
|
+
const packageIsNew = !ctx.resolvedPkgsById[pkgResponse.body.id];
|
|
1285
|
+
const parentImporterId = options.parentIds[0];
|
|
1286
|
+
const currentIsOptional = wantedDependency.optional || options.parentPkg.optional;
|
|
1287
|
+
const childrenResolution = claimChildrenResolution(ctx, {
|
|
1288
|
+
currentDepth: options.currentDepth,
|
|
1289
|
+
parentIds: options.parentIds,
|
|
1290
|
+
pkgId: pkgResponse.body.id,
|
|
1291
|
+
});
|
|
1292
|
+
const isNew = childrenResolution.isOwner;
|
|
1293
|
+
if (packageIsNew) {
|
|
1294
|
+
if (pkg.deprecated &&
|
|
1295
|
+
(!ctx.allowedDeprecatedVersions[pkg.name] || !semver.satisfies(pkg.version, ctx.allowedDeprecatedVersions[pkg.name]))) {
|
|
1296
|
+
// Report deprecated packages only on first occurrence.
|
|
1297
|
+
deprecationLogger.debug({
|
|
1298
|
+
deprecated: pkg.deprecated,
|
|
1299
|
+
depth: options.currentDepth,
|
|
1300
|
+
pkgId: pkgResponse.body.id,
|
|
1301
|
+
pkgName: pkg.name,
|
|
1302
|
+
pkgVersion: pkg.version,
|
|
1303
|
+
prefix: options.prefix,
|
|
1304
|
+
});
|
|
1305
|
+
}
|
|
1306
|
+
if (pkgResponse.body.isInstallable === false || !parentIsInstallable) {
|
|
1307
|
+
ctx.skipped.add(pkgResponse.body.id);
|
|
1080
1308
|
}
|
|
1309
|
+
progressLogger.debug({
|
|
1310
|
+
packageId: pkgResponse.body.id,
|
|
1311
|
+
requester: ctx.lockfileDir,
|
|
1312
|
+
status: 'resolved',
|
|
1313
|
+
});
|
|
1314
|
+
// WARN: It is very important to keep this sync
|
|
1315
|
+
// Otherwise, deprecation messages for the same package might get written several times
|
|
1316
|
+
ctx.resolvedPkgsById[pkgResponse.body.id] = getResolvedPackage({
|
|
1317
|
+
dependencyLockfile: currentPkg.dependencyLockfile,
|
|
1318
|
+
pkgIdWithPatchHash,
|
|
1319
|
+
force: ctx.force,
|
|
1320
|
+
hasBin,
|
|
1321
|
+
patch,
|
|
1322
|
+
pkg,
|
|
1323
|
+
pkgResponse,
|
|
1324
|
+
prepare,
|
|
1325
|
+
wantedDependency,
|
|
1326
|
+
parentImporterId,
|
|
1327
|
+
optional: currentIsOptional,
|
|
1328
|
+
});
|
|
1081
1329
|
}
|
|
1082
1330
|
else {
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1331
|
+
ctx.resolvedPkgsById[pkgResponse.body.id].prod = ctx.resolvedPkgsById[pkgResponse.body.id].prod || !wantedDependency.dev && !wantedDependency.optional;
|
|
1332
|
+
ctx.resolvedPkgsById[pkgResponse.body.id].dev = ctx.resolvedPkgsById[pkgResponse.body.id].dev || wantedDependency.dev;
|
|
1333
|
+
ctx.resolvedPkgsById[pkgResponse.body.id].optional = ctx.resolvedPkgsById[pkgResponse.body.id].optional && currentIsOptional;
|
|
1334
|
+
if (ctx.resolvedPkgsById[pkgResponse.body.id].fetching == null && pkgResponse.fetching != null) {
|
|
1335
|
+
ctx.resolvedPkgsById[pkgResponse.body.id].fetching = pkgResponse.fetching;
|
|
1336
|
+
ctx.resolvedPkgsById[pkgResponse.body.id].filesIndexFile = pkgResponse.filesIndexFile;
|
|
1337
|
+
}
|
|
1338
|
+
if (!isNew) {
|
|
1339
|
+
if (ctx.dependenciesTree.has(nodeId)) {
|
|
1340
|
+
ctx.dependenciesTree.get(nodeId).depth = Math.min(ctx.dependenciesTree.get(nodeId).depth, options.currentDepth);
|
|
1341
|
+
}
|
|
1342
|
+
else {
|
|
1343
|
+
ctx.pendingNodes.push({
|
|
1344
|
+
alias: wantedDependency.alias ?? pkgResponse.body.alias ?? pkg.name,
|
|
1345
|
+
depth: options.currentDepth,
|
|
1346
|
+
parentIds: options.parentIds,
|
|
1347
|
+
installable,
|
|
1348
|
+
lockedPeerContext: currentPkg.lockedPeerContext,
|
|
1349
|
+
previousDepPath: currentPkg.depPath,
|
|
1350
|
+
nodeId,
|
|
1351
|
+
resolvedPackage: ctx.resolvedPkgsById[pkgResponse.body.id],
|
|
1352
|
+
});
|
|
1353
|
+
}
|
|
1354
|
+
}
|
|
1093
1355
|
}
|
|
1356
|
+
const rootDir = pkgResponse.body.resolution.type === 'directory'
|
|
1357
|
+
? path.resolve(ctx.lockfileDir, pkgResponse.body.resolution.directory)
|
|
1358
|
+
: options.prefix;
|
|
1359
|
+
const missingPeersOfChildren = childrenResolution.missingPeersOfChildren;
|
|
1360
|
+
const resolvedPkg = ctx.resolvedPkgsById[pkgResponse.body.id];
|
|
1361
|
+
return {
|
|
1362
|
+
alias: wantedDependency.alias ?? pkgResponse.body.alias ?? pkg.name,
|
|
1363
|
+
depIsLinked,
|
|
1364
|
+
resolvedVia: pkgResponse.body.resolvedVia,
|
|
1365
|
+
isNew,
|
|
1366
|
+
nodeId,
|
|
1367
|
+
normalizedBareSpecifier: pkgResponse.body.normalizedBareSpecifier,
|
|
1368
|
+
missingPeersOfChildren,
|
|
1369
|
+
childrenResolutionId: childrenResolution.id,
|
|
1370
|
+
pkgId: pkgResponse.body.id,
|
|
1371
|
+
rootDir,
|
|
1372
|
+
missingPeers: getMissingPeers(pkg),
|
|
1373
|
+
optional: resolvedPkg.optional,
|
|
1374
|
+
version: resolvedPkg.version,
|
|
1375
|
+
saveCatalogName: wantedDependency.saveCatalogName,
|
|
1376
|
+
// Next fields are actually only needed when isNew = true
|
|
1377
|
+
installable,
|
|
1378
|
+
isLinkedDependency: undefined,
|
|
1379
|
+
pkg,
|
|
1380
|
+
updated: pkgResponse.body.updated,
|
|
1381
|
+
publishedAt: pkgResponse.body.publishedAt,
|
|
1382
|
+
};
|
|
1383
|
+
}
|
|
1384
|
+
finally {
|
|
1385
|
+
finishPackageResolution();
|
|
1094
1386
|
}
|
|
1095
|
-
const resolvedPkg = ctx.resolvedPkgsById[pkgResponse.body.id];
|
|
1096
|
-
return {
|
|
1097
|
-
alias: wantedDependency.alias ?? pkgResponse.body.alias ?? pkg.name,
|
|
1098
|
-
depIsLinked,
|
|
1099
|
-
resolvedVia: pkgResponse.body.resolvedVia,
|
|
1100
|
-
isNew,
|
|
1101
|
-
nodeId,
|
|
1102
|
-
normalizedBareSpecifier: pkgResponse.body.normalizedBareSpecifier,
|
|
1103
|
-
missingPeersOfChildren,
|
|
1104
|
-
pkgId: pkgResponse.body.id,
|
|
1105
|
-
rootDir,
|
|
1106
|
-
missingPeers: getMissingPeers(pkg),
|
|
1107
|
-
optional: resolvedPkg.optional,
|
|
1108
|
-
version: resolvedPkg.version,
|
|
1109
|
-
saveCatalogName: wantedDependency.saveCatalogName,
|
|
1110
|
-
// Next fields are actually only needed when isNew = true
|
|
1111
|
-
installable,
|
|
1112
|
-
isLinkedDependency: undefined,
|
|
1113
|
-
pkg,
|
|
1114
|
-
updated: pkgResponse.body.updated,
|
|
1115
|
-
publishedAt: pkgResponse.body.publishedAt,
|
|
1116
|
-
};
|
|
1117
1387
|
}
|
|
1118
1388
|
export function getManifestFromResponse(pkgResponse, wantedDependency, currentPkg) {
|
|
1119
1389
|
if (pkgResponse.body.manifest)
|