Skip to content

Commit 92bcb81

Browse files
committed
wording, optimizations, types, cleanup
1 parent 5230740 commit 92bcb81

File tree

1 file changed

+85
-45
lines changed

1 file changed

+85
-45
lines changed

bin/webpack.js

Lines changed: 85 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,16 @@
11
#!/usr/bin/env node
2-
function runCommand(command, options) {
2+
3+
process.exitCode = 0;
4+
5+
/**
6+
* @param {string} command process to run
7+
* @param {string[]} args commandline arguments
8+
* @returns {Promise<void>} promise
9+
*/
10+
const runCommand = (command, args) => {
311
const cp = require("child_process");
412
return new Promise((resolve, reject) => {
5-
const executedCommand = cp.spawn(command, options, {
13+
const executedCommand = cp.spawn(command, args, {
614
stdio: "inherit",
715
shell: true
816
});
@@ -13,114 +21,146 @@ function runCommand(command, options) {
1321

1422
executedCommand.on("exit", code => {
1523
if (code === 0) {
16-
resolve(true);
24+
resolve();
1725
} else {
1826
reject();
1927
}
2028
});
2129
});
22-
}
30+
};
2331

24-
function isInstalled(packageName) {
32+
/**
33+
* @param {string} packageName name of the package
34+
* @returns {boolean} is the package installed?
35+
*/
36+
const isInstalled = packageName => {
2537
try {
2638
require.resolve(packageName);
2739

2840
return true;
2941
} catch (err) {
3042
return false;
3143
}
32-
}
33-
34-
const CLI = [
44+
};
45+
46+
/**
47+
* @typedef {Object} CliOption
48+
* @property {string} name display name
49+
* @property {string} package npm package name
50+
* @property {string} alias shortcut for choice
51+
* @property {boolean} installed currently installed?
52+
* @property {string} url homepage
53+
* @property {string} description description
54+
*/
55+
56+
/** @type {CliOption[]} */
57+
const CLIs = [
3558
{
3659
name: "webpack-cli",
60+
package: "webpack-cli",
61+
alias: "cli",
3762
installed: isInstalled("webpack-cli"),
38-
URL: "https://github.com/webpack/webpack-cli",
39-
description: "The original webpack full-featured CLI from webpack@3."
63+
url: "https://github.com/webpack/webpack-cli",
64+
description: "The original webpack full-featured CLI."
4065
},
4166
{
4267
name: "webpack-command",
68+
package: "webpack-command",
69+
alias: "command",
4370
installed: isInstalled("webpack-command"),
44-
URL: "https://github.com/webpack-contrib/webpack-command",
71+
url: "https://github.com/webpack-contrib/webpack-command",
4572
description: "A lightweight, opinionated webpack CLI."
4673
}
4774
];
4875

49-
if (CLI.every(item => !item.installed)) {
76+
const installedClis = CLIs.filter(cli => cli.installed);
77+
78+
if (installedClis.length === 0) {
5079
const path = require("path");
5180
const fs = require("fs");
5281
const readLine = require("readline");
5382

5483
let notify =
55-
"The CLI for webpack must be installed as a separate package, for which there are choices:\n";
84+
"One CLI for webpack must be installed. These are recommended choices, delivered as separate packages:";
5685

57-
CLI.forEach(item => {
58-
notify += ` ${item.name} (${item.URL}): ${item.description}\n`;
59-
});
86+
for (const item of CLIs) {
87+
notify += `\n - ${item.name} (${item.url})\n ${item.description}`;
88+
}
6089

6190
console.error(notify);
6291

6392
const isYarn = fs.existsSync(path.resolve(process.cwd(), "yarn.lock"));
6493

6594
const packageManager = isYarn ? "yarn" : "npm";
66-
const installOptions = ["install", "-D"];
95+
const installOptions = [isYarn ? "add" : "install", "-D"];
6796

68-
if (isYarn) {
69-
installOptions[0] = "add";
70-
}
97+
console.error(
98+
`We will use "${packageManager}" to install the CLI via "${packageManager} ${installOptions.join(
99+
" "
100+
)}".`
101+
);
71102

72-
let question = `Would you like to install (${CLI.map(item => item.name).join(
73-
"/"
74-
)}):\n`;
103+
let question = `Which one do you like to install (${CLIs.map(
104+
item => item.name
105+
).join("/")}):\n`;
75106

76107
const questionInterface = readLine.createInterface({
77108
input: process.stdin,
78-
output: process.stdout
109+
output: process.stderr
79110
});
80111
questionInterface.question(question, answer => {
81112
questionInterface.close();
82113

83114
const normalizedAnswer = answer.toLowerCase();
84-
const selectedPackage = CLI.find(item => item.name === normalizedAnswer);
115+
const selectedPackage = CLIs.find(item => {
116+
return item.name === normalizedAnswer || item.alias === normalizedAnswer;
117+
});
85118

86-
if (!selectedPackage) {
119+
if (!normalizedAnswer) {
87120
console.error(
88-
"It needs to be installed alongside webpack to use the CLI"
121+
"One CLI needs to be installed alongside webpack to use the CLI."
122+
);
123+
process.exitCode = 1;
124+
125+
return;
126+
} else if (!selectedPackage) {
127+
console.error(
128+
"No matching choice.\n" +
129+
"One CLI needs to be installed alongside webpack to use the CLI.\n" +
130+
"Try to installing your CLI of choice manually."
89131
);
90132
process.exitCode = 1;
91133

92134
return;
93135
}
94136

95-
installOptions.push(normalizedAnswer);
137+
const packageName = selectedPackage.package;
96138

97139
console.log(
98-
`Installing '${normalizedAnswer}' (running '${packageManager} ${installOptions.join(
140+
`Installing '${
141+
selectedPackage.name
142+
}' (running '${packageManager} ${installOptions.join(
99143
" "
100-
)}')...`
144+
)} ${packageName}')...`
101145
);
102146

103-
runCommand(packageManager, installOptions)
104-
.then(result => {
105-
return require(normalizedAnswer); //eslint-disable-line
147+
runCommand(packageManager, installOptions.concat(packageName))
148+
.then(() => {
149+
require(packageName); //eslint-disable-line
106150
})
107151
.catch(error => {
108152
console.error(error);
109153
process.exitCode = 1;
110154
});
111155
});
156+
} else if (installedClis.length === 1) {
157+
require(installedClis[0].package); // eslint-disable-line
112158
} else {
113-
const installedPackage = CLI.map(
114-
item => (item.installed ? item.name : "")
115-
).filter(v => v);
116-
117-
if (installedPackage.length > 1) {
118-
console.warn(
119-
`You have installed ${installedPackage.join(
159+
console.warn(
160+
`You have installed ${installedClis
161+
.map(item => item.name)
162+
.join(
120163
" and "
121-
)} together. To work with the webpack you need only one CLI package, please remove one of them`
122-
);
123-
}
124-
125-
require(installedPackage[0]); // eslint-disable-line
164+
)} together. To work with the "webpack" command you need only one CLI package, please remove one of them or use them directly via their binary.`
165+
);
126166
}

0 commit comments

Comments
 (0)