@wpk-cli/cli
Version:
an unofficial CLI for webpack
331 lines (249 loc) • 9.17 kB
JavaScript
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.getCommandDefaults = getCommandDefaults;
exports.applyUserConfigOptions = applyUserConfigOptions;
exports.printCommandError = printCommandError;
exports.processError = processError;
exports.cleanConsole = cleanConsole;
exports.logCommandInfo = logCommandInfo;
exports.logWebpackInfo = logWebpackInfo;
exports.logEnvInfo = logEnvInfo;
exports.checkForUpdateMaybe = checkForUpdateMaybe;
exports.prepareCmd = prepareCmd;
exports.enhanceCommander = enhanceCommander;
var _semver = _interopRequireDefault(require("semver"));
var _execa = _interopRequireDefault(require("execa"));
var _set = _interopRequireDefault(require("lodash/set"));
var _includes = _interopRequireDefault(require("lodash/includes"));
var _reduce = _interopRequireDefault(require("lodash/reduce"));
var _split = _interopRequireDefault(require("lodash/split"));
var _get = _interopRequireDefault(require("lodash/get"));
var _chalk = _interopRequireDefault(require("chalk"));
var _logger = _interopRequireDefault(require("@wpk-cli/logger"));
var _ansiEscapes = _interopRequireDefault(require("ansi-escapes"));
var _getCursorPosition = _interopRequireDefault(require("get-cursor-position"));
var _keys = _interopRequireDefault(require("lodash/keys"));
var _toLower = _interopRequireDefault(require("lodash/toLower"));
var _startsWith = _interopRequireDefault(require("lodash/startsWith"));
var _user = _interopRequireDefault(require("@wpk-cli/user"));
var _utilities = require("@wpk-cli/utilities");
var _package = _interopRequireDefault(require("../package.json"));
var _commands = require("./commands");
const defaultsIgnore = ["WPK_PROFILE"];
let commandDefaults;
/** Gather command default from the environment. */
function getCommandDefaults() {
if (commandDefaults) {
return commandDefaults;
}
const value = (0, _reduce.default)((0, _keys.default)(process.env), (defaults, key) => {
if ((0, _includes.default)(defaultsIgnore, key)) {
return defaults;
}
if ((0, _startsWith.default)(key, "WPK_")) {
const lowerKey = (0, _toLower.default)(key.replace(/^WPK_/, ""));
defaults[lowerKey] = process.env[key];
}
return defaults;
}, {});
commandDefaults = value;
return value;
}
/** Apply user config options to the environment. */
function applyUserConfigOptions() {
const globals = {
color: value => {
process.env.FORCE_COLOR = value;
}
};
for (const opt in globals) {
const value = _user.default.get("global." + opt);
if (value) {
globals[opt](value);
}
}
}
/**
* Like `printError` in @wpk-cli/utilities but for command installation and execution errors
* that have extra messages.
* @param err {Error} the error
* @param command {Object} wpk command definition object
* @param what {String} operation name that errored
*/
function printCommandError(err, command, what) {
_logger.default.intercept.restore();
const name = (0, _get.default)(command, "name") || (0, _get.default)(command, "_location") || command;
const native = name in _commands.nativeCommandNames;
const messages = [`failed to ${what} command "${name}" ` + ((0, _get.default)(command, "_where") ? `(${(0, _get.default)(command, "_where")})` : "")];
if (!native && (0, _get.default)(command, "_location")) {
messages.push("remove this package and file an issue with the author");
let pkg;
try {
pkg = require(command._location + "/package.json");
} catch (err) {}
if (pkg && (pkg.bugs || pkg.homepage)) {
messages[1] = messages[1] + ":";
messages.push(pkg.bugs || pkg.homepage);
}
}
(0, _utilities.printError)(err, messages, native);
process.exit(1);
}
/**
* Handler for uncaught exceptions.
* @param err {Error} the error
*/
function processError(err) {
_logger.default.intercept.restore();
cleanConsole();
(0, _utilities.printError)(err, ["an unknown error occurred"], true);
process.exit(1);
}
/** Clear whatever is beneath the console cursor. */
function cleanConsole() {
const cursor = _getCursorPosition.default.sync();
if (cursor) {
process.stdout.write(_ansiEscapes.default.cursorSavePosition);
for (let i = 0; i < process.stdout.rows - cursor.row; i++) {
process.stdout.write(_ansiEscapes.default.cursorDown());
process.stdout.write(_ansiEscapes.default.eraseLine);
}
process.stdout.write(_ansiEscapes.default.cursorRestorePosition);
}
}
/**
* Log information about the command being run, e.g. name, version.
* @param command {String} command name
* @param thirdParty {Boolean} is the command an add-on?
* @returns {String} the command info that was logged
*/
function logCommandInfo(command, thirdParty = false) {
// TODO remove "beta" tag when out of beta
let cmdInfo = _chalk.default`wpk ${command} {grey v${_package.default.version} beta}`;
if (thirdParty) {
cmdInfo += _chalk.default.grey(" (add-on)");
} // TODO make this not set on the global object
global.wpk.commandInfo = cmdInfo;
if (!global.wpk.noInfoLogs) {
(0, _logger.default)(cmdInfo);
}
return cmdInfo;
}
/**
* Log information about the version and scope of webpack in use.
* @param webpack {Object} the webpack package in use
* @param scope {"local"|"global"} the scope of the webpack package
*/
function logWebpackInfo(webpack, scope) {
let warn;
if (webpack) {
// webpack 4 has webpack.version
let version = webpack.version;
if (!version) {
if (webpack && !webpack.version) {
// webpack <= 3 does not have version property on main export
version = (0, _utilities.getWebpackVersion)(scope);
}
} // TODO make this not set on the global object
global.wpk.webpackInfo = _chalk.default`webpack v${version} {grey (${webpack.scope})}`;
if (!global.wpk.noInfoLogs) {
_logger.default.info(global.wpk.webpackInfo);
}
if ((0, _split.default)(version, ".")[0] < 4) {
warn = `webpack version unsupported`;
}
} else {
warn = "webpack not found";
}
if (!global.wpk.noInfoLogs && warn) {
_logger.default.warn(_chalk.default`${warn} {grey (some commands may fail)}`);
if (warn === "webpack not found") {
_logger.default.warn("install webpack: {grey npm i -g webpack}");
}
}
}
/** Log what defaults are set by the environment. */
function logEnvInfo() {
const defaults = getCommandDefaults();
const defaultKeys = (0, _keys.default)(defaults);
if (defaultKeys.length) {
const len = defaultKeys.length;
let i = 0;
_logger.default.info("defaults set by environment:", (0, _reduce.default)(defaults, (str, v, k) => {
return str + `${k}=${v}` + (i++ === len - 1 ? "" : ", ");
}, ""));
}
}
/**
* Check if an update to wpk is available.
* The check is performed at most once a day.
* @param cmd {Object} Commander cmd object
*/
function checkForUpdateMaybe(cmd) {
// TODO reinstate in the future
return;
if (_user.default.get("global.checkForUpdates")) {
const lastCheckedForUpdate = _user.default.get("$.lastCheckedForUpdate");
if (lastCheckedForUpdate) {
const oneDayMs = 24 * 60 * 60 * 1000;
if (Date.now() - lastCheckedForUpdate < oneDayMs) {
return;
}
}
_user.default.set("$.lastCheckedForUpdate", Date.now());
try {
const _execa$sync = _execa.default.sync("npm view @wpk-cli/cli version"),
stdout = _execa$sync.stdout,
stderr = _execa$sync.stderr;
if (_semver.default.lt(_package.default.version, stdout)) {
// TODO check if @wpk-cli/cli is installed globally by yarn and suggest yarn command instead
_logger.default.info(`a newer version of wpk is available: v${stdout}`);
_logger.default.info(_chalk.default`run {grey npm i -g @wpk-cli/cli} to update`);
}
} catch (err) {
if (cmd.wpkDebug) {
(0, _utilities.printError)(err);
global.wpk.exit(1);
}
}
}
}
/**
* Prepare the cmd object to be handed off to a command by removing
* the Commander private properties & expanding dot-path properties.
* @param cmd {Object} Commander cmd object
*/
function prepareCmd(cmd) {
// remove all Commander.js properties
delete cmd.commands;
delete cmd.options;
delete cmd.parent;
for (const key in cmd) {
if ((0, _startsWith.default)(key, "_")) {
delete cmd[key];
}
} // expand dot path flags
for (const key in cmd) {
/* istanbul ignore next */
if (!cmd.hasOwnProperty(key)) {
continue;
}
if ((0, _includes.default)(key, ".")) {
const value = cmd[key];
delete cmd[key];
(0, _set.default)(cmd, key, value);
}
}
}
/** Enhance Commander program with extra methods. */
function enhanceCommander(program) {
program.Command.prototype.optionMulti = function (option, description) {
return this.option(option, description, (val, memo) => {
memo.push(val);
return memo;
}, []);
};
}
;