From d93848f488c1e83fdff0a964b3d0bcbd05aea4c1 Mon Sep 17 00:00:00 2001 From: Andrew Branch Date: Fri, 8 Mar 2024 14:37:01 -0800 Subject: [PATCH] API: distinguish between npm 404s and other thrown errors --- .changeset/fresh-queens-clean.md | 5 ++++ packages/core/src/createPackage.ts | 37 +++++++++++++++++++----------- 2 files changed, 28 insertions(+), 14 deletions(-) create mode 100644 .changeset/fresh-queens-clean.md diff --git a/.changeset/fresh-queens-clean.md b/.changeset/fresh-queens-clean.md new file mode 100644 index 0000000..d18b58c --- /dev/null +++ b/.changeset/fresh-queens-clean.md @@ -0,0 +1,5 @@ +--- +"@arethetypeswrong/core": patch +--- + +API: distinguish between npm 404s and other thrown errors diff --git a/packages/core/src/createPackage.ts b/packages/core/src/createPackage.ts index 79dce43..40851d3 100644 --- a/packages/core/src/createPackage.ts +++ b/packages/core/src/createPackage.ts @@ -227,20 +227,22 @@ async function getNpmTarballUrl( for (const packageSpec of packageSpecs) { const manifestUrl = `https://registry.npmjs.org/${packageSpec.name}/${packageSpec.version || "latest"}`; const doc = packument || (await fetch(manifestUrl).then((r) => r.json())); - if (typeof doc !== "object") { - continue; + if (typeof doc !== "object" || (doc.error && doc.error !== "Not found")) { + throw new Error(`Unexpected response from ${manifestUrl}: ${JSON.stringify(doc)}`); } const isManifest = !!doc.version; let tarballUrl, packageVersion; if (packageSpec.versionKind === "range") { - packageVersion = maxSatisfying( - Object.keys(doc.versions).filter( - (v) => - (allowDeprecated || !doc.versions[v].deprecated) && - (!before || !doc.time || new Date(doc.time[v]) <= before), - ), - packageSpec.version, - ); + packageVersion = + doc.versions && + maxSatisfying( + Object.keys(doc.versions).filter( + (v) => + (allowDeprecated || !doc.versions[v].deprecated) && + (!before || !doc.time || new Date(doc.time[v]) <= before), + ), + packageSpec.version, + ); if (!packageVersion) { continue; } @@ -256,17 +258,24 @@ async function getNpmTarballUrl( tarballUrl = doc.versions[packageVersion].dist.tarball; } else if (isManifest) { packageVersion = doc.version; - tarballUrl = doc.dist.tarball; + tarballUrl = doc.dist?.tarball; } else { - packageVersion = doc["dist-tags"].latest; - tarballUrl = doc.versions[packageVersion].dist.tarball; + packageVersion = doc["dist-tags"]?.latest; + tarballUrl = doc.versions?.[packageVersion].dist.tarball; } if (packageVersion && tarballUrl) { return { packageName: packageSpec.name, packageVersion, tarballUrl }; } } - throw new Error(`Failed to find a matching version for ${packageSpecs[0].name}`); + throw new Npm404Error(packageSpecs); +} + +export class Npm404Error extends Error { + kind = "Npm404Error"; + constructor(public packageSpecs: readonly ParsedPackageSpec[]) { + super(`Failed to find a matching version for ${packageSpecs[0].name}`); + } } export async function createPackageFromTarballUrl(tarballUrl: string): Promise {