@pnpm/installing.deps-resolver 1100.2.4 → 1100.2.6
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/getNonDevWantedDependencies.d.ts +2 -0
- package/lib/index.js +16 -0
- package/lib/resolveDependencies.d.ts +20 -0
- package/lib/resolveDependencies.js +40 -7
- package/lib/resolveDependencyTree.d.ts +5 -0
- package/lib/resolveDependencyTree.js +1 -0
- package/lib/updateProjectManifest.js +12 -7
- package/package.json +24 -24
|
@@ -6,6 +6,8 @@ export interface WantedDependency {
|
|
|
6
6
|
optional: boolean;
|
|
7
7
|
injected?: boolean;
|
|
8
8
|
saveCatalogName?: string;
|
|
9
|
+
/** Whether this dependency's spec should be (re)written to the manifest. */
|
|
10
|
+
updateSpec?: boolean;
|
|
9
11
|
}
|
|
10
12
|
type GetNonDevWantedDependenciesManifest = Pick<DependencyManifest, 'bundleDependencies' | 'bundledDependencies' | 'optionalDependencies' | 'dependencies' | 'dependenciesMeta'> & {
|
|
11
13
|
name?: string;
|
package/lib/index.js
CHANGED
|
@@ -221,6 +221,7 @@ export async function resolveDependencies(importers, opts) {
|
|
|
221
221
|
}
|
|
222
222
|
}
|
|
223
223
|
}
|
|
224
|
+
await waitForResolutionFetches(resolvedPkgsById);
|
|
224
225
|
const newLockfile = updateLockfile({
|
|
225
226
|
dependenciesGraph,
|
|
226
227
|
lockfile: opts.wantedLockfile,
|
|
@@ -334,6 +335,21 @@ function alignDependencyTypes(manifest, projectSnapshot) {
|
|
|
334
335
|
}
|
|
335
336
|
}
|
|
336
337
|
}
|
|
338
|
+
/**
|
|
339
|
+
* Waits for fetches that complete resolution data used by the lockfile snapshot and
|
|
340
|
+
* virtual-store paths. Other package fetches are awaited later by `waitTillAllFetchingsFinish`.
|
|
341
|
+
*/
|
|
342
|
+
async function waitForResolutionFetches(resolvedPkgsById) {
|
|
343
|
+
const fetches = [];
|
|
344
|
+
for (const pkg of Object.values(resolvedPkgsById)) {
|
|
345
|
+
if (pkg.resolutionNeedsFetch && pkg.fetching != null) {
|
|
346
|
+
fetches.push(pkg.fetching());
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
if (fetches.length > 0) {
|
|
350
|
+
await Promise.all(fetches);
|
|
351
|
+
}
|
|
352
|
+
}
|
|
337
353
|
function getAliasToDependencyTypeMap(manifest) {
|
|
338
354
|
const depTypesOfAliases = {};
|
|
339
355
|
for (const depType of DEPENDENCIES_FIELDS) {
|
|
@@ -45,6 +45,11 @@ export interface PkgAddressOrLinkBase {
|
|
|
45
45
|
optional: boolean;
|
|
46
46
|
pkg: PackageManifest;
|
|
47
47
|
pkgId: PkgResolutionId;
|
|
48
|
+
/**
|
|
49
|
+
* The wanted dependency this direct dependency was resolved from, carried so
|
|
50
|
+
* consumers can recover the request directly. See `updateProjectManifest`.
|
|
51
|
+
*/
|
|
52
|
+
wantedDependency?: WantedDependency;
|
|
48
53
|
}
|
|
49
54
|
export interface LinkedDependency extends PkgAddressOrLinkBase {
|
|
50
55
|
isLinkedDependency: true;
|
|
@@ -201,6 +206,12 @@ export interface ResolvedPackage {
|
|
|
201
206
|
dev: boolean;
|
|
202
207
|
optional: boolean;
|
|
203
208
|
fetching: () => Promise<PkgRequestFetchResult>;
|
|
209
|
+
/**
|
|
210
|
+
* The resolution can't be completed without awaiting `fetching` (e.g. a registry tarball
|
|
211
|
+
* whose integrity is computed from the downloaded bytes). The lockfile snapshot and the
|
|
212
|
+
* virtual-store paths derived from the integrity must await `fetching` for these first.
|
|
213
|
+
*/
|
|
214
|
+
resolutionNeedsFetch?: boolean;
|
|
204
215
|
filesIndexFile: string;
|
|
205
216
|
name: string;
|
|
206
217
|
version: string;
|
|
@@ -278,6 +289,15 @@ export declare function resolveDependencies(ctx: ResolutionContext, preferredVer
|
|
|
278
289
|
updateDepth?: number;
|
|
279
290
|
}>, options: ResolvedDependenciesOptions): Promise<ResolvedDependenciesResult>;
|
|
280
291
|
export declare function createNodeIdForLinkedLocalPkg(lockfileDir: string, pkgDir: string): NodeId;
|
|
292
|
+
export declare function claimChildrenResolution(ctx: ResolutionContext, opts: {
|
|
293
|
+
currentDepth: number;
|
|
294
|
+
parentIds: PkgResolutionId[];
|
|
295
|
+
pkgId: PkgResolutionId;
|
|
296
|
+
}): {
|
|
297
|
+
id: number;
|
|
298
|
+
isOwner: boolean;
|
|
299
|
+
missingPeersOfChildren?: MissingPeersOfChildren;
|
|
300
|
+
};
|
|
281
301
|
export declare function buildTree(ctx: {
|
|
282
302
|
childrenByParentId: ChildrenByParentId;
|
|
283
303
|
dependenciesTree: DependenciesTree<ResolvedPackage>;
|
|
@@ -8,6 +8,7 @@ import { nameVerFromPkgSnapshot, pkgSnapshotToResolution, } from '@pnpm/lockfile
|
|
|
8
8
|
import { logger } from '@pnpm/logger';
|
|
9
9
|
import { getPatchInfo } from '@pnpm/patching.config';
|
|
10
10
|
import { convertEnginesRuntimeToDependencies } from '@pnpm/pkg-manifest.utils';
|
|
11
|
+
import { parseBareSpecifier } from '@pnpm/resolving.npm-resolver';
|
|
11
12
|
import { DIRECT_DEP_SELECTOR_WEIGHT, } from '@pnpm/resolving.resolver-base';
|
|
12
13
|
import { lexCompare } from '@pnpm/util.lex-comparator';
|
|
13
14
|
import normalizePath from 'normalize-path';
|
|
@@ -39,7 +40,8 @@ export async function resolveRootDependencies(ctx, importers) {
|
|
|
39
40
|
ctx.allPreferredVersions = getPreferredVersionsFromLockfileAndManifests(ctx.wantedLockfile.packages, []);
|
|
40
41
|
}
|
|
41
42
|
else if (ctx.hoistPeers) {
|
|
42
|
-
|
|
43
|
+
// Null-prototype: keyed by package names from resolved manifests.
|
|
44
|
+
ctx.allPreferredVersions = Object.create(null);
|
|
43
45
|
}
|
|
44
46
|
const { pkgAddressesByImportersWithoutPeers, publishedBy, time } = await resolveDependenciesOfImporters(ctx, importers);
|
|
45
47
|
if (!ctx.hoistPeers) {
|
|
@@ -434,8 +436,14 @@ async function resolveDependenciesOfDependency(ctx, preferredVersions, options,
|
|
|
434
436
|
const updateShouldContinue = options.currentDepth <= updateDepth;
|
|
435
437
|
const updateRequested = updateShouldContinue &&
|
|
436
438
|
((options.updateMatching == null) ||
|
|
437
|
-
(extendedWantedDep.infoFromLockfile?.name != null
|
|
438
|
-
options.updateMatching(extendedWantedDep.infoFromLockfile.name, extendedWantedDep.infoFromLockfile.version)
|
|
439
|
+
(extendedWantedDep.infoFromLockfile?.name != null
|
|
440
|
+
? options.updateMatching(extendedWantedDep.infoFromLockfile.name, extendedWantedDep.infoFromLockfile.version)
|
|
441
|
+
// A changed specifier forgets the edge's lockfile reference before
|
|
442
|
+
// resolution (e.g. `pnpm audit --fix` widening a vulnerable pin), so
|
|
443
|
+
// the target would otherwise lose its updateRequested status — and
|
|
444
|
+
// keep its seeded lockfile pins — at the very moment it is being
|
|
445
|
+
// updated. Fall back to matching by the wanted dependency itself.
|
|
446
|
+
: wantedDependencyMatchesUpdateTarget(ctx, options.updateMatching, extendedWantedDep.wantedDependency)));
|
|
439
447
|
const update = updateRequested ||
|
|
440
448
|
((extendedWantedDep.infoFromLockfile?.dependencyLockfile) == null) || Boolean((ctx.workspacePackages != null) &&
|
|
441
449
|
ctx.linkWorkspacePackagesDepth !== -1 &&
|
|
@@ -557,6 +565,21 @@ async function resolveDependenciesOfDependency(ctx, preferredVersions, options,
|
|
|
557
565
|
},
|
|
558
566
|
};
|
|
559
567
|
}
|
|
568
|
+
/**
|
|
569
|
+
* Whether a wanted dependency without a lockfile reference matches the
|
|
570
|
+
* update target by package name. The name is parsed from the bare
|
|
571
|
+
* specifier, so an `npm:` alias matches by the real package name it
|
|
572
|
+
* installs — `foo@npm:bar@^4` matches an update target of `bar`, not
|
|
573
|
+
* `foo`. Exotic specifiers the npm parser rejects fall back to the alias.
|
|
574
|
+
*/
|
|
575
|
+
function wantedDependencyMatchesUpdateTarget(ctx, updateMatching, wantedDependency) {
|
|
576
|
+
const { alias, bareSpecifier } = wantedDependency;
|
|
577
|
+
const spec = alias && bareSpecifier
|
|
578
|
+
? parseBareSpecifier(bareSpecifier, alias, ctx.defaultTag ?? 'latest', ctx.registries.default)
|
|
579
|
+
: null;
|
|
580
|
+
const name = spec?.name ?? alias;
|
|
581
|
+
return name != null && updateMatching(name, undefined);
|
|
582
|
+
}
|
|
560
583
|
export function createNodeIdForLinkedLocalPkg(lockfileDir, pkgDir) {
|
|
561
584
|
return `link:${normalizePath(path.relative(lockfileDir, pkgDir))}`;
|
|
562
585
|
}
|
|
@@ -611,7 +634,7 @@ function hasActivePackageResolutionBeforeDepth(ctx, depth) {
|
|
|
611
634
|
}
|
|
612
635
|
return false;
|
|
613
636
|
}
|
|
614
|
-
function claimChildrenResolution(ctx, opts) {
|
|
637
|
+
export function claimChildrenResolution(ctx, opts) {
|
|
615
638
|
const owner = {
|
|
616
639
|
depth: opts.currentDepth,
|
|
617
640
|
importerOrder: ctx.importerResolutionOrder[opts.parentIds[0]] ?? Number.MAX_SAFE_INTEGER,
|
|
@@ -657,8 +680,13 @@ function claimChildrenResolution(ctx, opts) {
|
|
|
657
680
|
if (ctx.hoistPeers &&
|
|
658
681
|
!opts.parentIds.includes(opts.pkgId) &&
|
|
659
682
|
existing.missingPeersOfChildren &&
|
|
660
|
-
|
|
661
|
-
|
|
683
|
+
existing.owner.depth >= opts.currentDepth) {
|
|
684
|
+
// Gating reuse on the owner's depth keeps a transitive optional peer's
|
|
685
|
+
// presence in the resolved suffix a function of graph structure, not of
|
|
686
|
+
// which occurrence happened to finish resolving first. A strictly shallower
|
|
687
|
+
// owner is excluded because its promise may still be unsettled here, and
|
|
688
|
+
// awaiting it can deadlock under auto-install-peers
|
|
689
|
+
// (https://github.com/pnpm/pnpm/issues/5454).
|
|
662
690
|
missingPeersOfChildren = existing.missingPeersOfChildren;
|
|
663
691
|
}
|
|
664
692
|
return {
|
|
@@ -1097,6 +1125,7 @@ async function resolveDependency(wantedDependency, ctx, options) {
|
|
|
1097
1125
|
trustPolicyExclude: ctx.trustPolicyExclude,
|
|
1098
1126
|
trustPolicyIgnoreAfter: ctx.trustPolicyIgnoreAfter,
|
|
1099
1127
|
update: options.update,
|
|
1128
|
+
updateRequested: options.updateRequested,
|
|
1100
1129
|
updateChecksums: options.updateChecksums,
|
|
1101
1130
|
workspacePackages: ctx.workspacePackages,
|
|
1102
1131
|
supportedArchitectures: options.supportedArchitectures,
|
|
@@ -1158,7 +1187,8 @@ async function resolveDependency(wantedDependency, ctx, options) {
|
|
|
1158
1187
|
}
|
|
1159
1188
|
if (ctx.allPreferredVersions && pkgResponse.body.manifest?.version) {
|
|
1160
1189
|
if (!ctx.allPreferredVersions[pkgResponse.body.manifest.name]) {
|
|
1161
|
-
|
|
1190
|
+
// Null-prototype: keyed by versions from the resolved manifest.
|
|
1191
|
+
ctx.allPreferredVersions[pkgResponse.body.manifest.name] = Object.create(null);
|
|
1162
1192
|
}
|
|
1163
1193
|
ctx.allPreferredVersions[pkgResponse.body.manifest.name][pkgResponse.body.manifest.version] = 'version';
|
|
1164
1194
|
}
|
|
@@ -1184,6 +1214,7 @@ async function resolveDependency(wantedDependency, ctx, options) {
|
|
|
1184
1214
|
version: pkgResponse.body.manifest.version,
|
|
1185
1215
|
normalizedBareSpecifier: pkgResponse.body.normalizedBareSpecifier,
|
|
1186
1216
|
pkg: pkgResponse.body.manifest,
|
|
1217
|
+
wantedDependency,
|
|
1187
1218
|
};
|
|
1188
1219
|
}
|
|
1189
1220
|
let prepare;
|
|
@@ -1364,6 +1395,7 @@ async function resolveDependency(wantedDependency, ctx, options) {
|
|
|
1364
1395
|
resolvedVia: pkgResponse.body.resolvedVia,
|
|
1365
1396
|
isNew,
|
|
1366
1397
|
nodeId,
|
|
1398
|
+
wantedDependency,
|
|
1367
1399
|
normalizedBareSpecifier: pkgResponse.body.normalizedBareSpecifier,
|
|
1368
1400
|
missingPeersOfChildren,
|
|
1369
1401
|
childrenResolutionId: childrenResolution.id,
|
|
@@ -1433,6 +1465,7 @@ function getResolvedPackage(options) {
|
|
|
1433
1465
|
pkgIdWithPatchHash: options.pkgIdWithPatchHash,
|
|
1434
1466
|
dev: options.wantedDependency.dev,
|
|
1435
1467
|
fetching: options.pkgResponse.fetching,
|
|
1468
|
+
resolutionNeedsFetch: options.pkgResponse.resolutionNeedsFetch,
|
|
1436
1469
|
filesIndexFile: options.pkgResponse.filesIndexFile,
|
|
1437
1470
|
hasBin: options.hasBin,
|
|
1438
1471
|
hasBundledDependencies: !((options.pkg.bundledDependencies ?? options.pkg.bundleDependencies) == null),
|
|
@@ -25,6 +25,11 @@ export interface ResolvedDirectDependency {
|
|
|
25
25
|
name: string;
|
|
26
26
|
catalogLookup?: CatalogLookupMetadata;
|
|
27
27
|
normalizedBareSpecifier?: string;
|
|
28
|
+
/**
|
|
29
|
+
* The wanted dependency this was resolved from, carried so consumers can
|
|
30
|
+
* recover the request directly. See `updateProjectManifest`.
|
|
31
|
+
*/
|
|
32
|
+
wantedDependency?: WantedDependency;
|
|
28
33
|
}
|
|
29
34
|
/**
|
|
30
35
|
* Information related to the catalog entry for this dependency if it was
|
|
@@ -164,6 +164,7 @@ export async function resolveDependencyTree(importers, opts) {
|
|
|
164
164
|
resolution: resolvedPackage.resolution,
|
|
165
165
|
version: resolvedPackage.version,
|
|
166
166
|
normalizedBareSpecifier: dep.normalizedBareSpecifier,
|
|
167
|
+
wantedDependency: dep.wantedDependency,
|
|
167
168
|
};
|
|
168
169
|
}),
|
|
169
170
|
directNodeIdsByAlias: new Map(directNonLinkedDeps.map(({ alias, nodeId }) => [alias, nodeId])),
|
|
@@ -3,19 +3,24 @@ export async function updateProjectManifest(importer, opts) {
|
|
|
3
3
|
if (!importer.manifest) {
|
|
4
4
|
throw new Error('Cannot save because no package.json found');
|
|
5
5
|
}
|
|
6
|
-
const specsToUpsert =
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
6
|
+
const specsToUpsert = [];
|
|
7
|
+
for (const rdd of opts.directDependencies) {
|
|
8
|
+
const wantedDep = rdd.wantedDependency;
|
|
9
|
+
if (wantedDep?.updateSpec !== true)
|
|
10
|
+
continue;
|
|
11
|
+
specsToUpsert.push({
|
|
11
12
|
alias: rdd.alias,
|
|
12
13
|
peer: importer.peer,
|
|
13
14
|
bareSpecifier: getBareSpecifierToSave(wantedDep, rdd, opts.preserveWorkspaceProtocol),
|
|
14
15
|
resolvedVersion: rdd.version,
|
|
15
16
|
pinnedVersion: importer.pinnedVersion,
|
|
16
17
|
saveType: importer.targetDependenciesField,
|
|
17
|
-
};
|
|
18
|
-
}
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
// Re-save a dependency flagged for update that failed to resolve (e.g. a
|
|
21
|
+
// missing optional, hence absent from `directDependencies`) carrying no
|
|
22
|
+
// specifier, so it keeps its existing version under the importer's target
|
|
23
|
+
// field (which is unset for a plain install/update, making this a no-op).
|
|
19
24
|
for (const pkgToInstall of importer.wantedDependencies) {
|
|
20
25
|
if (pkgToInstall.updateSpec && pkgToInstall.alias && !specsToUpsert.some(({ alias }) => alias === pkgToInstall.alias)) {
|
|
21
26
|
specsToUpsert.push({
|
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.6",
|
|
4
4
|
"description": "Resolves dependency graph of a package",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pnpm",
|
|
@@ -10,9 +10,9 @@
|
|
|
10
10
|
"funding": "https://opencollective.com/pnpm",
|
|
11
11
|
"repository": {
|
|
12
12
|
"type": "git",
|
|
13
|
-
"url": "https://github.com/pnpm/pnpm/tree/main/installing/deps-resolver"
|
|
13
|
+
"url": "https://github.com/pnpm/pnpm/tree/main/pnpm11/installing/deps-resolver"
|
|
14
14
|
},
|
|
15
|
-
"homepage": "https://github.com/pnpm/pnpm/tree/main/installing/deps-resolver#readme",
|
|
15
|
+
"homepage": "https://github.com/pnpm/pnpm/tree/main/pnpm11/installing/deps-resolver#readme",
|
|
16
16
|
"bugs": {
|
|
17
17
|
"url": "https://github.com/pnpm/pnpm/issues"
|
|
18
18
|
},
|
|
@@ -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/config.version-policy": "1100.1.6",
|
|
48
|
+
"@pnpm/catalogs.types": "1100.0.0",
|
|
46
49
|
"@pnpm/constants": "1100.0.0",
|
|
47
50
|
"@pnpm/core-loggers": "1100.2.1",
|
|
48
|
-
"@pnpm/deps.graph-hasher": "1100.2.
|
|
49
|
-
"@pnpm/error": "1100.0.0",
|
|
50
|
-
"@pnpm/fetching.pick-fetcher": "1100.0.12",
|
|
51
|
+
"@pnpm/deps.graph-hasher": "1100.2.7",
|
|
51
52
|
"@pnpm/deps.peer-range": "1100.0.2",
|
|
52
|
-
"@pnpm/hooks.types": "1100.0.12",
|
|
53
53
|
"@pnpm/deps.path": "1100.0.8",
|
|
54
|
-
"@pnpm/
|
|
55
|
-
"@pnpm/
|
|
56
|
-
"@pnpm/
|
|
57
|
-
"@pnpm/lockfile.
|
|
58
|
-
"@pnpm/
|
|
59
|
-
"@pnpm/
|
|
60
|
-
"@pnpm/
|
|
61
|
-
"@pnpm/
|
|
62
|
-
"@pnpm/resolving.npm-resolver": "1102.0.1",
|
|
63
|
-
"@pnpm/resolving.resolver-base": "1100.4.2",
|
|
64
|
-
"@pnpm/store.controller-types": "1100.1.5",
|
|
65
|
-
"@pnpm/types": "1101.3.2",
|
|
66
|
-
"@pnpm/workspace.spec-parser": "1100.0.0",
|
|
54
|
+
"@pnpm/error": "1100.0.1",
|
|
55
|
+
"@pnpm/hooks.types": "1100.1.1",
|
|
56
|
+
"@pnpm/fetching.pick-fetcher": "1100.0.14",
|
|
57
|
+
"@pnpm/lockfile.preferred-versions": "1100.0.18",
|
|
58
|
+
"@pnpm/lockfile.pruner": "1100.0.13",
|
|
59
|
+
"@pnpm/lockfile.types": "1100.0.13",
|
|
60
|
+
"@pnpm/lockfile.utils": "1100.1.1",
|
|
61
|
+
"@pnpm/patching.config": "1100.0.9",
|
|
67
62
|
"@pnpm/patching.types": "1100.0.0",
|
|
68
|
-
"@pnpm/
|
|
69
|
-
"@pnpm/
|
|
63
|
+
"@pnpm/resolving.npm-resolver": "1102.1.1",
|
|
64
|
+
"@pnpm/pkg-manifest.reader": "1100.0.9",
|
|
65
|
+
"@pnpm/resolving.resolver-base": "1100.5.1",
|
|
66
|
+
"@pnpm/pkg-manifest.utils": "1100.2.6",
|
|
67
|
+
"@pnpm/types": "1101.3.2",
|
|
68
|
+
"@pnpm/store.controller-types": "1100.1.7",
|
|
69
|
+
"@pnpm/workspace.spec-parser": "1100.0.0"
|
|
70
70
|
},
|
|
71
71
|
"peerDependencies": {
|
|
72
72
|
"@pnpm/logger": "^1100.0.0"
|
|
@@ -77,8 +77,8 @@
|
|
|
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/
|
|
81
|
-
"@pnpm/
|
|
80
|
+
"@pnpm/logger": "1100.0.0",
|
|
81
|
+
"@pnpm/installing.deps-resolver": "1100.2.6"
|
|
82
82
|
},
|
|
83
83
|
"engines": {
|
|
84
84
|
"node": ">=22.13"
|