Skip to content

Commit 9f222c4

Browse files
authored
Merge pull request #159 from arethetypeswrong/better-npm-404-errors
API: distinguish between npm 404s and other thrown errors
2 parents 320cc1f + d93848f commit 9f222c4

File tree

2 files changed

+28
-14
lines changed

2 files changed

+28
-14
lines changed

.changeset/fresh-queens-clean.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@arethetypeswrong/core": patch
3+
---
4+
5+
API: distinguish between npm 404s and other thrown errors

packages/core/src/createPackage.ts

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -227,20 +227,22 @@ async function getNpmTarballUrl(
227227
for (const packageSpec of packageSpecs) {
228228
const manifestUrl = `https://registry.npmjs.org/${packageSpec.name}/${packageSpec.version || "latest"}`;
229229
const doc = packument || (await fetch(manifestUrl).then((r) => r.json()));
230-
if (typeof doc !== "object") {
231-
continue;
230+
if (typeof doc !== "object" || (doc.error && doc.error !== "Not found")) {
231+
throw new Error(`Unexpected response from ${manifestUrl}: ${JSON.stringify(doc)}`);
232232
}
233233
const isManifest = !!doc.version;
234234
let tarballUrl, packageVersion;
235235
if (packageSpec.versionKind === "range") {
236-
packageVersion = maxSatisfying(
237-
Object.keys(doc.versions).filter(
238-
(v) =>
239-
(allowDeprecated || !doc.versions[v].deprecated) &&
240-
(!before || !doc.time || new Date(doc.time[v]) <= before),
241-
),
242-
packageSpec.version,
243-
);
236+
packageVersion =
237+
doc.versions &&
238+
maxSatisfying(
239+
Object.keys(doc.versions).filter(
240+
(v) =>
241+
(allowDeprecated || !doc.versions[v].deprecated) &&
242+
(!before || !doc.time || new Date(doc.time[v]) <= before),
243+
),
244+
packageSpec.version,
245+
);
244246
if (!packageVersion) {
245247
continue;
246248
}
@@ -256,17 +258,24 @@ async function getNpmTarballUrl(
256258
tarballUrl = doc.versions[packageVersion].dist.tarball;
257259
} else if (isManifest) {
258260
packageVersion = doc.version;
259-
tarballUrl = doc.dist.tarball;
261+
tarballUrl = doc.dist?.tarball;
260262
} else {
261-
packageVersion = doc["dist-tags"].latest;
262-
tarballUrl = doc.versions[packageVersion].dist.tarball;
263+
packageVersion = doc["dist-tags"]?.latest;
264+
tarballUrl = doc.versions?.[packageVersion].dist.tarball;
263265
}
264266

265267
if (packageVersion && tarballUrl) {
266268
return { packageName: packageSpec.name, packageVersion, tarballUrl };
267269
}
268270
}
269-
throw new Error(`Failed to find a matching version for ${packageSpecs[0].name}`);
271+
throw new Npm404Error(packageSpecs);
272+
}
273+
274+
export class Npm404Error extends Error {
275+
kind = "Npm404Error";
276+
constructor(public packageSpecs: readonly ParsedPackageSpec[]) {
277+
super(`Failed to find a matching version for ${packageSpecs[0].name}`);
278+
}
270279
}
271280

272281
export async function createPackageFromTarballUrl(tarballUrl: string): Promise<Package> {

0 commit comments

Comments
 (0)