@wpk-cli/command-add
Version:
@wpk-cli/command-add
371 lines (264 loc) • 11.1 kB
JavaScript
var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard");
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = addComponent;
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread"));
var _findUp = _interopRequireDefault(require("find-up"));
var _plur = _interopRequireDefault(require("plur"));
var _map = _interopRequireDefault(require("lodash/map"));
var _inquirer = _interopRequireDefault(require("inquirer"));
var _ora = _interopRequireDefault(require("ora"));
var _prettyFormat = _interopRequireDefault(require("pretty-format"));
var _ajv = _interopRequireDefault(require("ajv"));
var _chalk = _interopRequireDefault(require("chalk"));
var _groupBy = _interopRequireDefault(require("lodash/groupBy"));
var _replace = _interopRequireDefault(require("lodash/replace"));
var _semver = _interopRequireDefault(require("semver"));
var _find = _interopRequireDefault(require("lodash/find"));
var _logger = _interopRequireDefault(require("@wpk-cli/logger"));
var _requireLocalNodeModule = _interopRequireDefault(require("require-local-node-module"));
var _forEach = _interopRequireDefault(require("lodash/forEach"));
var _get = _interopRequireDefault(require("lodash/get"));
var _size = _interopRequireDefault(require("lodash/size"));
var _indent = _interopRequireDefault(require("indent"));
var _cardinal = _interopRequireDefault(require("cardinal"));
var _generator = _interopRequireDefault(require("@babel/generator"));
var _ansiEscapes = _interopRequireDefault(require("ansi-escapes"));
var pluginDefs = _interopRequireWildcard(require("@wpk-cli/defs/plugins"));
var loaderDefs = _interopRequireWildcard(require("@wpk-cli/defs/loaders"));
var _defs = require("@wpk-cli/defs");
var _utilities = require("@wpk-cli/utilities");
var _configurator = _interopRequireWildcard(require("../configurator"));
var _constants = require("../constants");
const shortEnvNames = {
prod: "production",
dev: "development"
};
function doesPackageJsonHaveDependency(dep) {
const pkg = (0, _findUp.default)("package.json");
if (!pkg) {
return false;
}
const deps = (0, _objectSpread2.default)({}, pkg.dependencies, pkg.devDependencies);
return (0, _find.default)(deps, (_, k) => k === dep);
}
function installComponentPackage(_x, _x2) {
return _installComponentPackage.apply(this, arguments);
}
/**
* Add a plugin or loader to a webpack configuration.
* @param type {"loader"|"plugin"}
* @param cmd {Object} cli options
* @param [opts] {Object} options object
* @param [opts.config] {WebpackConfig}
* @param [opts.definition] {Object}
* @returns {Promise<*>}
*/
function _installComponentPackage() {
_installComponentPackage = (0, _asyncToGenerator2.default)(function* (cmd, definition) {
_logger.default.info(`installing "${cmd.name}"`, cmd.scope ? _chalk.default.grey(cmd.scope) : "");
return (0, _utilities.installPackages)(`${cmd.name}@${definition.version || "latest"}`, {
scope: cmd.scope || "local",
saveDev: true
});
});
return _installComponentPackage.apply(this, arguments);
}
function addComponent(_x3, _x4, _x5) {
return _addComponent.apply(this, arguments);
}
function _addComponent() {
_addComponent = (0, _asyncToGenerator2.default)(function* (type, cmd, opts) {
const nativeDefinitions = {
plugin: pluginDefs,
loader: loaderDefs
}[type];
if (!nativeDefinitions) {
_logger.default.error(`unknown component type "${type}"`);
_logger.default.error('expecting type to be "plugin" or "loader"');
return false;
}
if (!cmd.name) {
_logger.default.error(`expecting a ${type} name to add to config`);
_logger.default.error(_chalk.default`e.g. {grey wpk add plugin define-plugin}`);
return false;
}
let definition = opts.definition;
if (!definition) {
definition = (0, _find.default)(nativeDefinitions, def => def.name === cmd.name);
}
if (cmd.dryRun) {
cmd.install = false;
}
if (cmd.dev) {
cmd.env = "development";
} else if (cmd.prod) {
cmd.env = "production";
} else if (cmd.env in shortEnvNames) {
cmd.env = shortEnvNames[cmd.env];
}
if (cmd.scope && cmd.scope !== "local" && cmd.scope !== "global") {
_logger.default.error(`bad value for scope "${cmd.scope}"`);
_logger.default.error('expecting "local" or "global"');
return false;
}
let didInstallPkg = false;
if (definition && (definition.native || !cmd.install)) {
const why = definition.native ? "(native component)" : "";
_logger.default.info(`skipping ${type} installation`, why);
} else if (definition && cmd.install) {
// we are looking at a loader for which we already have a definition
// but no loaders are native to webpack so we always must install them
if (definition.type === _constants.ComponentTypes.loader) {
if (!doesPackageJsonHaveDependency(cmd.name)) {
yield installComponentPackage(cmd);
}
}
} else if (!definition && cmd.install) {
const msg = `checking if "${cmd.name}" has a wpk-def.json`;
const spinner = (0, _ora.default)(msg).start();
try {
var hasWpkDefJson = yield (0, _utilities.checkPackageHasWpkDefJson)(cmd.name);
} catch (err) {
_logger.default.error(`failed to check for a wpk-def.json`);
if (cmd.wpkDebug) {
throw err;
}
}
if (!hasWpkDefJson) {
spinner.fail();
_logger.default.error(`no wpk-def.json found for "${cmd.name}"`);
_logger.default.error(`wpk cannot add the ${type} without a definition`);
_logger.default.error("the component must be added manually");
return false;
}
spinner.succeed();
if (cmd.install && !(0, _utilities.checkPackageHasWpkDefJson)(cmd.name)) {
yield installComponentPackage(cmd);
}
_logger.default.info("installation successful");
try {
definition = (0, _requireLocalNodeModule.default)(cmd.name + "/wpk-def.json");
} catch (err) {
_logger.default.error(`could not find a ${type} definition for "${cmd.name}"`);
_logger.default.error(`wpk cannot add the ${type} without a definition`);
_logger.default.error("you will need to add the component manually");
if (cmd.wpkDebug) {
throw err;
}
return false;
}
}
if (!definition && didInstallPkg) {
_logger.default.info("are you a plugin/loader maintainer?");
_logger.default.info(_chalk.default`consider adding a {grey wpk-def.json} file to your project`);
_logger.default.info(_chalk.default`see {grey github.com/wpk-cli/wpk} for more information`);
return 0;
}
const ajv = new _ajv.default({
useDefaults: true
});
ajv.validate(_defs.schemas.wpkDef, definition);
if (ajv.errors) {
const msg = "wpk definition file failed validation";
const err = new Error(msg + ":\n\n" + (0, _prettyFormat.default)(ajv.errors) + "\n");
(0, _utilities.printError)(err, [msg, "please raise with the definition author"]);
return false;
}
if (definition.webpackVersion) {
const version = (0, _utilities.getWebpackVersion)();
if (!_semver.default.satisfies(version, definition.webpackVersion)) {
_logger.default.warn("version of webpack detected is incompatible");
_logger.default.warn(type, "expecting webpack version", `"${definition.webpackVersion}"`);
_logger.default.warn("continuing anyway, however you may encounter issues");
}
}
(0, _logger.default)();
let cont = cmd.configure;
if (cmd.yes) {
cont = false;
}
let components;
if (cont) {
const answers = yield _inquirer.default.prompt([{
name: "cont",
message: `Configure the ${type} interactively?`,
type: "confirm"
}]);
cont = answers.cont;
}
if (!cont) {
cont = "skipped"; // remove the "do you want to configure this plugin" question
process.stdout.write(_ansiEscapes.default.eraseLines(2));
components = yield Promise.all((0, _map.default)(definition.components,
/*#__PURE__*/
function () {
var _ref = (0, _asyncToGenerator2.default)(function* (cmp) {
return (0, _configurator.prepareComponent)(definition, cmp, opts, true);
});
return function (_x6) {
return _ref.apply(this, arguments);
};
}()));
} else {
components = yield (0, _configurator.default)(opts.config, definition, cmd);
}
if (cmd.yes) {
_logger.default.info(`using component defaults`);
if ((0, _size.default)(definition.components) === 1) {
const docs = (0, _get.default)(definition, "components[0].url");
if (docs) {
_logger.default.info("docs:", docs);
}
}
} else {
(0, _logger.default)();
if (cont === "skipped") {
process.stdout.write(_ansiEscapes.default.eraseLines(3));
_logger.default.info(`using component defaults`);
} else {
(0, _logger.default)(_chalk.default.grey("---"));
}
_logger.default.info(`${(0, _plur.default)("component", (0, _size.default)(components))} configured`);
}
const componentsByType = (0, _groupBy.default)(definition.components, "type");
let typeName = type;
if ((0, _size.default)(componentsByType.loader) && (0, _size.default)(componentsByType.plugin)) {
typeName = "component";
}
_logger.default.info("added", (0, _size.default)(components), `${(0, _plur.default)(typeName, (0, _size.default)(components))}` + ":");
(0, _forEach.default)(components, (cmp, i) => {
const cmpDef = definition.components[i];
if (cmpDef.environment) {
cmp.environments = [cmpDef.environment];
}
if (cmpDef.type === _constants.ComponentTypes.plugin) {
opts.config.addPlugin(cmp);
} else if (cmpDef.type === _constants.ComponentTypes.loader) {
opts.config.addModuleRule(cmp);
}
const ast = cmp.buildAst(opts.config, {
environmentConditional: false
});
const src = (0, _generator.default)(ast);
const code = (0, _indent.default)(_cardinal.default.highlight(src.code), 2);
if (!i) {
(0, _logger.default)();
}
(0, _logger.default)(code);
(0, _logger.default)();
});
if (cmd.install && (0, _size.default)(definition.packages)) {
_logger.default.info("installing", (0, _size.default)(definition.packages), "packages");
yield (0, _utilities.installPackages)(definition.packages, {
scope: "local",
saveDev: true
});
}
});
return _addComponent.apply(this, arguments);
}
;