@pnpm/installing.package-requester 1101.1.0 → 1102.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -18,6 +18,7 @@ export declare function createPackageRequester(opts: {
18
18
  virtualStoreDirMaxLength: number;
19
19
  strictStorePkgContentCheck?: boolean;
20
20
  customFetchers?: CustomFetcher[];
21
+ frozenStore?: boolean;
21
22
  }): RequestPackageFunction & {
22
23
  fetchPackageToStore: FetchPackageToStoreFunction;
23
24
  getFilesIndexFilePath: GetFilesIndexFilePath;
@@ -7,7 +7,7 @@ import { PnpmError } from '@pnpm/error';
7
7
  import { pickFetcher } from '@pnpm/fetching.pick-fetcher';
8
8
  import gfs from '@pnpm/fs.graceful-fs';
9
9
  import { logger } from '@pnpm/logger';
10
- import { resolvePlatformSelector, selectPlatformVariant, } from '@pnpm/resolving.resolver-base';
10
+ import { classifyResolution, resolvePlatformSelector, selectPlatformVariant, } from '@pnpm/resolving.resolver-base';
11
11
  import { normalizeBundledManifest, } from '@pnpm/store.cafs';
12
12
  import { pickStoreIndexKey } from '@pnpm/store.index';
13
13
  import { calcMaxWorkers, readPkgFromCafs as _readPkgFromCafs, } from '@pnpm/worker';
@@ -42,6 +42,7 @@ export function createPackageRequester(opts) {
42
42
  storeDir: opts.storeDir,
43
43
  verifyStoreIntegrity: opts.verifyStoreIntegrity,
44
44
  strictStorePkgContentCheck: opts.strictStorePkgContentCheck,
45
+ frozenStore: opts.frozenStore,
45
46
  });
46
47
  const fetchPackageToStore = fetchToStore.bind(null, {
47
48
  readPkgFromCafs,
@@ -64,6 +65,8 @@ export function createPackageRequester(opts) {
64
65
  requestsQueue,
65
66
  resolve: opts.resolve,
66
67
  storeDir: opts.storeDir,
68
+ fetchers: opts.fetchers,
69
+ customFetchers: opts.customFetchers,
67
70
  });
68
71
  return Object.assign(requestPackage, {
69
72
  fetchPackageToStore,
@@ -156,9 +159,19 @@ async function resolveAndFetch(ctx, wantedDependency, options) {
156
159
  optional: wantedDependency.optional === true,
157
160
  supportedArchitectures: options.supportedArchitectures,
158
161
  })));
