UNPKG

24.5 kBJavaScriptView Raw
1"use strict";
2
3Object.defineProperty(exports, "__esModule", {
4 value: true
5});
6exports._installNpmLibDef = installNpmLibDef;
7exports._installNpmLibDefs = installNpmLibDefs;
8exports.name = exports.description = void 0;
9exports.run = run;
10exports.setup = setup;
11
12var _safe = _interopRequireDefault(require("colors/safe"));
13
14var _semver = _interopRequireDefault(require("semver"));
15
16var _cacheRepoUtils = require("../lib/cacheRepoUtils");
17
18var _codeSign = require("../lib/codeSign");
19
20var _envDefs = require("../lib/envDefs");
21
22var _fileUtils = require("../lib/fileUtils");
23
24var _flowProjectUtils = require("../lib/flowProjectUtils");
25
26var _flowVersion = require("../lib/flowVersion");
27
28var _ftConfig = require("../lib/ftConfig");
29
30var _node = require("../lib/node");
31
32var _npmLibDefs = require("../lib/npm/npmLibDefs");
33
34var _npmProjectUtils = require("../lib/npm/npmProjectUtils");
35
36var _semver2 = require("../lib/semver");
37
38var _stubUtils = require("../lib/stubUtils");
39
40var _logger = require("../lib/logger");
41
42function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
43
44const name = 'install [explicitLibDefs...]';
45exports.name = name;
46const description = 'Installs libdefs into the ./flow-typed directory';
47exports.description = description;
48
49function setup(yargs) {
50 return yargs.usage(`$0 ${name} - ${description}`).positional('explicitLibDefs', {
51 describe: 'Explicitly specify packages to install',
52 default: []
53 }).options({
54 flowVersion: {
55 alias: 'f',
56 describe: 'The Flow version that fetched libdefs must be compatible with',
57 type: 'string'
58 },
59 verbose: {
60 describe: 'Print additional, verbose info while installing libdefs',
61 type: 'boolean',
62 demandOption: false
63 },
64 skip: {
65 alias: 's',
66 describe: 'Do not generate stubs for missing libdefs',
67 type: 'boolean',
68 demandOption: false
69 },
70 skipCache: {
71 describe: 'Do not update cache prior to installing libdefs',
72 type: 'boolean',
73 demandOption: false
74 },
75 skipFlowRestart: {
76 describe: 'Do not restart flow after installing libdefs',
77 type: 'boolean',
78 demandOption: false
79 },
80 libdefDir: {
81 alias: 'l',
82 describe: 'Use a custom directory to install libdefs',
83 type: 'string',
84 demandOption: false
85 },
86 cacheDir: {
87 alias: 'c',
88 describe: 'Directory (absolute or relative path, ~ is not supported) to store cache of libdefs',
89 type: 'string',
90 demandOption: false
91 },
92 packageDir: {
93 alias: 'p',
94 describe: 'The relative path of package.json where flow-bin is installed',
95 type: 'string'
96 },
97 overwrite: {
98 alias: 'o',
99 describe: 'Overwrite an existing libdef',
100 type: 'boolean',
101 demandOption: false
102 },
103 ignoreDeps: {
104 alias: 'i',
105 describe: 'Dependency categories to ignore when installing definitions',
106 choices: ['dev', 'bundled', 'peer'],
107 type: 'array'
108 },
109 rootDir: {
110 alias: 'r',
111 describe: 'Directory of .flowconfig relative to node_modules',
112 type: 'string'
113 },
114 useCacheUntil: {
115 alias: 'u',
116 describe: 'Use cache until specified time in milliseconds',
117 type: 'number'
118 }
119 });
120}
121
122async function run(args) {
123 const cwd = typeof args.rootDir === 'string' ? _node.path.resolve(args.rootDir) : process.cwd();
124 const packageDir = typeof args.packageDir === 'string' ? _node.path.resolve(args.packageDir) : cwd;
125 const flowVersion = await (0, _flowVersion.determineFlowSpecificVersion)(packageDir, args.flowVersion);
126 const libdefDir = typeof args.libdefDir === 'string' ? args.libdefDir : 'flow-typed';
127
128 if (args.ignoreDeps !== undefined && !Array.isArray(args.ignoreDeps)) {
129 throw new Error('ignoreDeps is not array');
130 }
131
132 const ignoreDeps = (args.ignoreDeps || []).map(dep => {
133 if (typeof dep !== 'string') {
134 throw new Error('ignoreDeps should be array of strings');
135 }
136
137 return dep;
138 });
139
140 if (args.explicitLibDefs !== undefined && !Array.isArray(args.explicitLibDefs)) {
141 throw new Error('explicitLibDefs is not array');
142 }
143
144 const explicitLibDefs = (args.explicitLibDefs || []).map(dep => {
145 if (typeof dep !== 'string') {
146 throw new Error('explicitLibDefs should be array of strings');
147 }
148
149 return dep;
150 });
151 const ftConfig = (0, _ftConfig.getFtConfig)(cwd);
152
153 if (args.cacheDir) {
154 const cacheDir = _node.path.resolve(String(args.cacheDir));
155
156 console.log('• Setting cache dir', cacheDir);
157 (0, _cacheRepoUtils._setCustomCacheDir)(cacheDir);
158 }
159
160 const useCacheUntil = Number(args.useCacheUntil) || _cacheRepoUtils.CACHE_REPO_EXPIRY;
161
162 const {
163 status: npmLibDefResult,
164 dependencyEnvs
165 } = await installNpmLibDefs({
166 cwd,
167 flowVersion,
168 explicitLibDefs,
169 libdefDir: libdefDir,
170 verbose: Boolean(args.verbose),
171 overwrite: Boolean(args.overwrite),
172 skip: Boolean(args.skip),
173 skipCache: Boolean(args.skipCache),
174 ignoreDeps: ignoreDeps,
175 useCacheUntil: Number(args.useCacheUntil) || _cacheRepoUtils.CACHE_REPO_EXPIRY,
176 ftConfig
177 });
178
179 if (npmLibDefResult !== 0) {
180 return npmLibDefResult;
181 } // Must be after `installNpmLibDefs` to ensure cache is updated first
182
183
184 if (ftConfig !== null && ftConfig !== void 0 && ftConfig.env || dependencyEnvs.length > 0) {
185 var _ftConfig$env;
186
187 const envLibDefResult = await installEnvLibDefs([...new Set([...((_ftConfig$env = ftConfig === null || ftConfig === void 0 ? void 0 : ftConfig.env) !== null && _ftConfig$env !== void 0 ? _ftConfig$env : []), ...dependencyEnvs])], flowVersion, cwd, libdefDir, useCacheUntil, Boolean(args.overwrite));
188
189 if (envLibDefResult !== 0) {
190 return envLibDefResult;
191 }
192 } // Once complete restart flow to solve flow issues when scanning large diffs
193
194
195 if (!args.skipFlowRestart) {
196 try {
197 await _node.child_process.execP('npx flow stop');
198 await _node.child_process.execP('npx flow');
199 } catch (e) {
200 console.log(_safe.default.red('!! Flow restarted with some errors'));
201 }
202 }
203
204 return 0;
205}
206
207async function installEnvLibDefs(env, flowVersion, flowProjectRoot, libdefDir, useCacheUntil, overwrite) {
208 if (env) {
209 console.log(_safe.default.green('• `env` key found in `flow-typed.config.json`, attempting to install env definitions...\n'));
210
211 if (!Array.isArray(env)) {
212 console.log(_safe.default.yellow('Warning: `env` in `flow-typed.config.json` must be of type Array<string> - skipping'));
213 return 0;
214 } // Get a list of all environment defs
215
216
217 const envDefs = await (0, _envDefs.getEnvDefs)();
218
219 const flowTypedDirPath = _node.path.join(flowProjectRoot, libdefDir, 'environments');
220
221 await (0, _fileUtils.mkdirp)(flowTypedDirPath); // Go through each env and try to install a libdef of the same name
222 // for the given flow version,
223 // if none is found throw a warning and continue. We shouldn't block the user.
224
225 await Promise.all(env.map(async en => {
226 if (typeof en === 'string') {
227 const def = await (0, _envDefs.findEnvDef)(en, flowVersion, useCacheUntil, envDefs);
228
229 if (def) {
230 const fileName = `${en}.js`;
231
232 const defLocalPath = _node.path.join(flowTypedDirPath, fileName);
233
234 const envAlreadyInstalled = await _node.fs.exists(defLocalPath);
235
236 if (envAlreadyInstalled) {
237 const localFile = _node.fs.readFileSync(defLocalPath, 'utf-8');
238
239 if (!(0, _codeSign.verifySignedCode)(localFile) && !overwrite) {
240 (0, _logger.listItem)(en, _safe.default.red(`${en} already exists and appears to have been manually written or changed!`), _safe.default.yellow(`Consider contributing your changes back to flow-typed repository :)`), _safe.default.yellow(`${en} already exists and appears to have been manually written or changed!`), _safe.default.yellow(`Read more at https://github.com/flow-typed/flow-typed/blob/main/CONTRIBUTING.md`), _safe.default.yellow(`Use --overwrite to overwrite the existing env defs.`));
241 return;
242 }
243
244 _node.fs.unlink(defLocalPath);
245 }
246
247 const repoVersion = await (0, _envDefs.getEnvDefVersionHash)((0, _cacheRepoUtils.getCacheRepoDir)(), def);
248 const codeSignPreprocessor = (0, _codeSign.signCodeStream)(repoVersion);
249 await (0, _fileUtils.copyFile)(def.path, defLocalPath, codeSignPreprocessor);
250 (0, _logger.listItem)(en, _safe.default.green(`.${_node.path.sep}${_node.path.relative(flowProjectRoot, defLocalPath)}`));
251 } else {
252 (0, _logger.listItem)(en, _safe.default.yellow(`Was unable to install ${en}. The env might not exist or there is not a version compatible with your version of flow`));
253 }
254 }
255 }));
256 }
257
258 return 0;
259}
260
261const FLOW_BUILT_IN_NPM_LIBS = ['react'];
262
263async function installNpmLibDefs({
264 cwd,
265 flowVersion,
266 explicitLibDefs,
267 libdefDir,
268 verbose,
269 overwrite,
270 skip,
271 skipCache,
272 ignoreDeps,
273 useCacheUntil,
274 ftConfig = {}
275}) {
276 const flowProjectRoot = await (0, _flowProjectUtils.findFlowRoot)(cwd);
277
278 if (flowProjectRoot === null) {
279 console.error('Error: Unable to find a flow project in the current dir or any of ' + "it's parent dirs!\n" + 'Please run this command from within a Flow project.');
280 return {
281 status: 1,
282 dependencyEnvs: []
283 };
284 }
285
286 const libdefsToSearchFor = new Map();
287 let ignoreDefs;
288
289 if (Array.isArray(ftConfig.ignore)) {
290 ignoreDefs = ftConfig.ignore;
291 } else {
292 try {
293 ignoreDefs = _node.fs.readFileSync(_node.path.join(cwd, libdefDir, '.ignore'), 'utf-8').replace(/"/g, '').split('\n');
294 } catch (err) {
295 // If the error is unrelated to file not existing we should continue throwing
296 if (err.code !== 'ENOENT') {
297 throw err;
298 }
299
300 ignoreDefs = [];
301 }
302 }
303
304 let workspacesPkgJsonData; // If a specific pkg/version was specified, only add those packages.
305 // Otherwise, extract dependencies from the package.json
306
307 if (explicitLibDefs.length > 0) {
308 for (var i = 0; i < explicitLibDefs.length; i++) {
309 const term = explicitLibDefs[i];
310 const termMatches = term.match(/(@[^@\/]+\/)?([^@]+)@(.+)/);
311
312 if (termMatches == null) {
313 const pkgJsonData = await (0, _npmProjectUtils.getPackageJsonData)(cwd);
314 workspacesPkgJsonData = await (0, _npmProjectUtils.findWorkspacesPackages)(cwd, pkgJsonData, ftConfig);
315 const pkgJsonDeps = workspacesPkgJsonData.reduce((acc, pckData) => {
316 return (0, _npmProjectUtils.mergePackageJsonDependencies)(acc, (0, _npmProjectUtils.getPackageJsonDependencies)(pckData, [], []));
317 }, (0, _npmProjectUtils.getPackageJsonDependencies)(pkgJsonData, [], []));
318 const packageVersion = pkgJsonDeps[term];
319
320 if (packageVersion) {
321 libdefsToSearchFor.set(term, packageVersion);
322 } else {
323 console.error('ERROR: Package not found from package.json.\n' + 'Please specify version for the package in the format of `foo@1.2.3`');
324 return {
325 status: 1,
326 dependencyEnvs: []
327 };
328 }
329 } else {
330 const [_, npmScope, pkgName, pkgVerStr] = termMatches;
331 const scopedPkgName = npmScope != null ? npmScope + pkgName : pkgName;
332 libdefsToSearchFor.set(scopedPkgName, pkgVerStr);
333 }
334 }
335
336 console.log(`• Searching for ${libdefsToSearchFor.size} libdefs...`);
337 } else {
338 const pkgJsonData = await (0, _npmProjectUtils.getPackageJsonData)(cwd);
339 workspacesPkgJsonData = await (0, _npmProjectUtils.findWorkspacesPackages)(cwd, pkgJsonData, ftConfig);
340 const pkgJsonDeps = workspacesPkgJsonData.reduce((acc, pckData) => {
341 return (0, _npmProjectUtils.mergePackageJsonDependencies)(acc, (0, _npmProjectUtils.getPackageJsonDependencies)(pckData, ignoreDeps, ignoreDefs));
342 }, (0, _npmProjectUtils.getPackageJsonDependencies)(pkgJsonData, ignoreDeps, ignoreDefs));
343
344 for (const pkgName in pkgJsonDeps) {
345 libdefsToSearchFor.set(pkgName, pkgJsonDeps[pkgName]);
346 }
347
348 if (libdefsToSearchFor.size === 0) {
349 console.error("No dependencies were found in this project's package.json!");
350 return {
351 status: 0,
352 dependencyEnvs: []
353 };
354 }
355
356 if (verbose) {
357 libdefsToSearchFor.forEach((ver, name) => {
358 console.log(`• Found package.json dependency: ${name}@${ver}`);
359 });
360 } else {
361 console.log(`• Found ${libdefsToSearchFor.size} dependencies in package.json to install libdefs for. Searching...`);
362 }
363 }
364
365 const libDefsToSearchForEntries = [...libdefsToSearchFor.entries()]; // Search for the requested libdefs
366
367 const libDefsToInstall = new Map();
368 const outdatedLibDefsToInstall = [];
369 const unavailableLibDefs = [];
370 const defDepsToInstall = {}; // This updates the cache for all definition types, npm/env/etc
371
372 const libDefs = await (0, _npmLibDefs.getCacheNpmLibDefs)(useCacheUntil, skipCache);
373
374 const getLibDefsToInstall = async entries => {
375 await Promise.all(entries.map(async ([name, ver]) => {
376 delete defDepsToInstall[name]; // To comment in json files a work around is to give a key value pair
377 // of `"//": "comment"` we should exclude these so the install doesn't crash
378 // Ref: https://stackoverflow.com/a/14221781/430128
379
380 if (name === '//') {
381 return;
382 }
383
384 if (FLOW_BUILT_IN_NPM_LIBS.indexOf(name) !== -1) {
385 return;
386 }
387
388 const libDef = await (0, _npmLibDefs.findNpmLibDef)(name, ver, flowVersion, useCacheUntil, true, libDefs);
389
390 if (libDef === null) {
391 unavailableLibDefs.push({
392 name,
393 ver
394 });
395 } else {
396 libDefsToInstall.set(name, libDef);
397 const libDefLower = (0, _semver2.getRangeLowerBound)(libDef.version);
398 const depLower = (0, _semver2.getRangeLowerBound)(ver);
399
400 if (_semver.default.lt(libDefLower, depLower)) {
401 outdatedLibDefsToInstall.push([libDef, {
402 name,
403 ver
404 }]);
405 } // If this libdef has dependencies let's first add it to a giant list
406
407
408 if (libDef.depVersions) {
409 Object.keys(libDef.depVersions).forEach(dep => {
410 if (libDef.depVersions) {
411 // This may result in overriding other libDef dependencies
412 // but we don't care because either way a project cannot have the
413 // same module declared twice.
414 defDepsToInstall[dep] = libDef.depVersions[dep];
415 }
416 });
417 }
418 }
419 }));
420 };
421
422 await getLibDefsToInstall(libDefsToSearchForEntries);
423 const pnpResolver = await (0, _npmProjectUtils.loadPnpResolver)(await (0, _npmProjectUtils.getPackageJsonData)(cwd));
424 const dependencyEnvs = []; // If a package that's missing a flow-typed libdef has any .flow files,
425 // we'll skip generating a stub for it.
426
427 const untypedMissingLibDefs = [];
428 const typedMissingLibDefs = [];
429 await Promise.all(unavailableLibDefs.map(async ({
430 name: pkgName,
431 ver: pkgVer
432 }) => {
433 const {
434 isFlowTyped,
435 pkgPath
436 } = await (0, _stubUtils.pkgHasFlowFiles)(cwd, pkgName, pnpResolver, workspacesPkgJsonData);
437
438 if (isFlowTyped && pkgPath) {
439 typedMissingLibDefs.push([pkgName, pkgVer, pkgPath]);
440
441 try {
442 // If the flow typed dependency has a flow-typed config
443 // check if they have env's defined and if so keep them in
444 // a list so we can later install them along with project
445 // defined envs.
446 const pkgFlowTypedConfig = await _node.fs.readJson(_node.path.join(pkgPath, 'flow-typed.config.json'));
447
448 if (pkgFlowTypedConfig.env) {
449 dependencyEnvs.push(...pkgFlowTypedConfig.env);
450 }
451 } catch (e) {// Ignore if we cannot read flow-typed config
452 }
453 } else {
454 untypedMissingLibDefs.push([pkgName, pkgVer]);
455 }
456 })); // If there are any typed packages we should try install any missing
457 // lib defs for that package.
458 // Scanning through all typed dependencies then checking their immediate deps
459 // but do not overwrite the lib def that the project itself wants
460
461 if (typedMissingLibDefs.length > 0) {
462 const typedDepsLibDefsToSearchFor = [];
463 await Promise.all(typedMissingLibDefs.map(async typedLibDef => {
464 const pkgJsonData = await (0, _npmProjectUtils.getPackageJsonData)(`${typedLibDef[2]}/package.json`);
465 const pkgJsonDeps = (0, _npmProjectUtils.getPackageJsonDependencies)(pkgJsonData, // Only get their production dependencies
466 // as the rest aren't installed anyways
467 ['dev', 'peer', ...ignoreDeps], ignoreDefs);
468
469 for (const pkgName in pkgJsonDeps) {
470 if (!libDefsToInstall.has(pkgName)) {
471 typedDepsLibDefsToSearchFor.push([pkgName, pkgJsonDeps[pkgName]]);
472 }
473 }
474 }));
475 await getLibDefsToInstall(typedDepsLibDefsToSearchFor);
476 } // Now that we've captured all package.json libdefs and typed package libdefs
477 // We can compare libDefsToInstall with defDepsToInstall and override any that
478 // are already needed but don't match the supported dependency versions.
479
480
481 if (Object.keys(defDepsToInstall).length > 0) {
482 (0, _logger.sectionHeader)('Running definition dependency check');
483
484 while (Object.keys(defDepsToInstall).length > 0) {
485 await getLibDefsToInstall(Object.keys(defDepsToInstall).map(dep => {
486 const libDef = libDefsToInstall.get(dep);
487 const defVersions = defDepsToInstall[dep];
488
489 if (libDef) {
490 if (!defVersions.includes(libDef.version)) {
491 // If no supported version warn it'll be overridden and continue
492 (0, _logger.listItem)(_safe.default.yellow(`One of your definitions has a dependency to ${dep} @ version(s) ${defVersions.join(', ')}`), `You have version ${_safe.default.yellow(libDef.version)} installed`, `We're overriding to a supported version to fix flow-typed ${_safe.default.red('but you may experience other type errors')}`);
493 } else {
494 // If a supported version already installed return dummy tuple
495 // to get filtered out
496 delete defDepsToInstall[dep];
497 return ['', ''];
498 }
499 } // This only hits if no supported version installed,
500 // we will find the last version in dependency to install
501
502
503 return [dep, defVersions[defVersions.length - 1]];
504 }).filter(o => !!o[0]));
505 }
506
507 (0, _logger.sectionHeader)('Check complete');
508 } // Scan libdefs that are already installed
509
510
511 const libDefsToUninstall = new Map();
512 const alreadyInstalledLibDefs = await (0, _npmLibDefs.getInstalledNpmLibDefs)(_node.path.join(flowProjectRoot), libdefDir);
513 [...alreadyInstalledLibDefs.entries()].forEach(([filePath, npmLibDef]) => {
514 const fullFilePath = _node.path.join(flowProjectRoot, filePath);
515
516 switch (npmLibDef.kind) {
517 case 'LibDef':
518 // If a libdef is already installed for some dependency, we need to
519 // uninstall it before installing the new (potentially updated) ver
520 const libDef = npmLibDef.libDef;
521 const scopedPkgName = (0, _npmLibDefs.getScopedPackageName)(libDef);
522
523 if (libDefsToInstall.has(scopedPkgName)) {
524 libDefsToUninstall.set(scopedPkgName, fullFilePath);
525 }
526
527 break;
528
529 case 'Stub':
530 break;
531
532 default:
533 npmLibDef;
534 }
535 });
536
537 if (libDefsToInstall.size > 0) {
538 (0, _logger.sectionHeader)(`Installing ${libDefsToInstall.size} libDefs...`);
539
540 const flowTypedDirPath = _node.path.join(flowProjectRoot, libdefDir, 'npm');
541
542 await (0, _fileUtils.mkdirp)(flowTypedDirPath);
543 const results = await Promise.all([...libDefsToInstall.values()].map(async libDef => {
544 const toUninstall = libDefsToUninstall.get((0, _npmLibDefs.getScopedPackageName)(libDef));
545
546 if (toUninstall != null) {
547 await _node.fs.unlink(toUninstall);
548 }
549
550 return installNpmLibDef(libDef, flowTypedDirPath, overwrite);
551 }));
552
553 if (results.some(res => !res)) {
554 return {
555 status: 1,
556 dependencyEnvs: []
557 };
558 }
559 }
560
561 if ((verbose || unavailableLibDefs.length === 0) && outdatedLibDefsToInstall.length > 0) {
562 console.log('• The following installed libdefs are compatible with your ' + 'dependencies, but may not include all minor and patch changes for ' + 'your specific dependency version:\n');
563 outdatedLibDefsToInstall.forEach(([libDef, {
564 name: pkgName,
565 ver: pkgVersion
566 }]) => {
567 console.log(' • libdef: %s (satisfies %s)', _safe.default.yellow(`${libDef.name}_${libDef.version}`), _safe.default.bold(`${pkgName}@${pkgVersion}`));
568 const libDefPlural = outdatedLibDefsToInstall.length > 1 ? ['versioned updates', 'these packages'] : ['a versioned update', 'this package'];
569 console.log(`\n` + ` Consider submitting ${libDefPlural[0]} for ${libDefPlural[1]} to \n` + ` https://github.com/flowtype/flow-typed/\n`);
570 });
571 }
572
573 if (unavailableLibDefs.length > 0 && unavailableLibDefs.length === explicitLibDefs.length) {
574 // If the user specified an explicit library to be installed, don't generate
575 // a stub if no libdef exists -- just inform them that one doesn't exist
576 console.log(_safe.default.red(`!! No flow@${(0, _flowVersion.toSemverString)(flowVersion)}-compatible libdefs ` + `found in flow-typed for the explicitly requested libdefs. !!`) + '\n' + '\n' + 'Consider using `%s` to generate an empty libdef that you can fill in.', _safe.default.bold(`flow-typed create-stub ${explicitLibDefs.join(' ')}`));
577 return {
578 status: 1,
579 dependencyEnvs: []
580 };
581 } else {
582 if (untypedMissingLibDefs.length > 0 && !skip) {
583 console.log('• Generating stubs for untyped dependencies...');
584 await Promise.all(untypedMissingLibDefs.map(async ([pkgName, pkgVerStr]) => {
585 await (0, _stubUtils.createStub)(flowProjectRoot, pkgName, pkgVerStr, overwrite, pnpResolver,
586 /* typescript */
587 false, libdefDir);
588 }));
589 console.log(_safe.default.red(`\n!! No flow@${(0, _flowVersion.toSemverString)(flowVersion)}-compatible libdefs ` + `found in flow-typed for the above untyped dependencies !!`));
590 const plural = unavailableLibDefs.length > 1 ? ['libdefs', 'these packages', 'them'] : ['a libdef', 'this package', 'it'];
591 console.log(`\n` + `We've generated ${'`'}any${'`'}-typed stubs for ${plural[1]}, but ` + `consider submitting \n` + `${plural[0]} for ${plural[2]} to ` + `${_safe.default.bold('https://github.com/flowtype/flow-typed/')}\n`);
592 }
593 }
594
595 return {
596 status: 0,
597 dependencyEnvs
598 };
599}
600
601async function installNpmLibDef(npmLibDef, npmDir, overwrite) {
602 const scopedDir = npmLibDef.scope === null ? npmDir : _node.path.join(npmDir, npmLibDef.scope);
603 (0, _fileUtils.mkdirp)(scopedDir);
604 const fileName = `${npmLibDef.name}_${npmLibDef.version}.js`;
605
606 const filePath = _node.path.join(scopedDir, fileName); // Find the libDef in the cached repo
607
608
609 try {
610 const terseFilePath = _node.path.relative(_node.path.resolve(npmDir, '..', '..'), filePath);
611
612 if (!overwrite && (await _node.fs.exists(filePath))) {
613 (0, _logger.listItem)(_safe.default.bold(_safe.default.red(`${terseFilePath} already exists and appears to have been manually ` + `written or changed!`)), _safe.default.green(`Consider contributing your changes back to flow-typed repository :)`), `Read more at https://github.com/flow-typed/flow-typed/blob/main/CONTRIBUTING.md`, 'Use --overwrite to overwrite the existing libdef.');
614 return true;
615 }
616
617 const repoVersion = await (0, _npmLibDefs.getNpmLibDefVersionHash)((0, _cacheRepoUtils.getCacheRepoDir)(), npmLibDef);
618 const codeSignPreprocessor = (0, _codeSign.signCodeStream)(repoVersion);
619 await (0, _fileUtils.copyFile)(npmLibDef.path, filePath, codeSignPreprocessor);
620 (0, _logger.listItem)(fileName, _safe.default.green(`.${_node.path.sep}${terseFilePath}`)); // Remove any lingering stubs
621
622 console.log(npmLibDef.name);
623 console.log(scopedDir);
624 const stubName = `${npmLibDef.name}_vx.x.x.js`;
625
626 const stubPath = _node.path.join(scopedDir, stubName);
627
628 if (overwrite && (await _node.fs.exists(stubPath))) {
629 await _node.fs.unlink(stubPath);
630 }
631
632 return true;
633 } catch (e) {
634 console.error(` !! Failed to install ${npmLibDef.name} at ${filePath}`);
635 console.error(` ERROR: ${e.message}`);
636 return false;
637 }
638}
\No newline at end of file