@pnpm/installing.deps-resolver 1100.2.4 → 1100.2.5

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.
@@ -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>;
@@ -611,7 +611,7 @@ function hasActivePackageResolutionBeforeDepth(ctx, depth) {
611
611
  }
612
612
  return false;
613
613
  }
614
- function claimChildrenResolution(ctx, opts) {
614
+ export function claimChildrenResolution(ctx, opts) {
615
615
  const owner = {
616
616
  depth: opts.currentDepth,
617
617
  importerOrder: ctx.importerResolutionOrder[opts.parentIds[0]] ?? Number.MAX_SAFE_INTEGER,
@@ -657,8 +657,13 @@ function claimChildrenResolution(ctx, opts) {
657
657
  if (ctx.hoistPeers &&
658
658
  !opts.parentIds.includes(opts.pkgId) &&
659
659
  existing.missingPeersOfChildren &&
660
- (existing.owner.depth >= opts.currentDepth ||
661
- existing.missingPeersOfChildren.resolved)) {
660
+ existing.owner.depth >= opts.currentDepth) {
661
+ // Gating reuse on the owner's depth keeps a transitive optional peer's
662
+ // presence in the resolved suffix a function of graph structure, not of
663
+ // which occurrence happened to finish resolving first. A strictly shallower
664
+ // owner is excluded because its promise may still be unsettled here, and
665
+ // awaiting it can deadlock under auto-install-peers
666
+ // (https://github.com/pnpm/pnpm/issues/5454).
662
667
  missingPeersOfChildren = existing.missingPeersOfChildren;
663
668
  }
664
669
  return {
@@ -1184,6 +1189,7 @@ async function resolveDependency(wantedDependency, ctx, options) {
1184
1189
  version: pkgResponse.body.manifest.version,
1185
1190
  normalizedBareSpecifier: pkgResponse.body.normalizedBareSpecifier,
1186
1191
  pkg: pkgResponse.body.manifest,
1192
+ wantedDependency,
1187
1193
  };
1188
1194
  }
1189
1195
  let prepare;
@@ -1364,6 +1370,7 @@ async function resolveDependency(wantedDependency, ctx, options) {
1364
1370
  resolvedVia: pkgResponse.body.resolvedVia,
1365
1371
  isNew,
1366
1372
  nodeId,
1373
+ wantedDependency,
1367
1374
  normalizedBareSpecifier: pkgResponse.body.normalizedBareSpecifier,
1368
1375
  missingPeersOfChildren,
1369
1376
  childrenResolutionId: childrenResolution.id,
@@ -1433,6 +1440,7 @@ function getResolvedPackage(options) {
1433
1440
  pkgIdWithPatchHash: options.pkgIdWithPatchHash,
1434
1441
  dev: options.wantedDependency.dev,
1435
1442
  fetching: options.pkgResponse.fetching,
1443
+ resolutionNeedsFetch: options.pkgResponse.resolutionNeedsFetch,
1436
1444
  filesIndexFile: options.pkgResponse.filesIndexFile,
1437
1445
  hasBin: options.hasBin,
1438
1446
  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 = opts.directDependencies
7
- .filter((rdd, index) => importer.wantedDependencies[index]?.updateSpec)
8
- .map((rdd, index) => {
9
- const wantedDep = importer.wantedDependencies[index];
10
- return {
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.4",
3
+ "version": "1100.2.5",
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/catalogs.types": "1100.0.0",
48
+ "@pnpm/config.version-policy": "1100.1.6",
46
49
  "@pnpm/constants": "1100.0.0",
47
50
  "@pnpm/core-loggers": "1100.2.1",
48
- "@pnpm/deps.graph-hasher": "1100.2.5",
49
- "@pnpm/error": "1100.0.0",
50
- "@pnpm/fetching.pick-fetcher": "1100.0.12",
51
- "@pnpm/deps.peer-range": "1100.0.2",
52
- "@pnpm/hooks.types": "1100.0.12",
53
51
  "@pnpm/deps.path": "1100.0.8",
54
- "@pnpm/config.version-policy": "1100.1.5",
55
- "@pnpm/lockfile.preferred-versions": "1100.0.16",
56
- "@pnpm/lockfile.types": "1100.0.11",
57
- "@pnpm/lockfile.utils": "1100.0.13",
58
- "@pnpm/patching.config": "1100.0.8",
59
- "@pnpm/catalogs.types": "1100.0.0",
60
- "@pnpm/pkg-manifest.reader": "1100.0.8",
61
- "@pnpm/pkg-manifest.utils": "1100.2.5",
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",
52
+ "@pnpm/deps.graph-hasher": "1100.2.6",
53
+ "@pnpm/deps.peer-range": "1100.0.2",
54
+ "@pnpm/error": "1100.0.1",
55
+ "@pnpm/fetching.pick-fetcher": "1100.0.13",
56
+ "@pnpm/hooks.types": "1100.1.0",
57
+ "@pnpm/lockfile.preferred-versions": "1100.0.17",
58
+ "@pnpm/lockfile.pruner": "1100.0.12",
59
+ "@pnpm/lockfile.types": "1100.0.12",
60
+ "@pnpm/lockfile.utils": "1100.1.0",
61
+ "@pnpm/patching.config": "1100.0.9",
67
62
  "@pnpm/patching.types": "1100.0.0",
68
- "@pnpm/catalogs.resolver": "1100.0.0",
69
- "@pnpm/lockfile.pruner": "1100.0.11"
63
+ "@pnpm/pkg-manifest.reader": "1100.0.9",
64
+ "@pnpm/pkg-manifest.utils": "1100.2.6",
65
+ "@pnpm/resolving.resolver-base": "1100.5.0",
66
+ "@pnpm/store.controller-types": "1100.1.6",
67
+ "@pnpm/resolving.npm-resolver": "1102.1.0",
68
+ "@pnpm/types": "1101.3.2",
69
+ "@pnpm/workspace.spec-parser": "1100.0.0"
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.4",
80
+ "@pnpm/installing.deps-resolver": "1100.2.5",
81
81
  "@pnpm/logger": "1100.0.0"
82
82
  },
83
83
  "engines": {