mirror of https://github.com/webpack/webpack.git
				
				
				
			
		
			
				
	
	
		
			173 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			JavaScript
		
	
	
		
			Executable File
		
	
	
			
		
		
	
	
			173 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			JavaScript
		
	
	
		
			Executable File
		
	
	
| #!/usr/bin/env node
 | |
| 
 | |
| process.exitCode = 0;
 | |
| 
 | |
| /**
 | |
|  * @param {string} command process to run
 | |
|  * @param {string[]} args commandline arguments
 | |
|  * @returns {Promise<void>} promise
 | |
|  */
 | |
| const runCommand = (command, args) => {
 | |
| 	const cp = require("child_process");
 | |
| 	return new Promise((resolve, reject) => {
 | |
| 		const executedCommand = cp.spawn(command, args, {
 | |
| 			stdio: "inherit",
 | |
| 			shell: true
 | |
| 		});
 | |
| 
 | |
| 		executedCommand.on("error", error => {
 | |
| 			reject(error);
 | |
| 		});
 | |
| 
 | |
| 		executedCommand.on("exit", code => {
 | |
| 			if (code === 0) {
 | |
| 				resolve();
 | |
| 			} else {
 | |
| 				reject();
 | |
| 			}
 | |
| 		});
 | |
| 	});
 | |
| };
 | |
| 
 | |
| /**
 | |
|  * @param {string} packageName name of the package
 | |
|  * @returns {boolean} is the package installed?
 | |
|  */
 | |
| const isInstalled = packageName => {
 | |
| 	try {
 | |
| 		require.resolve(packageName);
 | |
| 
 | |
| 		return true;
 | |
| 	} catch (err) {
 | |
| 		return false;
 | |
| 	}
 | |
| };
 | |
| 
 | |
| /**
 | |
|  * @typedef {Object} CliOption
 | |
|  * @property {string} name display name
 | |
|  * @property {string} package npm package name
 | |
|  * @property {string} binName name of the executable file
 | |
|  * @property {string} alias shortcut for choice
 | |
|  * @property {boolean} installed currently installed?
 | |
|  * @property {string} url homepage
 | |
|  * @property {string} description description
 | |
|  */
 | |
| 
 | |
| /** @type {CliOption[]} */
 | |
| const CLIs = [
 | |
| 	{
 | |
| 		name: "webpack-cli",
 | |
| 		package: "webpack-cli",
 | |
| 		binName: "webpack-cli",
 | |
| 		alias: "cli",
 | |
| 		installed: isInstalled("webpack-cli"),
 | |
| 		url: "https://github.com/webpack/webpack-cli",
 | |
| 		description: "The original webpack full-featured CLI."
 | |
| 	},
 | |
| 	{
 | |
| 		name: "webpack-command",
 | |
| 		package: "webpack-command",
 | |
| 		binName: "webpack-command",
 | |
| 		alias: "command",
 | |
| 		installed: isInstalled("webpack-command"),
 | |
| 		url: "https://github.com/webpack-contrib/webpack-command",
 | |
| 		description: "A lightweight, opinionated webpack CLI."
 | |
| 	}
 | |
| ];
 | |
| 
 | |
| const installedClis = CLIs.filter(cli => cli.installed);
 | |
| 
 | |
| if (installedClis.length === 0) {
 | |
| 	const path = require("path");
 | |
| 	const fs = require("fs");
 | |
| 	const readLine = require("readline");
 | |
| 
 | |
| 	let notify =
 | |
| 		"One CLI for webpack must be installed. These are recommended choices, delivered as separate packages:";
 | |
| 
 | |
| 	for (const item of CLIs) {
 | |
| 		notify += `\n - ${item.name} (${item.url})\n   ${item.description}`;
 | |
| 	}
 | |
| 
 | |
| 	console.error(notify);
 | |
| 
 | |
| 	const isYarn = fs.existsSync(path.resolve(process.cwd(), "yarn.lock"));
 | |
| 
 | |
| 	const packageManager = isYarn ? "yarn" : "npm";
 | |
| 	const installOptions = [isYarn ? "add" : "install", "-D"];
 | |
| 
 | |
| 	console.error(
 | |
| 		`We will use "${packageManager}" to install the CLI via "${packageManager} ${installOptions.join(
 | |
| 			" "
 | |
| 		)}".`
 | |
| 	);
 | |
| 
 | |
| 	let question = `Which one do you like to install (${CLIs.map(
 | |
| 		item => item.name
 | |
| 	).join("/")}):\n`;
 | |
| 
 | |
| 	const questionInterface = readLine.createInterface({
 | |
| 		input: process.stdin,
 | |
| 		output: process.stderr
 | |
| 	});
 | |
| 	questionInterface.question(question, answer => {
 | |
| 		questionInterface.close();
 | |
| 
 | |
| 		const normalizedAnswer = answer.toLowerCase();
 | |
| 		const selectedPackage = CLIs.find(item => {
 | |
| 			return item.name === normalizedAnswer || item.alias === normalizedAnswer;
 | |
| 		});
 | |
| 
 | |
| 		if (!normalizedAnswer) {
 | |
| 			console.error(
 | |
| 				"One CLI needs to be installed alongside webpack to use the CLI."
 | |
| 			);
 | |
| 			process.exitCode = 1;
 | |
| 
 | |
| 			return;
 | |
| 		} else if (!selectedPackage) {
 | |
| 			console.error(
 | |
| 				"No matching choice.\n" +
 | |
| 					"One CLI needs to be installed alongside webpack to use the CLI.\n" +
 | |
| 					"Try to installing your CLI of choice manually."
 | |
| 			);
 | |
| 			process.exitCode = 1;
 | |
| 
 | |
| 			return;
 | |
| 		}
 | |
| 
 | |
| 		const packageName = selectedPackage.package;
 | |
| 
 | |
| 		console.log(
 | |
| 			`Installing '${
 | |
| 				selectedPackage.name
 | |
| 			}' (running '${packageManager} ${installOptions.join(
 | |
| 				" "
 | |
| 			)} ${packageName}')...`
 | |
| 		);
 | |
| 
 | |
| 		runCommand(packageManager, installOptions.concat(packageName))
 | |
| 			.then(() => {
 | |
| 				require(packageName); //eslint-disable-line
 | |
| 			})
 | |
| 			.catch(error => {
 | |
| 				console.error(error);
 | |
| 				process.exitCode = 1;
 | |
| 			});
 | |
| 	});
 | |
| } else if (installedClis.length === 1) {
 | |
| 	const path = require("path");
 | |
| 	const pkgPath = require.resolve(`${installedClis[0].package}/package.json`);
 | |
| 	const pkg = require(pkgPath); // eslint-disable-line
 | |
| 	require(path.resolve(path.dirname(pkgPath), pkg.bin[installedClis[0].binName])); // eslint-disable-line
 | |
| } else {
 | |
| 	console.warn(
 | |
| 		`You have installed ${installedClis
 | |
| 			.map(item => item.name)
 | |
| 			.join(
 | |
| 				" and "
 | |
| 			)} 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.`
 | |
| 	);
 | |
| }
 |