-
-
Notifications
You must be signed in to change notification settings - Fork 62
/
index.js
92 lines (74 loc) · 2.25 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
import ky from 'ky';
import registryUrl from 'registry-url';
import registryAuthToken from 'registry-auth-token';
import semver from 'semver';
export class PackageNotFoundError extends Error {
constructor(packageName) {
super(`Package \`${packageName}\` could not be found`);
this.name = 'PackageNotFoundError';
}
}
export class VersionNotFoundError extends Error {
constructor(packageName, version) {
super(`Version \`${version}\` for package \`${packageName}\` could not be found`);
this.name = 'VersionNotFoundError';
}
}
export default async function packageJson(packageName, options = {}) {
let {version = 'latest'} = options;
const {omitDeprecated = true} = options;
const scope = packageName.split('/')[0];
const registryUrl_ = options.registryUrl ?? registryUrl(scope);
const packageUrl = new URL(encodeURIComponent(packageName).replace(/^%40/, '@'), registryUrl_);
const authInfo = registryAuthToken(registryUrl_.toString(), {recursive: true});
const headers = {
accept: 'application/vnd.npm.install-v1+json; q=1.0, application/json; q=0.8, */*',
};
if (options.fullMetadata) {
delete headers.accept;
}
if (authInfo) {
headers.authorization = `${authInfo.type} ${authInfo.token}`;
}
let data;
try {
data = await ky(packageUrl, {headers, keepalive: true}).json();
} catch (error) {
if (error?.response?.status === 404) {
throw new PackageNotFoundError(packageName);
}
throw error;
}
if (options.allVersions) {
return data;
}
const versionError = new VersionNotFoundError(packageName, version);
if (data['dist-tags'][version]) {
const {time} = data;
data = data.versions[data['dist-tags'][version]];
data.time = time;
} else if (version) {
const versionExists = Boolean(data.versions[version]);
if (omitDeprecated && !versionExists) {
for (const [metadataVersion, metadata] of Object.entries(data.versions)) {
if (metadata.deprecated) {
delete data.versions[metadataVersion];
}
}
}
if (!versionExists) {
const versions = Object.keys(data.versions);
version = semver.maxSatisfying(versions, version);
if (!version) {
throw versionError;
}
}
const {time} = data;
data = data.versions[version];
data.time = time;
if (!data) {
throw versionError;
}
}
return data;
}