UNPKG

9.59 kBJavaScriptView Raw
1"use strict";
2/**
3 * @license
4 * Copyright Google LLC All Rights Reserved.
5 *
6 * Use of this source code is governed by an MIT-style license that can be
7 * found in the LICENSE file at https://angular.io/license
8 */
9var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
10 if (k2 === undefined) k2 = k;
11 Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
12}) : (function(o, m, k, k2) {
13 if (k2 === undefined) k2 = k;
14 o[k2] = m[k];
15}));
16var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
17 Object.defineProperty(o, "default", { enumerable: true, value: v });
18}) : function(o, v) {
19 o["default"] = v;
20});
21var __importStar = (this && this.__importStar) || function (mod) {
22 if (mod && mod.__esModule) return mod;
23 var result = {};
24 if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
25 __setModuleDefault(result, mod);
26 return result;
27};
28Object.defineProperty(exports, "__esModule", { value: true });
29exports.getNpmPackageJson = exports.fetchPackageManifest = exports.fetchPackageMetadata = void 0;
30const fs_1 = require("fs");
31const os_1 = require("os");
32const path = __importStar(require("path"));
33const lockfile = require('@yarnpkg/lockfile');
34const ini = require('ini');
35const pacote = require('pacote');
36const npmPackageJsonCache = new Map();
37let npmrc;
38function ensureNpmrc(logger, usingYarn, verbose) {
39 if (!npmrc) {
40 try {
41 npmrc = readOptions(logger, false, verbose);
42 }
43 catch { }
44 if (usingYarn) {
45 try {
46 npmrc = { ...npmrc, ...readOptions(logger, true, verbose) };
47 }
48 catch { }
49 }
50 }
51}
52function readOptions(logger, yarn = false, showPotentials = false) {
53 const cwd = process.cwd();
54 const baseFilename = yarn ? 'yarnrc' : 'npmrc';
55 const dotFilename = '.' + baseFilename;
56 let globalPrefix;
57 if (process.env.PREFIX) {
58 globalPrefix = process.env.PREFIX;
59 }
60 else {
61 globalPrefix = path.dirname(process.execPath);
62 if (process.platform !== 'win32') {
63 globalPrefix = path.dirname(globalPrefix);
64 }
65 }
66 const defaultConfigLocations = [
67 (!yarn && process.env.NPM_CONFIG_GLOBALCONFIG) || path.join(globalPrefix, 'etc', baseFilename),
68 (!yarn && process.env.NPM_CONFIG_USERCONFIG) || path.join(os_1.homedir(), dotFilename),
69 ];
70 const projectConfigLocations = [path.join(cwd, dotFilename)];
71 if (yarn) {
72 const root = path.parse(cwd).root;
73 for (let curDir = path.dirname(cwd); curDir && curDir !== root; curDir = path.dirname(curDir)) {
74 projectConfigLocations.unshift(path.join(curDir, dotFilename));
75 }
76 }
77 if (showPotentials) {
78 logger.info(`Locating potential ${baseFilename} files:`);
79 }
80 let rcOptions = {};
81 for (const location of [...defaultConfigLocations, ...projectConfigLocations]) {
82 if (fs_1.existsSync(location)) {
83 if (showPotentials) {
84 logger.info(`Trying '${location}'...found.`);
85 }
86 const data = fs_1.readFileSync(location, 'utf8');
87 // Normalize RC options that are needed by 'npm-registry-fetch'.
88 // See: https://github.com/npm/npm-registry-fetch/blob/ebddbe78a5f67118c1f7af2e02c8a22bcaf9e850/index.js#L99-L126
89 const rcConfig = yarn ? lockfile.parse(data) : ini.parse(data);
90 rcOptions = normalizeOptions(rcConfig, location, rcOptions);
91 }
92 }
93 const envVariablesOptions = {};
94 for (const [key, value] of Object.entries(process.env)) {
95 if (!value) {
96 continue;
97 }
98 let normalizedName = key.toLowerCase();
99 if (normalizedName.startsWith('npm_config_')) {
100 normalizedName = normalizedName.substring(11);
101 }
102 else if (yarn && normalizedName.startsWith('yarn_')) {
103 normalizedName = normalizedName.substring(5);
104 }
105 else {
106 continue;
107 }
108 normalizedName = normalizedName.replace(/(?!^)_/g, '-'); // don't replace _ at the start of the key.s
109 envVariablesOptions[normalizedName] = value;
110 }
111 return normalizeOptions(envVariablesOptions, undefined, rcOptions);
112}
113function normalizeOptions(rawOptions, location = process.cwd(), existingNormalizedOptions = {}) {
114 var _a;
115 const options = { ...existingNormalizedOptions };
116 for (const [key, value] of Object.entries(rawOptions)) {
117 let substitutedValue = value;
118 // Substitute any environment variable references.
119 if (typeof value === 'string') {
120 substitutedValue = value.replace(/\$\{([^\}]+)\}/, (_, name) => process.env[name] || '');
121 }
122 switch (key) {
123 // Unless auth options are scope with the registry url it appears that npm-registry-fetch ignores them,
124 // even though they are documented.
125 // https://github.com/npm/npm-registry-fetch/blob/8954f61d8d703e5eb7f3d93c9b40488f8b1b62ac/README.md
126 // https://github.com/npm/npm-registry-fetch/blob/8954f61d8d703e5eb7f3d93c9b40488f8b1b62ac/auth.js#L45-L91
127 case '_authToken':
128 case 'token':
129 case 'username':
130 case 'password':
131 case '_auth':
132 case 'auth':
133 (_a = options['forceAuth']) !== null && _a !== void 0 ? _a : (options['forceAuth'] = {});
134 options['forceAuth'][key] = substitutedValue;
135 break;
136 case 'noproxy':
137 case 'no-proxy':
138 options['noProxy'] = substitutedValue;
139 break;
140 case 'maxsockets':
141 options['maxSockets'] = substitutedValue;
142 break;
143 case 'https-proxy':
144 case 'proxy':
145 options['proxy'] = substitutedValue;
146 break;
147 case 'strict-ssl':
148 options['strictSSL'] = substitutedValue;
149 break;
150 case 'local-address':
151 options['localAddress'] = substitutedValue;
152 break;
153 case 'cafile':
154 if (typeof substitutedValue === 'string') {
155 const cafile = path.resolve(path.dirname(location), substitutedValue);
156 try {
157 options['ca'] = fs_1.readFileSync(cafile, 'utf8').replace(/\r?\n/g, '\n');
158 }
159 catch { }
160 }
161 break;
162 default:
163 options[key] = substitutedValue;
164 break;
165 }
166 }
167 return options;
168}
169function normalizeManifest(rawManifest) {
170 // TODO: Fully normalize and sanitize
171 return {
172 dependencies: {},
173 devDependencies: {},
174 peerDependencies: {},
175 optionalDependencies: {},
176 ...rawManifest,
177 };
178}
179async function fetchPackageMetadata(name, logger, options) {
180 const { usingYarn, verbose, registry } = {
181 registry: undefined,
182 usingYarn: false,
183 verbose: false,
184 ...options,
185 };
186 ensureNpmrc(logger, usingYarn, verbose);
187 const response = await pacote.packument(name, {
188 fullMetadata: true,
189 ...npmrc,
190 ...(registry ? { registry } : {}),
191 });
192 // Normalize the response
193 const metadata = {
194 name: response.name,
195 tags: {},
196 versions: {},
197 };
198 if (response.versions) {
199 for (const [version, manifest] of Object.entries(response.versions)) {
200 metadata.versions[version] = normalizeManifest(manifest);
201 }
202 }
203 if (response['dist-tags']) {
204 // Store this for use with other npm utility packages
205 metadata['dist-tags'] = response['dist-tags'];
206 for (const [tag, version] of Object.entries(response['dist-tags'])) {
207 const manifest = metadata.versions[version];
208 if (manifest) {
209 metadata.tags[tag] = manifest;
210 }
211 else if (verbose) {
212 logger.warn(`Package ${metadata.name} has invalid version metadata for '${tag}'.`);
213 }
214 }
215 }
216 return metadata;
217}
218exports.fetchPackageMetadata = fetchPackageMetadata;
219async function fetchPackageManifest(name, logger, options = {}) {
220 const { usingYarn = false, verbose = false, registry } = options;
221 ensureNpmrc(logger, usingYarn, verbose);
222 const response = await pacote.manifest(name, {
223 fullMetadata: true,
224 ...npmrc,
225 ...(registry ? { registry } : {}),
226 });
227 return normalizeManifest(response);
228}
229exports.fetchPackageManifest = fetchPackageManifest;
230function getNpmPackageJson(packageName, logger, options = {}) {
231 const cachedResponse = npmPackageJsonCache.get(packageName);
232 if (cachedResponse) {
233 return cachedResponse;
234 }
235 const { usingYarn = false, verbose = false, registry } = options;
236 ensureNpmrc(logger, usingYarn, verbose);
237 const resultPromise = pacote.packument(packageName, {
238 fullMetadata: true,
239 ...npmrc,
240 ...(registry ? { registry } : {}),
241 });
242 // TODO: find some way to test this
243 const response = resultPromise.catch((err) => {
244 logger.warn(err.message || err);
245 return { requestedName: packageName };
246 });
247 npmPackageJsonCache.set(packageName, response);
248 return response;
249}
250exports.getNpmPackageJson = getNpmPackageJson;