123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115 |
- '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;
|