terraform-plus
Version:
Terraform Plus
223 lines (184 loc) • 6.1 kB
JavaScript
const cli = require('commander');
const inquirer = require('inquirer');
const autocomplete = require('inquirer-autocomplete-prompt');
const pjson = require('../package');
const AbstractCommand = require('./abstract-command');
class TerraformPlus {
construct() {
this._currentCommand = null;
this._logger = null;
}
/**
* @desc
* Run tfs [command] [options] [arguments]
*
* @example
* let tfs = new TerraformPlus();
* tfs.run(process.argv);
*
* @param {Array} commandLine - entire command line passed to cli
*/
run(commandLine) {
// customize default indentation
this._defaultIndentation();
// setup cli version
cli.version(pjson.version);
// parse and remove global options from command line
let parsed = commandLine.slice(2);
let options = [ '-V', '--version', '-v', '--verbose', '-w', '--verbose2' ];
for (let i = parsed.length; i > 0; i--) {
if (options.includes(parsed[i - 1])) {
parsed.splice(i - 1, 1);
}
}
// check for potential command name
if (parsed.length > 0) {
// validate that command name is supported
this._parseCommand(parsed);
// remove command from parsed command line
//parsed = parsed.slice(1);
}
// no command provided
else {
// setup default command
this._defaultCommand();
}
// finish specifying commands, options and arguments, and parse the whole thing
cli.arguments('[arguments]')
.option('-v, --verbose', 'output warning messages by enabling verbose mode')
.option('-w, --verbose2', 'output debugging messages by enabling verbose2 mode')
.parse(commandLine);
// enable verbose or debug logging capabilities
if (cli.verbose) {
this._logger.setLevel(this._logger.WARN);
} else if (cli.verbose2) {
this._logger.setLevel(this._logger.DEBUG);
}
// if no options, output help
let showHelp = ((parsed.length <= 1 && parsed[0] === 'create') || parsed.length === 0);
if (showHelp) {
cli.outputHelp();
process.exit(0);
}
}
/**
* @private
*/
_defaultIndentation() {
const helpInformation = cli.Command.prototype.helpInformation;
const indentation = ' ';
cli.Command.prototype.helpInformation = function () {
return helpInformation.call(this)
.split(/^/m)
.reduce((accum, line) => {
if (line === '\n') {
const lastLine = accum[accum.length - 1];
if (!lastLine || !(lastLine === '\n' || lastLine.endsWith(':\n'))) {
accum.push(line);
}
} else {
accum.push(line.substr(indentation.length));
}
return accum;
}, [])
.join('');
}
}
/**
* @private
*/
_defaultCommand() {
// setup command action and description
cli.usage(`[command] [options] [arguments]`)
.description(`tfs@${pjson.version} (built: ${pjson.buildDate})\n ${pjson.description}`);
// setup command options
AbstractCommand.COMMANDS_LIST.forEach(command => {
if (typeof command !== 'undefined') {
cli.command(command.name)
.description(command.description);
}
});
// customize help output
cli.on('--help', function() {
console.log(`\nUse "tfs [command] --help" for more information about [command]`);
});
// enable default logging capabilities
this._logger = AbstractCommand.LOGGER;
}
/**
* @desc Validates passed command name and set up it.
*
* @param {Array} parsed
*
* @private
*/
_parseCommand(parsed) {
// validate that command name is supported
if (AbstractCommand.COMMANDS_LIST.map(key => key.name).includes(parsed[0])) {
this._currentCommand = parsed[0];
// setup command specific action and description
const CommandClass = require(`${AbstractCommand.COMMANDS_PATH}/${this._currentCommand}`);
cli.usage(`${parsed[0]} [options] [arguments]`)
.description(`tfs@${pjson.version} (built: ${pjson.buildDate})
tfs ${this._currentCommand} will ${CommandClass.DESCRIPTION}`);
if ((parsed.length >= 1 && parsed[0] !== 'create') || (parsed.length > 1 && parsed[0] === 'create')) {
cli.action(commandName => { this._runCommand(commandName, parsed) });
}
// setup command specific options
CommandClass.OPTIONS.forEach(option => {
if (option.hasOwnProperty('collect')) {
cli.option(option.opt, option.desc, this.collect, []);
}
else {
cli.option(option.opt, option.desc);
}
});
// enable default logging capabilities
this._logger = CommandClass.LOGGER;
}
// command name is NOT supported
else {
console.log(`'${parsed[0]}' is not a valid tfs command`);
console.log(`Use 'tfs --help' to see supported list of commands.`);
process.exit(1);
}
}
/**
*
* @param {String} val
* @param {Array} memo
* @return {*}
*/
collect(val, memo) {
memo.push(val);
return memo;
}
/**
* Runs dynamicly tfs [command]
* @param {String} commandName
* @param {Object} parsed
* @private
*/
async _runCommand(commandName, parsed) {
const CommandClass = require(`${AbstractCommand.COMMANDS_PATH}/${commandName}`);
const command = new CommandClass(cli, parsed);
if (!(command instanceof AbstractCommand)) {
throw new Error(`${commandName} must be an implementation of AbstractCommand class`);
}
if (command._cli.interactive) {
inquirer.registerPrompt('autocomplete', autocomplete);
await inquirer.prompt(CommandClass.QUESTIONS).then(answers => {
// Use user feedback for ... whatever!!
command.promt(answers);
//command.run();
});
}
if (parsed.indexOf('-h') > -1 || parsed.indexOf('--help') > -1) {
command._cli.outputHelp();
process.exit(0);
}
command.run().then(res => {}).catch(err => this._logger.error(err));
}
}
module.exports = TerraformPlus;
;