159
- // We can skip fetching the package only if the manifest
160
- // is present after resolution AND the content of the package has not changed
161
- if ((options.skipFetch === true || isInstallable === false) && !integrityChanged && (manifest != null)) {
162
+ const fetcherForResolution = resolution.type === 'variations'
163
+ ? undefined
164
+ : await pickFetcher(ctx.fetchers, resolution, {
165
+ customFetchers: ctx.customFetchers,
166
+ packageId: id,
167
+ });
168
+ const resolutionNeedsFetchHook = fetcherForResolution?.resolutionNeedsFetch;
169
+ const resolutionNeedsFetch = typeof resolutionNeedsFetchHook === 'function'
170
+ ? resolutionNeedsFetchHook(resolution)
171
+ : false;
172
+ // Fetching can be skipped only when the manifest is available, the package content
173
+ // did not change, and the resolution does not need fetch-derived data.
174
+ if ((options.skipFetch === true || isInstallable === false) && !resolutionNeedsFetch && !integrityChanged && (manifest != null)) {
162
175
  return {
163
176
  body: {
164
177
  id,
@@ -181,6 +194,8 @@ async function resolveAndFetch(ctx, wantedDependency, options) {
181
194
  allowBuild: options.allowBuild,
182
195
  fetchRawManifest: true,
183
196
  force: integrityChanged,
197
+ populateMissingIntegrity: resolutionNeedsFetch,
198
+ pickedFetcher: fetcherForResolution,
184
199
  ignoreScripts: options.ignoreScripts,
185
200
  lockfileDir: options.lockfileDir,
186
201
  pkg: {
@@ -206,11 +221,29 @@ async function resolveAndFetch(ctx, wantedDependency, options) {
206
221
  manifest = loadedManifest;
207
222
  }
208
223
  }
209
- // Add integrity to resolution if it was computed during fetching (only for TarballResolution)
210
- if (fetchedResult.integrity && !resolution.type && !resolution.integrity) {
224
+ // Add computed integrity to tarball resolutions. `variations` spans multiple
225
+ // platform variants, so do not write one machine's integrity into the shared resolution.
226
+ if (resolution.type !== 'variations' && fetchedResult.integrity != null && getExpectedIntegrity(resolution) == null) {
211
227
  resolution.integrity = fetchedResult.integrity;
212
228
  }
213
229
  }
230
+ let fetching = fetchResult.fetching;
231
+ if (resolutionNeedsFetch) {
232
+ let populating;
233
+ fetching = () => {
234
+ populating ??= fetchResult.fetching().then((fetchedResult) => {
235
+ if (fetchedResult.integrity != null && getExpectedIntegrity(resolution) == null) {
236
+ resolution.integrity = fetchedResult.integrity;
237
+ }
238
+ return fetchedResult;
239
+ }).catch((err) => {
240
+ // Cache only fulfilled fetches; rejected fetches may be retried.
241
+ populating = undefined;
242
+ throw err;
243
+ });
244
+ return populating;
245
+ };
246
+ }
214
247
  // Check installability now that we have the manifest (for git/tarball packages without registry metadata)
215
248
  if (isInstallable === undefined && manifest != null) {
216
249
  isInstallable = ctx.force === true || packageIsInstallable(id, manifest, {
@@ -236,8 +269,9 @@ async function resolveAndFetch(ctx, wantedDependency, options) {
236
269
  alias,
237
270
  policyViolation,
238
271
  },
239
- fetching: fetchResult.fetching,
272
+ fetching,
240
273
  filesIndexFile: fetchResult.filesIndexFile,
274
+ resolutionNeedsFetch,
241
275
  };
242
276
  }
243
277
  function getFilesIndexFilePath(ctx, opts) {
@@ -356,7 +390,13 @@ function fetchToStore(ctx, opts) {
356
390
  try {
357
391
  const isLocalTarballDep = opts.pkg.id.startsWith('file:');
358
392
  const isLocalPkg = resolution.type === 'directory';
393
+ const populateMissingIntegrity = opts.populateMissingIntegrity === true;
394
+ if (!populateMissingIntegrity) {
395
+ assertFetchableResolution(opts.pkg.id, resolution);
396
+ }
397
+ let refetchingStoredPackage = false;
359
398
  if (!opts.force &&
399
+ !populateMissingIntegrity &&
360
400
  (!isLocalTarballDep ||
361
401
  await tarballIsUpToDate(opts.pkg.resolution, target, opts.lockfileDir) // eslint-disable-line
362
402
  ) &&
@@ -372,12 +412,13 @@ function fetchToStore(ctx, opts) {
372
412
  });
373
413
  return;
374
414
  }
375
- if ((files?.filesMap) != null) {
376
- packageRequestLogger.warn({
377
- message: `Refetching ${target} to store. It was either modified or had no integrity checksums`,
378
- prefix: opts.lockfileDir,
379
- });
380
- }
415
+ refetchingStoredPackage = (files?.filesMap) != null;
416
+ }
417
+ if (refetchingStoredPackage) {
418
+ packageRequestLogger.warn({
419
+ message: `Refetching ${target} to store. It was either modified or had no integrity checksums`,
420
+ prefix: opts.lockfileDir,
421
+ });
381
422
  }
382
423
  // We fetch into targetStage directory first and then fs.rename() it to the
383
424
  // target directory.
@@ -410,8 +451,8 @@ function fetchToStore(ctx, opts) {
410
451
  name: opts.pkg.name,
411
452
  version: opts.pkg.version,
412
453
  },
413
- }), { priority });
414
- const integrity = opts.pkg.resolution.integrity ?? fetchedPackage.integrity;
454
+ }, opts.pickedFetcher), { priority });
455
+ const integrity = getExpectedIntegrity(opts.pkg.resolution) ?? fetchedPackage.integrity;
415
456
  if (isLocalTarballDep && integrity) {
416
457
  await fs.mkdir(target, { recursive: true });
417
458
  await gfs.writeFile(path.join(target, TARBALL_INTEGRITY_FILENAME), integrity, 'utf8');
@@ -435,6 +476,19 @@ function fetchToStore(ctx, opts) {
435
476
  async function readBundledManifest(pkgJsonPath) {
436
477
  return normalizeBundledManifest(await loadJsonFile(pkgJsonPath));
437
478
  }
479
+ function getExpectedIntegrity(resolution) {
480
+ const integrity = resolution.integrity;
481
+ return typeof integrity === 'string' && integrity.length > 0
482
+ ? integrity
483
+ : undefined;
484
+ }
485
+ function assertFetchableResolution(depPath, resolution) {
486
+ if (classifyResolution(resolution) !== 'remoteTarball')
487
+ return;
488
+ if (getExpectedIntegrity(resolution) != null)
489
+ return;
490
+ throw new PnpmError('MISSING_TARBALL_INTEGRITY', `Cannot fetch package "${depPath}" from the lockfile: it has no "integrity" field, so the downloaded tarball cannot be verified. Run a fresh install to repair the lockfile.`);
491
+ }
438
492
  async function tarballIsUpToDate(resolution, pkgInStoreLocation, lockfileDir) {
439
493
  let currentIntegrity;
440
494
  try {
@@ -454,10 +508,9 @@ async function tarballIsUpToDate(resolution, pkgInStoreLocation, lockfileDir) {
454
508
  return false;
455
509
  }
456
510
  }
457
- async function fetcher(fetcherByHostingType, cafs, customFetchers, packageId, resolution, opts) {
511
+ async function fetcher(fetcherByHostingType, cafs, customFetchers, packageId, resolution, opts, pickedFetcher) {
458
512
  try {
459
- // pickFetcher now handles custom fetcher hooks internally
460
- const fetch = await pickFetcher(fetcherByHostingType, resolution, {
513
+ const fetch = pickedFetcher ?? await pickFetcher(fetcherByHostingType, resolution, {
461
514
  customFetchers,
462
515
  packageId,
463
516
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pnpm/installing.package-requester",
3
- "version": "1101.1.0",
3
+ "version": "1102.1.0",
4
4
  "description": "Concurrent downloader of npm-compatible packages",
5
5
  "keywords": [
6
6
  "pnpm",
@@ -12,9 +12,9 @@
12
12
  "funding": "https://opencollective.com/pnpm",
13
13
  "repository": {
14
14
  "type": "git",
15
- "url": "https://github.com/pnpm/pnpm/tree/main/installing/package-requester"
15
+ "url": "https://github.com/pnpm/pnpm/tree/main/pnpm11/installing/package-requester"
16
16
  },
17
- "homepage": "https://github.com/pnpm/pnpm/tree/main/installing/package-requester#readme",
17
+ "homepage": "https://github.com/pnpm/pnpm/tree/main/pnpm11/installing/package-requester#readme",
18
18
  "bugs": {
19
19
  "url": "https://github.com/pnpm/pnpm/issues"
20
20
  },
@@ -36,28 +36,28 @@
36
36
  "p-queue": "^9.3.0",
37
37
  "promise-share": "^2.0.1",
38
38
  "ramda": "npm:@pnpm/ramda@0.28.1",
39
- "semver": "^7.8.1",
39
+ "semver": "^7.8.4",
40
40
  "ssri": "13.0.1",
41
- "@pnpm/config.package-is-installable": "1100.0.10",
42
- "@pnpm/core-loggers": "1100.2.0",
43
- "@pnpm/deps.path": "1100.0.7",
44
- "@pnpm/fetching.pick-fetcher": "1100.0.11",
41
+ "@pnpm/config.package-is-installable": "1100.0.12",
42
+ "@pnpm/core-loggers": "1100.2.1",
43
+ "@pnpm/deps.path": "1100.0.8",
44
+ "@pnpm/error": "1100.0.1",
45
+ "@pnpm/fetching.fetcher-base": "1100.2.0",
46
+ "@pnpm/fetching.pick-fetcher": "1100.0.13",
45
47
  "@pnpm/fs.graceful-fs": "1100.1.0",
46
- "@pnpm/hooks.types": "1100.0.11",
47
- "@pnpm/resolving.resolver-base": "1100.4.1",
48
- "@pnpm/store.cafs": "1100.1.9",
49
- "@pnpm/store.controller-types": "1100.1.4",
50
- "@pnpm/types": "1101.3.1",
51
- "@pnpm/store.index": "1100.1.0",
52
- "@pnpm/error": "1100.0.0",
53
- "@pnpm/fetching.fetcher-base": "1100.1.8"
48
+ "@pnpm/hooks.types": "1100.1.0",
49
+ "@pnpm/resolving.resolver-base": "1100.5.0",
50
+ "@pnpm/store.cafs": "1100.1.11",
51
+ "@pnpm/store.controller-types": "1100.1.6",
52
+ "@pnpm/store.index": "1100.2.1",
53
+ "@pnpm/types": "1101.3.2"
54
54
  },
55
55
  "peerDependencies": {
56
- "@pnpm/logger": "^1001.0.1",
57
- "@pnpm/worker": "^1100.1.11"
56
+ "@pnpm/logger": "^1100.0.0",
57
+ "@pnpm/worker": "^1100.2.2"
58
58
  },
59
59
  "devDependencies": {
60
- "@jest/globals": "30.3.0",
60
+ "@jest/globals": "30.4.1",
61
61
  "@types/normalize-path": "^3.0.2",
62
62
  "@types/ramda": "0.31.1",
63
63
  "@types/semver": "7.7.1",
@@ -65,14 +65,14 @@
65
65
  "delay": "^7.0.0",
66
66
  "normalize-path": "^3.0.0",
67
67
  "tempy": "3.0.0",
68
- "@pnpm/installing.client": "1100.2.7",
68
+ "@pnpm/installing.client": "1100.2.10",
69
+ "@pnpm/installing.package-requester": "1102.1.0",
69
70
  "@pnpm/store.cafs-types": "1100.0.1",
70
- "@pnpm/store.create-cafs-store": "1100.0.13",
71
71
  "@pnpm/logger": "1100.0.0",
72
- "@pnpm/testing.mock-agent": "1101.0.2",
73
- "@pnpm/installing.package-requester": "1101.1.0",
72
+ "@pnpm/store.create-cafs-store": "1100.0.16",
73
+ "@pnpm/testing.mock-agent": "1101.0.4",
74
74
  "@pnpm/test-fixtures": "1100.0.0",
75
- "@pnpm/testing.registry-mock": "1100.0.5"
75
+ "@pnpm/testing.registry-mock": "1100.0.7"
76
76
  },
77
77
  "engines": {
78
78
  "node": ">=22.13"