1 | 'use strict';
|
2 |
|
3 | const chalk = require('chalk');
|
4 | const _ = require('lodash');
|
5 | const table = require('text-table');
|
6 | const emoji = require('./emoji');
|
7 | const stripAnsi = require('strip-ansi');
|
8 |
|
9 | function uppercaseFirstLetter(str) {
|
10 | return str[0].toUpperCase() + str.substr(1);
|
11 | }
|
12 |
|
13 | function render(pkg, currentState) {
|
14 | const packageName = pkg.moduleName;
|
15 | const rows = [];
|
16 |
|
17 | const indent = ' ' + emoji(' ');
|
18 |
|
19 | const installer = currentState.get('installer');
|
20 | const isYarn = installer === 'yarn';
|
21 |
|
22 | const args = [isYarn ? 'add' : 'install'];
|
23 | if (currentState.get('global')) {
|
24 | isYarn ? args.unshift('global') : args.push('--global');
|
25 | }
|
26 |
|
27 | const flags = [];
|
28 | if (isYarn) {
|
29 | pkg.devDependency && flags.push('--dev');
|
30 | } else {
|
31 | pkg.devDependency ? flags.push('--save-dev') : flags.push('--save');
|
32 | }
|
33 |
|
34 | const upgradeCommand = `${installer} ${args.join(' ')} ${packageName}@${pkg.latest} ${flags.join(' ')}`;
|
35 | const upgradeMessage = `${chalk.green(upgradeCommand)} to go from ${pkg.installed} to ${pkg.latest}`;
|
36 |
|
37 | const status = _([
|
38 | pkg.notInstalled ? chalk.bgRed.white.bold(emoji(' :worried: ') + ' MISSING! ') + ' Not installed.' : '',
|
39 | pkg.notInPackageJson ? chalk.bgRed.white.bold(emoji(' :worried: ') + ' PKG ERR! ') + ' Not in the package.json. ' + pkg.notInPackageJson : '',
|
40 | pkg.pkgError && !pkg.notInstalled ? chalk.bgGreen.white.bold(emoji(' :worried: ') + ' PKG ERR! ') + ' ' + chalk.red(pkg.pkgError.message) : '',
|
41 | pkg.bump && pkg.easyUpgrade ? [
|
42 | chalk.bgGreen.white.bold(emoji(' :heart_eyes: ') + ' UPDATE! ') + ' Your local install is out of date. ' + chalk.blue.underline(pkg.homepage || ''),
|
43 | indent + upgradeMessage
|
44 | ] : '',
|
45 | pkg.bump && !pkg.easyUpgrade ? [
|
46 | chalk.white.bold.bgGreen((pkg.bump === 'nonSemver' ? emoji(' :sunglasses: ') + ' new ver! '.toUpperCase() : emoji(' :sunglasses: ') + ' ' + pkg.bump.toUpperCase() + ' UP ')) + ' ' + uppercaseFirstLetter(pkg.bump) + ' update available. ' + chalk.blue.underline(pkg.homepage || ''),
|
47 | indent + upgradeMessage
|
48 | ] : '',
|
49 | pkg.unused ? [
|
50 | chalk.black.bold.bgWhite(emoji(' :confused: ') + ' NOTUSED? ') + ` ${chalk.yellow(`Still using ${packageName}?`)}`,
|
51 | indent + `Depcheck did not find code similar to ${chalk.green(`require('${packageName}')`)} or ${chalk.green(`import from '${packageName}'`)}.`,
|
52 | indent + `Check your code before removing as depcheck isn't able to foresee all ways dependencies can be used.`,
|
53 | indent + `Use rc file options to remove unused check, but still monitor for outdated version:`,
|
54 | indent + ` .npmcheckrc {"depcheck": {"ignoreMatches": ["${packageName}"]}}`,
|
55 | indent + `Use ${chalk.green('--skip-unused')} to skip this check.`,
|
56 | indent + `To remove this package: ${chalk.green(
|
57 | isYarn
|
58 | ? `yarn remove ${packageName} ${pkg.devDependency ? '--dev' : ''}`
|
59 | : `npm uninstall ${packageName} --save${pkg.devDependency ? '-dev' : ''}`
|
60 | )}`
|
61 | ] : '',
|
62 | pkg.mismatch && !pkg.bump ? chalk.bgRed.yellow.bold(emoji(' :interrobang: ') + ' MISMATCH ') + ' Installed version does not match package.json. ' + pkg.installed + ' ≠ ' + pkg.packageJson : '',
|
63 | pkg.regError ? chalk.bgRed.white.bold(emoji(' :no_entry: ') + ' NPM ERR! ') + ' ' + chalk.red(pkg.regError) : ''
|
64 | ])
|
65 | .flatten()
|
66 | .compact()
|
67 | .valueOf();
|
68 |
|
69 | if (!status.length) {
|
70 | return false;
|
71 | }
|
72 |
|
73 | rows.push(
|
74 | [
|
75 | chalk.yellow(packageName),
|
76 | status.shift()
|
77 | ]);
|
78 |
|
79 | while (status.length) {
|
80 | rows.push([
|
81 | ' ',
|
82 | status.shift()
|
83 | ]);
|
84 | }
|
85 |
|
86 | rows.push(
|
87 | [
|
88 | ' '
|
89 | ]);
|
90 |
|
91 | return rows;
|
92 | }
|
93 |
|
94 | function outputConsole(currentState) {
|
95 | const packages = currentState.get('packages');
|
96 |
|
97 | const rows = packages.reduce((acc, pkg) => {
|
98 | return acc.concat(render(pkg, currentState));
|
99 | }, [])
|
100 | .filter(Boolean);
|
101 |
|
102 | if (rows.length) {
|
103 | const renderedTable = table(rows, {
|
104 | stringLength: s => stripAnsi(s).length
|
105 | });
|
106 |
|
107 | console.log('');
|
108 | console.log(renderedTable);
|
109 | console.log(`Use ${chalk.green(`npm-check -${currentState.get('global') ? 'g' : ''}u`)} for interactive update.`);
|
110 | process.exitCode = 1;
|
111 | } else {
|
112 | console.log(`${emoji(':heart: ')}Your modules look ${chalk.bold('amazing')}. Keep up the great work.${emoji(' :heart:')}`);
|
113 | process.exitCode = 0;
|
114 | }
|
115 | }
|
116 |
|
117 | module.exports = outputConsole;
|