atomic-reactor-cli
Version:
A CLI for creating Atomic Reactor Awesomeness
233 lines (207 loc) • 6.73 kB
JavaScript
/**
* -----------------------------------------------------------------------------
* Imports
* -----------------------------------------------------------------------------
*/
const path = require('path');
const fs = require('fs-extra');
const chalk = require('chalk');
const semver = require('semver');
const op = require('object-path');
const mod = path.dirname(require.main.filename);
const { error, message } = require(`${mod}/lib/messenger`);
const getPackageVersion = (cwd, inc) => {
let val = '0.0.1';
const pkgFile = path.normalize(path.join(cwd, 'package.json'));
if (fs.existsSync(pkgFile)) {
const { version } = require(`${cwd}/package`);
val = version ? semver.coerce(version).version : val;
}
val = inc ? semver.inc(val, inc) : val;
return val;
};
const GENERATOR = require('./generator');
/**
* NAME String
* @description Constant defined as the command name. Value passed to the commander.command() function.
* @example $ arcli publish
* @see https://www.npmjs.com/package/commander#command-specific-options
* @since 2.0.0
*/
const NAME = 'publish';
/**
* DESC String
* @description Constant defined as the command description. Value passed to
* the commander.desc() function. This string is also used in the --help flag output.
* @see https://www.npmjs.com/package/commander#automated---help
* @since 2.0.0
*/
const DESC = 'Publish a reactium module';
/**
* CANCELED String
* @description Message sent when the command is canceled
* @since 2.0.0
*/
const CANCELED = 'Publish canceled!';
/**
* conform(input:Object) Function
* @description Reduces the input object.
* @param input Object The key value pairs to reduce.
* @since 2.0.0
*/
const CONFORM = ({ input, props }) =>
Object.keys(input).reduce((obj, key) => {
let val = input[key];
switch (key) {
case 'version':
const incs = ['major', 'minor', 'patch'];
obj[key] = incs.includes(String(val).toLowerCase())
? semver.inc(getPackageVersion(props.cwd), val)
: semver.coerce(val).version;
break;
default:
obj[key] = val;
break;
}
return obj;
}, {});
/**
* HELP Function
* @description Function called in the commander.on('--help', callback) callback.
* @see https://www.npmjs.com/package/commander#automated---help
* @since 2.0.0
*/
const HELP = () =>
console.log(`
When specifying -v, --version with ${chalk.cyan('major')}, ${chalk.cyan(
'minor',
)}, or ${chalk.cyan('patch')}, the plugin ${chalk.bold(
'package.json',
)} ${chalk.cyan('version')} value will be incremented accordingly.
Example:
$ arcli publish
`);
/**
* FLAGS
* @description Array of flags passed from the commander options.
* @since 2.0.18
*/
const FLAGS = ['app', 'private', 'server', 'version'];
/**
* FLAGS_TO_PARAMS Function
* @description Create an object used by the prompt.override property.
* @since 2.0.18
*/
const FLAGS_TO_PARAMS = ({ opt = {} }) =>
FLAGS.reduce((obj, key) => {
let val = opt[key];
val = typeof val === 'function' ? undefined : val;
if (val) {
obj[key] = val;
}
return obj;
}, {});
/**
* SCHEMA Function
* @description used to describe the input for the prompt function.
* @see https://www.npmjs.com/package/prompt
* @since 2.0.0
*/
const SCHEMA = ({ props }) => {
const sessionToken = op.get(props, 'config.registry.sessionToken');
return {
properties: {
username: {
ask: () => !sessionToken,
description: chalk.white('Username:'),
required: true,
},
password: {
ask: () => !sessionToken,
description: chalk.white('Password:'),
hidden: true,
message: 'Password is a required parameter',
replace: '*',
required: true,
},
version: {
default: getPackageVersion(props.cwd, 'patch'),
description: chalk.white('Version:'),
message: 'Version is a required parameter',
required: true,
},
private: {
before: val => String(val).substr(0, 1).toUpperCase() === 'Y',
default: 'N',
description: `${chalk.white('Private')} ${chalk.cyan('(Y/N):')}`,
message: ' ',
pattern: /^y|n|Y|N/,
required: true,
type: 'string',
}
},
};
};
/**
* ACTION Function
* @description Function used as the commander.action() callback.
* @see https://www.npmjs.com/package/commander
* @param opt Object The commander options passed into the function.
* @param props Object The CLI props passed from the calling class `orcli.js`.
* @since 2.0.0
*/
const ACTION = ({ opt, props }) => {
const { cwd, prompt } = props;
const schema = SCHEMA({ props });
const ovr = FLAGS_TO_PARAMS({ opt });
prompt.override = ovr;
prompt.start();
let params = {};
return new Promise((resolve, reject) => {
prompt.get(schema, (err, input = {}) => {
if (err) {
prompt.stop();
reject(`${NAME} ${err.message}`);
return;
}
input = { ...ovr, ...input };
params = CONFORM({ input, props });
resolve();
});
})
.then(() => GENERATOR({ params, props }))
.then(() => prompt.stop())
.then(results => console.log(''))
.catch(err => {
prompt.stop();
message(op.get(err, 'message', op.get(err, 'msg', CANCELED)));
});
};
/**
* COMMAND Function
* @description Function that executes program.command()
*/
const COMMAND = ({ program, props }) =>
program
.command(NAME)
.description(DESC)
.action(opt => ACTION({ opt, props }))
.option('-a, --app [app]', 'App ID')
.option(
'-p, --private [private]',
'Make the plugin available to ACL targets only',
)
.option('-s, --server [server]', 'Server URL')
.option('-v, --version [version]', 'Plugin semver. Defaults to 0.0.1')
.on('--help', HELP);
/**
* Module Constructor
* @description Internal constructor of the module that is being exported.
* @param program Class Commander.program reference.
* @param props Object The CLI props passed from the calling class `arcli.js`.
* @since 2.0.0
*/
module.exports = {
COMMAND,
NAME,
};