diff --git a/packages/build-modules/src/index.ts b/packages/build-modules/src/index.ts index 1562359e3d..a3ec8d3c47 100644 --- a/packages/build-modules/src/index.ts +++ b/packages/build-modules/src/index.ts @@ -152,7 +152,7 @@ function getSubgraphToBuild ( } export interface DependenciesGraphNode { - fetchingRawManifest?: Promise, + fetchingRawManifest?: () => Promise, hasBundledDependencies: boolean, peripheralLocation: string, children: {[alias: string]: string}, @@ -205,7 +205,7 @@ export async function linkBinsOfDependencies ( const dep = depGraph[childrenToLink[alias]] return { location: dep.peripheralLocation, - manifest: dep.fetchingRawManifest && (await dep.fetchingRawManifest) || (await readPackageFromDir(dep.peripheralLocation) as DependencyManifest), + manifest: dep.fetchingRawManifest && (await dep.fetchingRawManifest()) || (await readPackageFromDir(dep.peripheralLocation) as DependencyManifest), } }), ) diff --git a/packages/headless/src/index.ts b/packages/headless/src/index.ts index e5bf7849b8..f8b5baecf1 100644 --- a/packages/headless/src/index.ts +++ b/packages/headless/src/index.ts @@ -523,7 +523,7 @@ async function lockfileToDepGraph ( resolution, }) if (fetchResponse instanceof Promise) fetchResponse = await fetchResponse - fetchResponse.fetchingFiles // tslint:disable-line + fetchResponse.fetchingFiles() // tslint:disable-line .then((fetchResult) => { progressLogger.debug({ packageId, @@ -532,6 +532,9 @@ async function lockfileToDepGraph ( ? 'found_in_store' : 'fetched', }) }) + .catch(() => { + // ignore + }) graph[peripheralLocation] = { centralLocation: pkgLocation.directory, children: {}, @@ -645,8 +648,8 @@ export interface DependenciesGraphNode { centralLocation: string, modules: string, name: string, - fetchingFiles: Promise, - finishing: Promise, + fetchingFiles: () => Promise, + finishing: () => Promise, peripheralLocation: string, children: {[alias: string]: string}, // an independent package is a package that @@ -677,7 +680,7 @@ async function linkAllPkgs ( ) { return Promise.all( depNodes.map(async (depNode) => { - const filesResponse = await depNode.fetchingFiles + const filesResponse = await depNode.fetchingFiles() if (depNode.independent) return return storeController.importPackage(depNode.centralLocation, depNode.peripheralLocation, { diff --git a/packages/package-requester/package.json b/packages/package-requester/package.json index a9845f00bd..d5f8677682 100644 --- a/packages/package-requester/package.json +++ b/packages/package-requester/package.json @@ -48,6 +48,7 @@ "p-limit": "2.2.1", "p-queue": "6.1.1", "path-exists": "4.0.0", + "promise-share": "1.0.0", "rename-overwrite": "2.0.2", "ssri": "6.0.1", "symlink-dir": "3.1.1", diff --git a/packages/package-requester/src/packageRequester.ts b/packages/package-requester/src/packageRequester.ts index 63e262e98c..27b73d4fe4 100644 --- a/packages/package-requester/src/packageRequester.ts +++ b/packages/package-requester/src/packageRequester.ts @@ -10,7 +10,6 @@ import pkgIdToFilename from '@pnpm/pkgid-to-filename' import { fromDir as readPkgFromDir } from '@pnpm/read-package-json' import { DirectoryResolution, - LocalPackages, Resolution, ResolveFunction, ResolveResult, @@ -35,6 +34,7 @@ import * as fs from 'mz/fs' import PQueue from 'p-queue' import path = require('path') import exists = require('path-exists') +import pShare = require('promise-share') import renameOverwrite = require('rename-overwrite') import ssri = require('ssri') import symlinkDir = require('symlink-dir') @@ -242,9 +242,9 @@ function fetchToStore ( resolution: Resolution, }, ): { - fetchingFiles: Promise, - fetchingRawManifest?: Promise, - finishing: Promise, + fetchingFiles: () => Promise, + fetchingRawManifest?: () => Promise, + finishing: () => Promise, inStoreLocation: string, } { const targetRelative = pkgIdToFilename(opts.pkgId, opts.prefix) @@ -323,7 +323,12 @@ function fetchToStore ( ) } - return result + return { + fetchingFiles: pShare(result.fetchingFiles), + fetchingRawManifest: result.fetchingRawManifest ? pShare(result.fetchingRawManifest) : undefined, + finishing: pShare(result.finishing), + inStoreLocation: result.inStoreLocation, + } function removeKeyOnFail (p: Promise): Promise { return p.catch((err) => { diff --git a/packages/package-requester/test/index.ts b/packages/package-requester/test/index.ts index 9b2035f17d..a4b1f4306a 100644 --- a/packages/package-requester/test/index.ts +++ b/packages/package-requester/test/index.ts @@ -56,8 +56,8 @@ test('request package', async t => { registry, }) as PackageResponse & { body: {inStoreLocation: string, latest: string, manifest: {name: string}}, - fetchingFiles: Promise<{filenames: string[], fromStore: boolean}>, - finishing: Promise, + fetchingFiles: () => Promise<{filenames: string[], fromStore: boolean}>, + finishing: () => Promise, } t.ok(pkgResponse, 'response received') @@ -76,13 +76,13 @@ test('request package', async t => { tarball: 'https://registry.npmjs.org/is-positive/-/is-positive-1.0.0.tgz', }, 'resolution returned') - const files = await pkgResponse.fetchingFiles + const files = await pkgResponse.fetchingFiles() t.deepEqual(files, { filenames: [ 'package.json', 'index.js', 'license', 'readme.md' ], fromStore: false, }, 'returned info about files after fetch completed') - t.ok(pkgResponse.finishing) + t.ok(pkgResponse.finishing()) t.deepEqual(storeIndex, { 'registry.npmjs.org/is-positive/1.0.0': [] }) @@ -108,8 +108,8 @@ test('request package but skip fetching', async t => { skipFetch: true, }) as PackageResponse & { body: {inStoreLocation: string, latest: string, manifest: {name: string}}, - fetchingFiles: Promise, - finishing: Promise, + fetchingFiles: () => Promise, + finishing: () => Promise, } t.ok(pkgResponse, 'response received') @@ -163,8 +163,8 @@ test('request package but skip fetching, when resolution is already available', latest: string, manifest: {name: string}, }, - fetchingFiles: Promise, - finishing: Promise, + fetchingFiles: () => Promise, + finishing: () => Promise, } t.ok(pkgResponse, 'response received') @@ -223,15 +223,15 @@ test('refetch local tarball if its integrity has changed', async t => { tarball, }, }) as PackageResponse & { - fetchingFiles: Promise, - finishing: Promise, + fetchingFiles: () => Promise, + finishing: () => Promise, } - await response.fetchingFiles - await response.finishing + await response.fetchingFiles() + await response.finishing() t.ok(response.body.updated === false, 'resolution not updated') - t.notOk((await response.fetchingFiles).fromStore, 'unpack tarball if it is not in store yet') - t.equal((await response['fetchingRawManifest']).version, '0.8.1') + t.notOk((await response.fetchingFiles()).fromStore, 'unpack tarball if it is not in store yet') + t.equal((await response['fetchingRawManifest']()).version, '0.8.1') } await ncp(path.join(__dirname, 'pnpm-package-requester-4.1.2.tgz'), tarballPath) @@ -251,15 +251,15 @@ test('refetch local tarball if its integrity has changed', async t => { tarball, }, }) as PackageResponse & { - fetchingFiles: Promise, - finishing: Promise, + fetchingFiles: () => Promise, + finishing: () => Promise, } - await response.fetchingFiles - await response.finishing + await response.fetchingFiles() + await response.finishing() t.ok(response.body.updated === true, 'resolution updated') - t.notOk((await response.fetchingFiles).fromStore, 'reunpack tarball if its integrity is not up-to-date') - t.equal((await response['fetchingRawManifest']).version, '4.1.2') + t.notOk((await response.fetchingFiles()).fromStore, 'reunpack tarball if its integrity is not up-to-date') + t.equal((await response['fetchingRawManifest']()).version, '4.1.2') } { @@ -276,15 +276,15 @@ test('refetch local tarball if its integrity has changed', async t => { tarball, }, }) as PackageResponse & { - fetchingFiles: Promise, - finishing: Promise, + fetchingFiles: () => Promise, + finishing: () => Promise, } - await response.fetchingFiles - await response.finishing + await response.fetchingFiles() + await response.finishing() t.ok(response.body.updated === false, 'resolution not updated') - t.ok((await response.fetchingFiles).fromStore, 'do not reunpack tarball if its integrity is up-to-date') - t.equal((await response['fetchingRawManifest']).version, '4.1.2') + t.ok((await response.fetchingFiles()).fromStore, 'do not reunpack tarball if its integrity is up-to-date') + t.equal((await response['fetchingRawManifest']()).version, '4.1.2') } t.end() @@ -315,15 +315,15 @@ test('refetch local tarball if its integrity has changed. The requester does not }) const response = await requestPackage(wantedPackage, requestPackageOpts) as PackageResponse & { - fetchingFiles: Promise, - finishing: Promise, + fetchingFiles: () => Promise, + finishing: () => Promise, } - await response.fetchingFiles - await response.finishing + await response.fetchingFiles() + await response.finishing() t.ok(response.body.updated === true, 'resolution updated') - t.notOk((await response.fetchingFiles).fromStore, 'unpack tarball if it is not in store yet') - t.equal((await response['fetchingRawManifest']).version, '0.8.1') + t.notOk((await response.fetchingFiles()).fromStore, 'unpack tarball if it is not in store yet') + t.equal((await response['fetchingRawManifest']()).version, '0.8.1') } await ncp(path.join(__dirname, 'pnpm-package-requester-4.1.2.tgz'), tarballPath) @@ -337,15 +337,15 @@ test('refetch local tarball if its integrity has changed. The requester does not }) const response = await requestPackage(wantedPackage, requestPackageOpts) as PackageResponse & { - fetchingFiles: Promise, - finishing: Promise, + fetchingFiles: () => Promise, + finishing: () => Promise, } - await response.fetchingFiles - await response.finishing + await response.fetchingFiles() + await response.finishing() t.ok(response.body.updated === true, 'resolution updated') - t.notOk((await response.fetchingFiles).fromStore, 'reunpack tarball if its integrity is not up-to-date') - t.equal((await response['fetchingRawManifest']).version, '4.1.2') + t.notOk((await response.fetchingFiles()).fromStore, 'reunpack tarball if its integrity is not up-to-date') + t.equal((await response['fetchingRawManifest']()).version, '4.1.2') } { @@ -356,14 +356,14 @@ test('refetch local tarball if its integrity has changed. The requester does not }) const response = await requestPackage(wantedPackage, requestPackageOpts) as PackageResponse & { - fetchingFiles: Promise, - finishing: Promise, + fetchingFiles: () => Promise, + finishing: () => Promise, } await response.fetchingFiles await response.finishing - t.ok((await response.fetchingFiles).fromStore, 'do not reunpack tarball if its integrity is up-to-date') - t.equal((await response['fetchingRawManifest']).version, '4.1.2') + t.ok((await response.fetchingFiles()).fromStore, 'do not reunpack tarball if its integrity is up-to-date') + t.equal((await response['fetchingRawManifest']()).version, '4.1.2') } t.end() @@ -391,13 +391,13 @@ test('fetchPackageToStore()', async (t) => { t.notOk(fetchResult.fetchingRawManifest, 'full manifest not returned') - const files = await fetchResult.fetchingFiles + const files = await fetchResult.fetchingFiles() t.deepEqual(files, { filenames: [ 'package.json', 'index.js', 'license', 'readme.md' ], fromStore: false, }, 'returned info about files after fetch completed') - t.ok(fetchResult.finishing) + t.ok(fetchResult.finishing()) const fetchResult2 = await packageRequester.fetchPackageToStore({ fetchRawManifest: true, @@ -413,7 +413,7 @@ test('fetchPackageToStore()', async (t) => { // This verifies that when a package has been cached with no full manifest // the full manifest is requested and added to the cache - t.ok((await fetchResult2.fetchingRawManifest)!.name, 'full manifest returned') + t.ok((await fetchResult2.fetchingRawManifest!()).name, 'full manifest returned') t.end() }) @@ -457,7 +457,7 @@ test('fetchPackageToStore() concurrency check', async (t) => { { const fetchResult = await fetchResults[0] - const files = await fetchResult.fetchingFiles + const files = await fetchResult.fetchingFiles() ino1 = fs.statSync(path.join(fetchResult.inStoreLocation, 'package', 'package.json')).ino @@ -471,7 +471,7 @@ test('fetchPackageToStore() concurrency check', async (t) => { { const fetchResult = await fetchResults[1] - const files = await fetchResult.fetchingFiles + const files = await fetchResult.fetchingFiles() ino2 = fs.statSync(path.join(fetchResult.inStoreLocation, 'package', 'package.json')).ino @@ -480,7 +480,7 @@ test('fetchPackageToStore() concurrency check', async (t) => { fromStore: false, }, 'returned info about files after fetch completed') - t.ok(fetchResult.finishing) + t.ok(fetchResult.finishing()) } t.equal(ino1, ino2, 'package fetched only once to the store') @@ -525,7 +525,7 @@ test('fetchPackageToStore() does not cache errors', async (t) => { tarball: 'https://registry.npmjs.org/is-positive/-/is-positive-1.0.0.tgz', }, }) - await badRequest.fetchingFiles + await badRequest.fetchingFiles() t.fail('first fetch should have failed') } catch (err) { t.pass('first fetch failed') @@ -541,13 +541,13 @@ test('fetchPackageToStore() does not cache errors', async (t) => { tarball: 'https://registry.npmjs.org/is-positive/-/is-positive-1.0.0.tgz', }, }) - const files = await fetchResult.fetchingFiles + const files = await fetchResult.fetchingFiles() t.deepEqual(files, { filenames: [ 'package.json', 'index.js', 'license', 'readme.md' ], fromStore: false, }, 'returned info about files after fetch completed') - t.ok(fetchResult.finishing) + t.ok(fetchResult.finishing()) t.ok(nock.isDone()) t.end() @@ -590,10 +590,10 @@ test('always return a package manifest in the response', async t => { preferredVersions: {}, prefix, registry, - }) as PackageResponse & {fetchingRawManifest: Promise} + }) as PackageResponse & {fetchingRawManifest: () => Promise} t.ok(pkgResponse.body, 'response has body') - t.ok((await pkgResponse.fetchingRawManifest).name, 'response has manifest') + t.ok((await pkgResponse.fetchingRawManifest()).name, 'response has manifest') } t.end() @@ -634,7 +634,7 @@ test('fetchPackageToStore() fetch raw manifest of cached package', async (t) => }) ]) - t.ok(await fetchResults[1].fetchingRawManifest) + t.ok(await fetchResults[1].fetchingRawManifest!()) t.end() }) @@ -666,7 +666,7 @@ test('refetch package to store if it has been modified', async (t) => { resolution, }) - await fetchResult.fetchingFiles + await fetchResult.fetchingFiles() } const distPathInStore = await path.join(storePath, pkgId, 'node_modules', 'magic-hook', 'dist') @@ -696,7 +696,7 @@ test('refetch package to store if it has been modified', async (t) => { resolution, }) - await fetchResult.fetchingFiles + await fetchResult.fetchingFiles() } streamParser.removeListener('data', reporter) @@ -740,7 +740,7 @@ test('refetch package to store if it has no integrity checksums and verification resolution, }) - await fetchResult.fetchingFiles + await fetchResult.fetchingFiles() const integrityJson = await loadJsonFile(path.join(storePath, pkgId, 'integrity.json')) t.notOk(integrityJson['package.json'].integrity, 'no integrity hash generated') @@ -765,7 +765,7 @@ test('refetch package to store if it has no integrity checksums and verification resolution, }) - await fetchResult.fetchingFiles + await fetchResult.fetchingFiles() const integrityJson = await loadJsonFile(path.join(storePath, pkgId, 'integrity.json')) t.ok(integrityJson['package.json'].integrity, 'integrity hash generated') diff --git a/packages/package-store/test/index.ts b/packages/package-store/test/index.ts index ff54e2edda..c548c88c27 100644 --- a/packages/package-store/test/index.ts +++ b/packages/package-store/test/index.ts @@ -43,7 +43,7 @@ test('store.importPackage()', async (t) => { const importTo = tempy.directory() const importFrom = path.join(fetchResult.inStoreLocation, 'node_modules', 'is-positive') await storeController.importPackage(importFrom, importTo, { - filesResponse: await fetchResult.fetchingFiles, + filesResponse: await fetchResult.fetchingFiles(), force: false, }) t.equal(typeof require(importTo), 'function', `sucessfully imported to ${importTo}`) @@ -82,7 +82,7 @@ test('store.importPackage() by copying', async (t) => { const importTo = tempy.directory() const importFrom = path.join(fetchResult.inStoreLocation, 'node_modules', 'is-positive') await storeController.importPackage(importFrom, importTo, { - filesResponse: await fetchResult.fetchingFiles, + filesResponse: await fetchResult.fetchingFiles(), force: false, }) t.equal(typeof require(importTo), 'function', `sucessfully imported to ${importTo}`) diff --git a/packages/pnpm/test/utils/execPnpm.ts b/packages/pnpm/test/utils/execPnpm.ts index af0b11f04d..285dfe8450 100644 --- a/packages/pnpm/test/utils/execPnpm.ts +++ b/packages/pnpm/test/utils/execPnpm.ts @@ -67,6 +67,7 @@ function createEnv (opts?: {storeDir?: string}) { const _ = { ...process.env, npm_config_fetch_retries: 4, + npm_config_hoist: true, npm_config_independent_leaves: false, npm_config_registry: 'http://localhost:4873/', npm_config_silent: 'true', diff --git a/packages/resolve-dependencies/src/resolveDependencies.ts b/packages/resolve-dependencies/src/resolveDependencies.ts index f23d07a3ee..3b25ab82a7 100644 --- a/packages/resolve-dependencies/src/resolveDependencies.ts +++ b/packages/resolve-dependencies/src/resolveDependencies.ts @@ -167,9 +167,9 @@ export interface ResolvedPackage { prod: boolean, dev: boolean, optional: boolean, - fetchingFiles: Promise, - fetchingRawManifest?: Promise, - finishing: Promise, + fetchingFiles: () => Promise, + fetchingRawManifest?: () => Promise, + finishing: () => Promise, path: string, name: string, version: string, @@ -582,7 +582,7 @@ async function resolveDependency ( } if (pkgResponse.body.isLocal) { - const manifest = pkgResponse.body.manifest || await pkgResponse['fetchingRawManifest'] // tslint:disable-line:no-string-literal + const manifest = pkgResponse.body.manifest || await pkgResponse['fetchingRawManifest']() // tslint:disable-line:no-string-literal if (options.currentDepth > 0) { logger.warn({ message: `Ignoring file dependency because it is not a root dependency ${wantedDependency}`, @@ -631,31 +631,22 @@ async function resolveDependency ( ) } else { // tslint:disable:no-string-literal - try { - pkg = ctx.readPackageHook - ? ctx.readPackageHook(pkgResponse.body['manifest'] || await pkgResponse['fetchingRawManifest']) - : pkgResponse.body['manifest'] || await pkgResponse['fetchingRawManifest'] + pkg = ctx.readPackageHook + ? ctx.readPackageHook(pkgResponse.body['manifest'] || await pkgResponse['fetchingRawManifest']()) + : pkgResponse.body['manifest'] || await pkgResponse['fetchingRawManifest']() - prepare = Boolean( - pkgResponse.body['resolvedVia'] === 'git-repository' && - pkg['scripts'] && typeof pkg['scripts']['prepare'] === 'string', - ) + prepare = Boolean( + pkgResponse.body['resolvedVia'] === 'git-repository' && + pkg['scripts'] && typeof pkg['scripts']['prepare'] === 'string', + ) - if ( - options.dependencyLockfile && options.dependencyLockfile.deprecated && - !pkgResponse.body.updated && !pkg.deprecated - ) { - pkg.deprecated = options.dependencyLockfile.deprecated - } - hasBin = Boolean(pkg.bin && !R.isEmpty(pkg.bin) || pkg.directories && pkg.directories.bin) - } catch (err) { - // tslint:disable:no-empty - // avoiding unhandled promise rejections - if (pkgResponse['finishing']) pkgResponse['finishing'].catch(() => {}) - if (pkgResponse['fetchingFiles']) pkgResponse['fetchingFiles'].catch(() => {}) - // tslint:enable:no-empty - throw err + if ( + options.dependencyLockfile && options.dependencyLockfile.deprecated && + !pkgResponse.body.updated && !pkg.deprecated + ) { + pkg.deprecated = options.dependencyLockfile.deprecated } + hasBin = Boolean(pkg.bin && !R.isEmpty(pkg.bin) || pkg.directories && pkg.directories.bin) // tslint:enable:no-string-literal } if (!pkg.name) { // TODO: don't fail on optional dependencies @@ -702,7 +693,7 @@ async function resolveDependency ( }) // tslint:disable:no-string-literal if (pkgResponse['fetchingFiles']) { - pkgResponse['fetchingFiles'] + pkgResponse['fetchingFiles']() .then((fetchResult: PackageFilesResponse) => { progressLogger.debug({ packageId: pkgResponse.body.id, @@ -711,6 +702,9 @@ async function resolveDependency ( ? 'found_in_store' : 'fetched', }) }) + .catch(() => { + // Ignore + }) } // tslint:enable:no-string-literal diff --git a/packages/server/package.json b/packages/server/package.json index 2ca2549c7b..16e39cae7e 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -52,6 +52,7 @@ "@pnpm/store-controller-types": "workspace:3.0.3", "@pnpm/types": "workspace:3.2.0", "p-limit": "2.2.1", + "promise-share": "1.0.0", "uuid": "3.3.3" } } diff --git a/packages/server/src/connectStoreController.ts b/packages/server/src/connectStoreController.ts index b45ae27144..81caa9aa36 100644 --- a/packages/server/src/connectStoreController.ts +++ b/packages/server/src/connectStoreController.ts @@ -11,6 +11,7 @@ import { import { PackageJson } from '@pnpm/types' import pLimit from 'p-limit' +import pShare = require('promise-share') import uuid = require('uuid') export type StoreServerController = StoreController & { @@ -131,7 +132,7 @@ function requestPackage ( if (options.skipFetch) { return { body: packageResponseBody, - fetchingRawManifest, + fetchingRawManifest: fetchingRawManifest && pShare(fetchingRawManifest), } } @@ -140,9 +141,9 @@ function requestPackage ( }) return { body: packageResponseBody, - fetchingFiles, - fetchingRawManifest, - finishing: Promise.all([fetchingRawManifest, fetchingFiles]).then(() => undefined), + fetchingFiles: pShare(fetchingFiles), + fetchingRawManifest: fetchingRawManifest && pShare(fetchingRawManifest), + finishing: pShare(Promise.all([fetchingRawManifest, fetchingFiles]).then(() => undefined)), } }) } @@ -152,9 +153,9 @@ function fetchPackage ( limitedFetch: (url: string, body: object) => any, // tslint:disable-line options: FetchPackageToStoreOptions, ): { - fetchingFiles: Promise, - fetchingRawManifest?: Promise, - finishing: Promise, + fetchingFiles: () => Promise, + fetchingRawManifest?: () => Promise, + finishing: () => Promise, inStoreLocation: string, } { const msgId = uuid.v4() @@ -172,9 +173,9 @@ function fetchPackage ( msgId, }) return { - fetchingFiles, - fetchingRawManifest, - finishing: Promise.all([fetchingRawManifest, fetchingFiles]).then(() => undefined), + fetchingFiles: pShare(fetchingFiles), + fetchingRawManifest: fetchingRawManifest && pShare(fetchingRawManifest), + finishing: pShare(Promise.all([fetchingRawManifest, fetchingFiles]).then(() => undefined)), inStoreLocation: fetchResponseBody.inStoreLocation, } }) diff --git a/packages/server/src/createServer.ts b/packages/server/src/createServer.ts index 5b8fc6cba9..f152fa65cb 100644 --- a/packages/server/src/createServer.ts +++ b/packages/server/src/createServer.ts @@ -116,13 +116,13 @@ export default function ( } case '/packageFilesResponse': body = await bodyPromise - const filesResponse = await filesPromises[body.msgId] + const filesResponse = await filesPromises[body.msgId]() delete filesPromises[body.msgId] res.end(JSON.stringify(filesResponse)) break case '/rawManifestResponse': body = await bodyPromise - const manifestResponse = await rawManifestPromises[body.msgId] + const manifestResponse = await rawManifestPromises[body.msgId]() delete rawManifestPromises[body.msgId] res.end(JSON.stringify(manifestResponse)) break diff --git a/packages/server/test/index.ts b/packages/server/test/index.ts index 83a3905505..d37ebde559 100644 --- a/packages/server/test/index.ts +++ b/packages/server/test/index.ts @@ -60,18 +60,18 @@ test('server', async t => { } ) - t.equal((await response['fetchingRawManifest']).name, 'is-positive', 'responded with fetchingRawManifest') + t.equal((await response['fetchingRawManifest']()).name, 'is-positive', 'responded with fetchingRawManifest') t.equal(response.body.id, 'registry.npmjs.org/is-positive/1.0.0', 'responded with correct ID') t.equal(response.body['manifest'].name, 'is-positive', 'responded with correct name in manifest') t.equal(response.body['manifest'].version, '1.0.0', 'responded with correct version in manifest') - const files = await response['fetchingFiles'] as PackageFilesResponse + const files = await response['fetchingFiles']() as PackageFilesResponse t.notOk(files.fromStore) t.ok(files.filenames.includes('package.json')) t.ok(response['finishing']) - await response['finishing'] + await response['finishing']() await server.close() await storeCtrl.close() @@ -103,14 +103,14 @@ test('fetchPackage', async t => { t.equal(typeof response.inStoreLocation, 'string', 'location in store returned') - t.ok(await response.fetchingRawManifest) + t.ok(await response.fetchingRawManifest!()) - const files = await response['fetchingFiles'] as PackageFilesResponse + const files = await response['fetchingFiles']() as PackageFilesResponse t.notOk(files.fromStore) t.ok(files.filenames.includes('package.json')) t.ok(response['finishing']) - await response['finishing'] + await response['finishing']() t.comment('getPackageLocation()') @@ -322,8 +322,8 @@ test('find package usages', async t => { sideEffectsCache: false, } ) - await requestResponse['fetchingRawManifest'] - await requestResponse['finishing'] + await requestResponse['fetchingRawManifest']() + await requestResponse['finishing']() // For debugging purposes await storeCtrl.saveState() diff --git a/packages/store-controller-types/src/index.ts b/packages/store-controller-types/src/index.ts index c5254a07b1..ee4e415d1e 100644 --- a/packages/store-controller-types/src/index.ts +++ b/packages/store-controller-types/src/index.ts @@ -43,9 +43,9 @@ export type PackageUsages = { export type FetchPackageToStoreFunction = ( opts: FetchPackageToStoreOptions, ) => { - fetchingFiles: Promise, - fetchingRawManifest?: Promise, - finishing: Promise, + fetchingFiles: () => Promise, + fetchingRawManifest?: () => Promise, + finishing: () => Promise, inStoreLocation: string, } @@ -109,8 +109,8 @@ export type PackageResponse = { }, } | ( { - fetchingFiles?: Promise, - finishing?: Promise, // a package request is finished once its integrity is generated and saved + fetchingFiles?: () => Promise, + finishing?: () => Promise, // a package request is finished once its integrity is generated and saved body: { isLocal: false, inStoreLocation: string, @@ -127,7 +127,7 @@ export type PackageResponse = { }, } & ( { - fetchingRawManifest: Promise, + fetchingRawManifest: () => Promise, } | { body: { manifest: PackageManifest, diff --git a/packages/supi/src/install/index.ts b/packages/supi/src/install/index.ts index 69f3f51fa8..117cd76540 100644 --- a/packages/supi/src/install/index.ts +++ b/packages/supi/src/install/index.ts @@ -854,11 +854,11 @@ async function installInContext ( // skipped packages might have not been reanalized on a repeat install // so lets just ignore those by excluding nulls .filter(Boolean) - .map(({ fetchingFiles }) => fetchingFiles), + .map(({ fetchingFiles }) => fetchingFiles()), ) // waiting till package requests are finished - await Promise.all(R.values(resolvedPackagesByPackageId).map(({ finishing }) => finishing)) + await Promise.all(R.values(resolvedPackagesByPackageId).map(({ finishing }) => finishing())) const lockfileOpts = { forceSharedFormat: opts.forceSharedLockfile } if (opts.lockfileOnly) { diff --git a/packages/supi/src/install/link.ts b/packages/supi/src/install/link.ts index 9b12d1931f..cac8899c6e 100644 --- a/packages/supi/src/install/link.ts +++ b/packages/supi/src/install/link.ts @@ -247,9 +247,9 @@ export default async function linkPackages ( // This should never ever happen throw new Error(`Cannot create ${WANTED_LOCKFILE} because raw manifest (aka package.json) wasn't fetched for "${absoluteDepPath}"`) } - const filesResponse = await depNode.fetchingFiles + const filesResponse = await depNode.fetchingFiles() // The npm team suggests to always read the package.json for deciding whether the package has lifecycle scripts - const pkgJson = await depNode.fetchingRawManifest + const pkgJson = await depNode.fetchingRawManifest() depNode.requiresBuild = Boolean( pkgJson.scripts && (pkgJson.scripts.preinstall || pkgJson.scripts.install || pkgJson.scripts.postinstall) || filesResponse.filenames.includes('binding.gyp') || @@ -480,7 +480,7 @@ async function linkAllPkgs ( ) { return Promise.all( depNodes.map(async ({ centralLocation, fetchingFiles, independent, peripheralLocation }) => { - const filesResponse = await fetchingFiles + const filesResponse = await fetchingFiles() if (independent) return return storeController.importPackage(centralLocation, peripheralLocation, { diff --git a/packages/supi/src/install/resolvePeers.ts b/packages/supi/src/install/resolvePeers.ts index 5de88f1077..3e2da66ea9 100644 --- a/packages/supi/src/install/resolvePeers.ts +++ b/packages/supi/src/install/resolvePeers.ts @@ -27,8 +27,8 @@ export interface DependenciesGraphNode { hasBundledDependencies: boolean, centralLocation: string, modules: string, - fetchingFiles: Promise, - fetchingRawManifest?: Promise, + fetchingFiles: () => Promise, + fetchingRawManifest?: () => Promise, resolution: Resolution, peripheralLocation: string, children: {[alias: string]: string}, diff --git a/packages/supi/src/storeAdd.ts b/packages/supi/src/storeAdd.ts index d33fb5bb82..f10b0c2e76 100644 --- a/packages/supi/src/storeAdd.ts +++ b/packages/supi/src/storeAdd.ts @@ -48,7 +48,7 @@ export default async function ( prefix, registry: dep.alias && pickRegistryForPackage(registries, dep.alias) || registries.default, }) - await pkgResponse['fetchingFiles'] // tslint:disable-line:no-string-literal + await pkgResponse['fetchingFiles']() // tslint:disable-line:no-string-literal storeLogger.info(`+ ${pkgResponse.body.id}`) } catch (e) { hasFailures = true diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b89050171c..e6e3b3bc64 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -905,6 +905,7 @@ importers: p-limit: 2.2.1 p-queue: 6.1.1 path-exists: 4.0.0 + promise-share: 1.0.0 rename-overwrite: 2.0.2 ssri: 6.0.1 symlink-dir: 3.1.1 @@ -958,6 +959,7 @@ importers: p-limit: 2.2.1 p-queue: 6.1.1 path-exists: 4.0.0 + promise-share: 1.0.0 rename-overwrite: 2.0.2 rimraf: 3.0.0 sinon: 7.4.2 @@ -1428,6 +1430,7 @@ importers: '@pnpm/store-controller-types': 'link:../store-controller-types' '@pnpm/types': 'link:../types' p-limit: 2.2.1 + promise-share: 1.0.0 uuid: 3.3.3 devDependencies: '@pnpm/logger': 2.1.1 @@ -1463,6 +1466,7 @@ importers: mz: 2.7.0 node-fetch: 2.6.0 p-limit: 2.2.1 + promise-share: 1.0.0 rimraf: 3.0.0 tape: 4.11.0 uuid: 3.3.3 @@ -6405,6 +6409,12 @@ packages: node: '>=8' resolution: integrity: sha512-R9gq36Th88xZ+rWAptN5IXLwqkwA1gagCQhT6ZXQ6RxEfmjb9ZW+UBzRVqv9sm5TQmbbI/TsKgGLbOaA61xR5w== + /p-reflect/2.1.0: + dev: false + engines: + node: '>=8' + resolution: + integrity: sha512-paHV8NUz8zDHu5lhr/ngGWQiW067DK/+IbJ+RfZ4k+s8y4EKyYCz8pGYWjxCg35eHztpJAt+NUgvN4L+GCbPlg== /p-some/4.1.0: dependencies: aggregate-error: 3.0.0 @@ -6696,6 +6706,14 @@ packages: /process-nextick-args/2.0.1: resolution: integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== + /promise-share/1.0.0: + dependencies: + p-reflect: 2.1.0 + dev: false + engines: + node: '>=8' + resolution: + integrity: sha512-lpABypysb42MdCZjMJAdapxt+uTU9F0BZW0YeYVlPD/Gv390c43CdFwBSC9YM3siAgyAjLV94WDuDnwHIJjxiw== /propagate/2.0.1: dev: true engines: