From de957c92c55a56775eb493349e3197fa4204d007 Mon Sep 17 00:00:00 2001 From: Zoltan Kochan Date: Thu, 29 Dec 2022 05:13:41 +0200 Subject: [PATCH] fix: better error message when the installed package was unpublished close #5849 --- resolving/npm-resolver/src/pickPackage.ts | 9 ++++++++- .../npm-resolver/src/pickPackageFromMeta.ts | 11 +++++++++++ resolving/npm-resolver/test/index.ts | 19 +++++++++++++++++++ 3 files changed, 38 insertions(+), 1 deletion(-) diff --git a/resolving/npm-resolver/src/pickPackage.ts b/resolving/npm-resolver/src/pickPackage.ts index 2990cc34cd8..8ec1adfb127 100644 --- a/resolving/npm-resolver/src/pickPackage.ts +++ b/resolving/npm-resolver/src/pickPackage.ts @@ -20,10 +20,17 @@ export interface PackageMeta { name: string 'dist-tags': Record versions: Record - time?: Record + time?: PackageMetaTime cachedAt?: number } +export type PackageMetaTime = Record & { + unpublished?: { + time: string + versions: string[] + } +} + export interface PackageMetaCache { get: (key: string) => PackageMeta | undefined set: (key: string, meta: PackageMeta) => void diff --git a/resolving/npm-resolver/src/pickPackageFromMeta.ts b/resolving/npm-resolver/src/pickPackageFromMeta.ts index 87301d79fdb..6e9ee952729 100644 --- a/resolving/npm-resolver/src/pickPackageFromMeta.ts +++ b/resolving/npm-resolver/src/pickPackageFromMeta.ts @@ -18,6 +18,14 @@ export function pickPackageFromMeta ( meta: PackageMeta, publishedBy?: Date ): PackageInRegistry | null { + if (!meta.versions || Object.keys(meta.versions).length === 0) { + // Unfortunately, the npm registry doesn't return the time field in the abbreviated metadata. + // So we won't always know if the package was unpublished. + if (meta.time?.unpublished?.versions?.length) { + throw new PnpmError('UNPUBLISHED_PKG', `No versions available for ${spec.name} because it was unpublished`) + } + throw new PnpmError('NO_VERSIONS', `No versions available for ${spec.name}. The package may be unpublished.`) + } try { let version!: string | null switch (spec.type) { @@ -43,6 +51,9 @@ export function pickPackageFromMeta ( } return manifest } catch (err: any) { // eslint-disable-line + // if (meta.unpublished) { + // throw new PnpmError('UNPUBLISHED_PKG', `Package ${spec.name} has been unpublished`) + // } throw new PnpmError('MALFORMED_METADATA', `Received malformed metadata for "${spec.name}"`, { hint: 'This might mean that the package was unpublished from the registry' } diff --git a/resolving/npm-resolver/test/index.ts b/resolving/npm-resolver/test/index.ts index b6a71cf801b..2ac11e0aad8 100644 --- a/resolving/npm-resolver/test/index.ts +++ b/resolving/npm-resolver/test/index.ts @@ -1732,3 +1732,22 @@ test('resolveFromNpm() should normalize the registry', async () => { expect(resolveResult!.manifest!.name).toBe('is-positive') expect(resolveResult!.manifest!.version).toBe('1.0.0') }) + +test('fail when the installed package has no versions', async () => { + nock(registry) + .get('/is-positive') + .reply(200, { + name: 'is-positive', + modified: '2021-09-28T14:21:36.303Z', + }) + + const cacheDir = tempy.directory() + const resolve = createResolveFromNpm({ + cacheDir, + }) + + await expect(resolve({ alias: 'is-positive', pref: '1.0.0' }, { registry })).rejects + .toThrow( + new PnpmError('NO_VERSIONS', 'No versions available for is-positive. The package may be unpublished.') + ) +})