atomic-reactor-cli
Version:
A CLI for creating Atomic Reactor Awesomeness
239 lines (215 loc) • 6.7 kB
JavaScript
/**
* -----------------------------------------------------------------------------
* Imports
* -----------------------------------------------------------------------------
*/
const chalk = require('chalk');
const generator = require('./generator');
const prettier = require('prettier');
const path = require('path');
const mod = path.dirname(require.main.filename);
const { error, message } = require(`${mod}/lib/messenger`);
/**
* NAME String
* @description Constant defined as the command name. Value passed to the commander.command() function.
* @example $ arcli reactium empty
* @see https://www.npmjs.com/package/commander#command-specific-options
* @since 2.0.0
*/
const NAME = 'reactium <empty>';
/**
* 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 = 'Reactium: Remove demo pages, components, and toolkit.';
/**
* CANCELED String
* @description Message sent when the command is canceled
* @since 2.0.0
*/
const CANCELED = 'Reactium empty canceled!';
/**
* confirm({ props:Object, params:Object }) Function
* @description Prompts the user to confirm the operation
* @since 2.0.0
*/
const CONFIRM = ({ props, params }) => {
const { prompt } = props;
return new Promise((resolve, reject) => {
prompt.get(
{
properties: {
confirmed: {
description: `${chalk.white(
'This is a destructive operation. Are you sure?',
)} ${chalk.cyan('(Y/N):')}`,
type: 'string',
required: true,
pattern: /^y|n|Y|N/,
message: ` `,
before: val => {
return String(val).toLowerCase() === 'y';
},
},
},
},
(error, input) => {
let confirmed;
try {
confirmed = input.confirmed;
} catch (err) {
confirmed = false;
}
if (error || confirmed === false) {
reject(error);
} else {
resolve(confirmed);
}
},
);
});
};
/**
* 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 }) => {
const { cwd } = props;
let output = {};
Object.entries(input).forEach(([key, val]) => {
switch (key) {
default:
output[key] = val;
break;
}
});
return output;
};
/**
* 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('');
console.log('Usage:');
console.log('');
console.log(' Keep the default toolkit:');
console.log(' $ arcli reactium empty --no-toolkit');
console.log('');
console.log(' Keep the demo site:');
console.log(' $ arcli reactium empty --no-demo');
console.log('');
};
/**
* 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 { cwd, prompt } = props;
return {
properties: {
// sample: {
// description: chalk.white('Sample:'),
// required: true,
// default: true,
// },
},
};
};
/**
* 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 = ['demo', 'font', 'images', 'style', 'toolkit'].reduce(
(obj, key) => {
let val = opt[key];
val = typeof val === 'function' ? null : val;
if (val) {
obj[key] = val;
}
return obj;
},
{},
);
prompt.override = ovr;
prompt.start();
prompt.get(schema, (err, input) => {
// Keep this conditional as the first line in this function.
// Why? because you will get a js error if you try to set or use anything related to the input object.
if (err) {
prompt.stop();
error(`${NAME} ${err.message}`);
return;
}
const params = { ...CONFORM({ input, props }), ...ovr };
CONFIRM({ props, params })
.then(() => {
console.log('');
generator({ params, props }).then(success => {
console.log('');
});
})
.then(() => prompt.stop())
.catch(err => {
prompt.stop();
message(CANCELED);
});
});
};
/**
* COMMAND Function
* @description Function that executes program.command()
*/
const COMMAND = ({ program, props }) =>
program
.command(NAME)
.description(DESC)
.action(opt => ACTION({ opt, props }))
.option('-D, --no-demo [demo]', 'Keep the demo site and components.')
.option(
'-T, --no-toolkit [toolkit]',
'Keep the default toolkit elements.',
)
.option(
'-S, --no-style [style]',
'Do not empty the ~/src/assets/style/style.scss file.',
)
.option(
'-F, --no-font [font]',
'Do not empty the ~/src/assets/fonts directory.',
)
.option(
'-I, --no-images [images]',
'Do not empty the ~/src/assets/images directory.',
)
.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 = {
ACTION,
CONFIRM,
CONFORM,
COMMAND,
ID: NAME,
};