pyr
Version:
A package for creating a script to store and run your most commonly used CLI commands
151 lines (130 loc) • 4.4 kB
JavaScript
const changeCase = require('change-case');
const fse = require('fs-extra');
const {
GlobalConfig
} = require('src/config');
const {
Operations,
OperationTypes
} = require('src/program');
const {
PATH_TO_LOCAL_YML
} = require('src/constants');
const {
Parser
} = require('src/parser');
const {
commander
} = require('src/shims/commander');
const {
isValidArgumentsLength,
safeExit
} = require('src/utility');
const {
print,
ERROR
} = require('src/messages');
const Menu = require('src/menu');
const validateArgumentLength = (operation, args) => {
const minimumArgumentsLength = operation.args.filter(arg => arg.required).length;
const maximumArgumentsLength = operation.args.length;
if (!isValidArgumentsLength({
actual: args.length,
min: minimumArgumentsLength,
max: maximumArgumentsLength
})) {
print(ERROR, 'invalidNumberOfArgs', operation.name, minimumArgumentsLength, maximumArgumentsLength, args.length);
safeExit();
}
}
const getArguments = () => {
const args = process.argv.slice(2);
return args.filter(arg => arg.indexOf('--') === -1 && arg.indexOf('-') !== 0);
}
const hasMutuallyExclusiveOperations = operations => {
return operations.some(operation => {
return operations.some(otherOperation => {
if (operation !== otherOperation && !operation.whitelist.includes(otherOperation.name)) {
print(ERROR, 'invalidWhitelisted', operation.name, otherOperation.name);
return true;
}
});
});
}
const getOperationsFromCommander = () => {
const operations = [];
Object.keys(OperationTypes).forEach(operationType => {
const operation = Operations.get(OperationTypes[operationType]);
if (commander.hasOwnProperty(changeCase.camelCase(operation.name))) {
operations.push(operation);
}
});
return operations;
}
const hasLocalPyrFile = () => {
return fse.existsSync(PATH_TO_LOCAL_YML);
}
const loadLocalPyrFile = () => {
Parser.runScript(PATH_TO_LOCAL_YML);
}
const runMenuOrHelp = () => {
GlobalConfig.load();
if (Object.keys(GlobalConfig.getScripts()).length === 0) {
commander.help();
} else {
const runOperation = Operations.get(OperationTypes.RUN);
const menu = new Menu({
operationName: runOperation.name,
operationRun: runOperation.run
});
menu.run();
}
}
const handleNoOperations = () => {
if (hasLocalPyrFile()) {
loadLocalPyrFile();
} else {
runMenuOrHelp();
}
}
const handleArguments = () => {
const operations = getOperationsFromCommander();
if (operations.length === 0) {
handleNoOperations();
} else {
if (hasMutuallyExclusiveOperations(operations)) {
safeExit();
}
const args = getArguments();
// Validate the arguments for all operations except `documented` which can be used in conjunction with the `run` operation
const operationsWithoutDocumented = operations.filter(operation => operation !== Operations.get(OperationTypes.DOCUMENTED));
operationsWithoutDocumented.forEach(operation => validateArgumentLength(operation, args));
// TODO - change `documented` from an Operation to an OperatingMode so we can just run operations if they're valid and not have to filter out documented
operations.forEach(operation => operation.run(args));
if (operationsWithoutDocumented.length === 0) {
runMenuOrHelp();
}
}
}
const formatArguments = args => {
return args.map(arg => arg.required ? `<${arg.name}>` : `[${arg.name}]`).join(' ');
}
const addOperationsToCommander = () => {
Object.keys(OperationTypes).forEach(operationType => {
const operation = Operations.get(OperationTypes[operationType]);
const details = `-${operation.flag}, --${operation.name} ${formatArguments(operation.args)}`;
const description = `${operation.description.toLowerCase()}`;
commander.option(details, description);
});
};
const init = () => {
commander.version('1.1.1');
commander.usage('[options]');
addOperationsToCommander();
commander.parse(process.argv);
handleArguments();
}
module.exports = {
init: init
}