fcs
2025-04-10 0163870d662dc5b7d69ceff977490ede594f7d82
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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
'use strict';
const {URL} = require('url');
const {Agent: HttpAgent} = require('http');
const {Agent: HttpsAgent} = require('https');
const got = require('got');
const registryUrl = require('registry-url');
const registryAuthToken = require('registry-auth-token');
const semver = require('semver');
 
// These agent options are chosen to match the npm client defaults and help with performance
// See: `npm config get maxsockets` and #50
const agentOptions = {
    keepAlive: true,
    maxSockets: 50
};
const httpAgent = new HttpAgent(agentOptions);
const httpsAgent = new HttpsAgent(agentOptions);
 
class PackageNotFoundError extends Error {
    constructor(packageName) {
        super(`Package \`${packageName}\` could not be found`);
        this.name = 'PackageNotFoundError';
    }
}
 
class VersionNotFoundError extends Error {
    constructor(packageName, version) {
        super(`Version \`${version}\` for package \`${packageName}\` could not be found`);
        this.name = 'VersionNotFoundError';
    }
}
 
const packageJson = async (packageName, options) => {
    options = {
        version: 'latest',
        ...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}`;
    }
 
    const gotOptions = {
        json: true,
        headers,
        agent: {
            http: httpAgent,
            https: httpsAgent
        }
    };
 
    if (options.agent) {
        gotOptions.agent = options.agent;
    }
 
    let response;
    try {
        response = await got(packageUrl, gotOptions);
    } catch (error) {
        if (error.statusCode === 404) {
            throw new PackageNotFoundError(packageName);
        }
 
        throw error;
    }
 
    let data = response.body;
 
    if (options.allVersions) {
        return data;
    }
 
    let {version} = options;
    const versionError = new VersionNotFoundError(packageName, version);
 
    if (data['dist-tags'][version]) {
        data = data.versions[data['dist-tags'][version]];
    } else if (version) {
        if (!data.versions[version]) {
            const versions = Object.keys(data.versions);
            version = semver.maxSatisfying(versions, version);
 
            if (!version) {
                throw versionError;
            }
        }
 
        data = data.versions[version];
 
        if (!data) {
            throw versionError;
        }
    }
 
    return data;
};
 
module.exports = packageJson;
// TODO: remove this in the next major version
module.exports.default = packageJson;
module.exports.PackageNotFoundError = PackageNotFoundError;
module.exports.VersionNotFoundError = VersionNotFoundError;