1 | "use strict";
|
2 |
|
3 | const fs = require("fs");
|
4 | const path = require("path");
|
5 |
|
6 | const chalk = require("chalk");
|
7 | const minimist = require("minimist");
|
8 | const semver = require('semver');
|
9 |
|
10 | const check = require(".");
|
11 | const tools = require("./tools");
|
12 |
|
13 |
|
14 | const argv = minimist(process.argv.slice(2), {
|
15 | alias: {
|
16 | "print": "p",
|
17 | "help": "h",
|
18 | },
|
19 | boolean: [
|
20 | "print",
|
21 | "help",
|
22 | ],
|
23 | string: [
|
24 | "node",
|
25 | "npm",
|
26 | "npx",
|
27 | "yarn",
|
28 | ]
|
29 | });
|
30 |
|
31 | if (argv.help) {
|
32 | const usage = fs.readFileSync(path.join(__dirname, "usage.txt"), {
|
33 | encoding: "utf8",
|
34 | });
|
35 |
|
36 | process.stdout.write(usage);
|
37 | process.exit(0);
|
38 | }
|
39 |
|
40 |
|
41 | const options = argv.package ? optionsFromPackage() : optionsFromCommandLine();
|
42 |
|
43 | check(options, (err, result) => {
|
44 | if (err) {
|
45 | throw err;
|
46 | }
|
47 |
|
48 | printVersions(result, argv.print);
|
49 | process.exit(result.isSatisfied ? 0 : 1);
|
50 | });
|
51 |
|
52 |
|
53 |
|
54 |
|
55 |
|
56 | function optionsFromCommandLine() {
|
57 | return Object.keys(tools).reduce((memo, name) => ({
|
58 | ...memo,
|
59 | [name]: argv[name],
|
60 | }), {});
|
61 | }
|
62 |
|
63 | function optionsFromPackage() {
|
64 | let packageJson;
|
65 |
|
66 | try {
|
67 | packageJson = require(path.join(process.cwd(), 'package.json'));
|
68 | } catch (e) {
|
69 | console.log('Error: When running with --package, a package.json file is expected in the current working directory');
|
70 | console.log('Current working directory is: ' + process.cwd());
|
71 |
|
72 | process.exit(1);
|
73 | }
|
74 |
|
75 | if (!packageJson.engines) {
|
76 | console.log('Error: When running with --package, your package.json is expected to contain the "engines" key');
|
77 | console.log('See https://docs.npmjs.com/files/package.json#engines for the supported syntax');
|
78 |
|
79 | process.exit(1);
|
80 | }
|
81 |
|
82 | return Object.keys(tools).reduce((memo, name) => ({
|
83 | ...memo,
|
84 | [name]: packageJson.engines[name],
|
85 | }), {});
|
86 | }
|
87 |
|
88 |
|
89 |
|
90 |
|
91 |
|
92 | function printVersions(result, print) {
|
93 | Object.keys(result.versions).forEach(name => {
|
94 | const info = result.versions[name];
|
95 | const isSatisfied = info.isSatisfied;
|
96 |
|
97 |
|
98 | if (print || !isSatisfied) {
|
99 | printInstalledVersion(name, info);
|
100 | }
|
101 |
|
102 | if (isSatisfied) return;
|
103 |
|
104 |
|
105 | const { raw, range } = info.wanted;
|
106 |
|
107 | console.error(chalk.red(`Wanted ${name} version ` + chalk.bold(`${raw} (${range})`)));
|
108 |
|
109 | console.log(chalk.yellow.bold(
|
110 | tools[name]
|
111 | .getInstallInstructions(
|
112 | semver.minVersion(info.wanted)
|
113 | )
|
114 | ));
|
115 | });
|
116 | }
|
117 |
|
118 | function printInstalledVersion(name, info) {
|
119 | if (info.version) {
|
120 | const versionNote = name + ": " + chalk.bold(info.version);
|
121 | if (info.isSatisfied) {
|
122 | console.log(versionNote);
|
123 | } else {
|
124 | console.log(chalk.red(versionNote));
|
125 | }
|
126 | }
|
127 |
|
128 | if (info.notfound) {
|
129 | if (info.isSatisfied) {
|
130 | console.log(chalk.gray(name + ': not installed'));
|
131 | } else {
|
132 | console.error(chalk.red(name + ': not installed'));
|
133 | }
|
134 | }
|
135 | }
|