@haystacks/async
Version:
A framework to build any number or any kind of native application or automation solution.
513 lines (497 loc) • 31 kB
JavaScript
/**
* @file advanced.js
* @module advanced
* @description Contains all of the advanced system commands.
* @requires module:commandBroker
* @requires module:ruleBroker
* @requires module:workflowBroker
* @requires module:configurator
* @requires module:loggers
* @requires module:data
* @requires module:queue
* @requires module:stack
* @requires {@link https://www.npmjs.com/package/@haystacks/constants|@haystacks/constants}
* @requires {@link https://www.npmjs.com/package/path|path}
* @author Seth Hollingsead
* @date 2022/02/04
* @copyright Copyright © 2022-… by Seth Hollingsead. All rights reserved
*/
// Internal imports
import commandBroker from '../../brokers/commandBroker.js';
import ruleBroker from '../../brokers/ruleBroker.js';
import workflowBroker from '../../brokers/workflowBroker.js';
import configurator from '../../executrix/configurator.js';
import loggers from '../../executrix/loggers.js';
import D from '../../structures/data.js';
import queue from '../../structures/queue.js';
import stack from '../../structures/stack.js';
// External imports
import hayConst from '@haystacks/constants';
import path from 'path';
const {bas, biz, cfg, gen, msg, sys, wrd} = hayConst;
const baseFileName = path.basename(import.meta.url, path.extname(import.meta.url));
// framework.commandsBlob.commands.advanced.
const namespacePrefix = wrd.cframework + bas.cDot + sys.ccommandsBlob + bas.cDot + wrd.ccommands + bas.cDot + baseFileName + bas.cDot;
/**
* @function commandSequencer
* @description Takes an arguments array where the second array object would contain a list of
* commands that should be enqueued to the command queue.
* @param {array<boolean|string|integer>} inputData An array that could actually contain anything,
* depending on what the user entered. But the function filters all of that internally and
* extracts the case the user has entered a list of commands that should be enqueued to the command queue.
* inputData[0] === 'commandSequencer'
* inputData[1] === command string 1
* inputData[2] === command string 2
* inputData[n] === command string n
* @param {string} inputMetaData Not used for this command.
* @return {array<boolean,string|integer|boolean|object|array>} An array with a boolean True or False value to
* indicate if the application should exit or not exit, followed by the command output.
* @author Seth Hollingsead
* @date 2022/02/22
*/
async function commandSequencer(inputData, inputMetaData) {
let functionName = commandSequencer.name;
await loggers.consoleLog(namespacePrefix + functionName, msg.cBEGIN_Function);
await loggers.consoleLog(namespacePrefix + functionName, msg.cinputDataIs + JSON.stringify(inputData));
await loggers.consoleLog(namespacePrefix + functionName, msg.cinputMetaDataIs + inputMetaData);
let returnData = [true, {}];
let commandSuccess = true;
// Initialize a temporary command queue that can be used to aggregate all of the commands that will be added to the official command queue.
// Once all of the commands are aggregated then we will enqueue the new temporary command queue to the front of the official command queue.
await queue.initQueue(sys.cCommandQueue + wrd.cTemp);
for (let i = 1; i < inputData.length; i++) {
let commandString = inputData[i];
let primaryCommandDelimiter = await configurator.getConfigurationSetting(wrd.csystem, cfg.cprimaryCommandDelimiter);
await loggers.consoleLog(namespacePrefix + functionName, msg.cprimaryCommandDelimiterIs + primaryCommandDelimiter);
if (primaryCommandDelimiter === null || primaryCommandDelimiter !== primaryCommandDelimiter || primaryCommandDelimiter === undefined) {
primaryCommandDelimiter = bas.cSpace;
}
let secondaryCommandArgsDelimiter = await configurator.getConfigurationSetting(wrd.csystem, cfg.csecondaryCommandDelimiter);
await loggers.consoleLog(namespacePrefix + functionName, msg.csecondaryCommandDelimiterIs + secondaryCommandArgsDelimiter);
let tertiaryCommandDelimiter = await configurator.getConfigurationSetting(wrd.csystem, cfg.ctertiaryCommandDelimiter);
await loggers.consoleLog(namespacePrefix + functionName, msg.ctertiaryCommandDelimiterIs + tertiaryCommandDelimiter);
// Replace 2nd & rd level delimiters and down-increment them so we are dealing with command strings that can actually be executed.
const regEx1 = new RegExp(secondaryCommandArgsDelimiter, bas.cg);
commandString = commandString.replace(regEx1, primaryCommandDelimiter);
if (commandString.includes(tertiaryCommandDelimiter)) {
const regEx2 = new RegExp(tertiaryCommandDelimiter, bas.cg);
commandString = commandString.replace(regEx2, secondaryCommandArgsDelimiter);
}
let currentCommand = await commandBroker.getValidCommand(commandString, primaryCommandDelimiter);
let commandArgs = await commandBroker.getCommandArgs(commandString, primaryCommandDelimiter);
// We need to recompose the command arguments for the current command using the sys.cPrimaryCommandDelimiter.
if (currentCommand !== false) {
for (let j = 1; j < commandArgs.length; j++) {
currentCommand = currentCommand + primaryCommandDelimiter + commandArgs[j];
} // End-for (let j = 1; j < commandArgs.length; j++)
await loggers.consoleLog(namespacePrefix + functionName, msg.ccommandSequencerCommandToEnqueueIs + currentCommand);
if (await configurator.getConfigurationSetting(wrd.csystem, cfg.clogAllCommands) === true) {
await stack.push(sys.cSystemCommandLog, currentCommand);
}
await queue.enqueue(sys.cCommandQueue + wrd.cTemp, currentCommand);
} else { // End-if (currentCommand !== false)
// WARNING: advanced.commandSequencer: The specified command was not found, please enter a valid command and try again. <commandString>
let errorMessage = msg.ccommandSequencerMessage1 + msg.ccommandSequencerMessage2 + bas.cSpace + commandString;
console.log(errorMessage);
returnData[1] = errorMessage;
commandSuccess = false;
}
} // End-for (let i = 1; i < inputData.length; i++)
// Now migrate the temporary command queue to the primary command queue,
// pushing all command entities it to the front of the command queue.
await queue.enqueueFront(sys.cCommandQueue, await queue.queueContents(sys.cCommandQueue + wrd.cTemp));
if (commandSuccess === true) {
returnData[1] = commandSuccess;
}
await loggers.consoleLog(namespacePrefix + functionName, msg.creturnDataIs + JSON.stringify(returnData));
await loggers.consoleLog(namespacePrefix + functionName, msg.cEND_Function);
return returnData;
}
/**
* @function workflow
* @description Takes an arguments array where the second array object would contain a workflow name.
* We will lookup the named workflow in the D-data structure and send that workflow to a cal to the command sequencer.
* Which will in-turn convert the list of commands in that workflow into commands that are enqueued to the command queue.
* @param {array<boolean|string|integer>} inputData An array that could actually contain anything,
* depending on what the user entered. But the function filters all of that internally and
* extracts the case the user has entered a workflow name, that we should use to look up the workflow in the D-data structure.
* inputData[0] === 'workflow'
* inputData[1] === workflowName
* @param {string} inputMetaData Not used for this command.
* @return {array<boolean,string|integer|boolean|object|array>} An array with a boolean True or False value to
* indicate if the application should exit or not exit, followed by the command output.
* @author Seth Hollingsead
* @date 2022/2/24
*/
async function workflow(inputData, inputMetaData) {
let functionName = workflow.name;
await loggers.consoleLog(namespacePrefix + functionName, msg.cBEGIN_Function);
await loggers.consoleLog(namespacePrefix + functionName, msg.cinputDataIs + JSON.stringify(inputData));
await loggers.consoleLog(namespacePrefix + functionName, msg.cinputMetaDataIs + inputMetaData);
let returnData = [true, {}];
let workflowName = inputData[1];
let workflowValue = await workflowBroker.getWorkflow(workflowName);
if (workflowValue !== false && typeof workflowValue != wrd.cobject) {
await queue.enqueueFront(sys.cCommandQueue, workflowValue);
returnData[1] = true;
} else {
// WARNING: advanced.workflow: The specified workflow:
// was not found in either the system defined workflows, or client defined workflows.
// Please enter a valid workflow name and try again.
let errorMessage = msg.cworkflowMessage1 + workflowName + bas.cComa + msg.cworkflowMessage2 + msg.cworkflowMessage3;
console.log(errorMessage);
returnData[1] = errorMessage;
}
await loggers.consoleLog(namespacePrefix + functionName, msg.creturnDataIs + JSON.stringify(returnData));
await loggers.consoleLog(namespacePrefix + functionName, msg.cEND_Function);
return returnData;
}
/**
* @function businessRule
* @description Executes a user specified business rule with some input.
* @param {array<boolean|string|integer>} inputData An array that could actually contain anything,
* depending on what the user entered. But the function filters all of that internally and
* extracts the case the user has entered a business rule name and perhaps some rule inputs.
* inputData[0] === 'businessRule'
* inputData[1] === rule 1 (including arguments with secondary delimiter)
* inputData[2] === rule 2 (including arguments with secondary delimiter)
* inputData[n] === rule n (including arguments with secondary delimiter)
* @NOTE There are 2 ways this system can work, the user can either call each rule with it's own inputs,
* or the user can leverage the rule system itself to pass the outputs from rule 1 as inputs to rule 2, etc...
* This command will only always take the arguments for the first business rule as inputs and let the business rules system
* pass the outputs as inputs as discussed above.
* It is assumed if the user wanted to execute a sequence of business rules each with their own inputs,
* then the user should use the command sequencer in combination with this function
* to call a series of business rules each with their own inputs.
* @param {string} inputMetaData Not used for this command.
* @return {array<boolean,string|integer|boolean|object|array>} An array with a boolean True or False value to
* indicate if the application should exit or not exit, followed by the command output.
* @author Seth Hollingsead
* @date 2022/02/24
* @NOTE When executing the business rule: replaceCharacterWithCharacter with a regular expression such as: regEx:[+]:flags:g
* Consider the following link that describes how the regEx & flags are parsed by the lexicalAnalyzer.
* {@link https://stackoverflow.com/questions/874709/converting-user-input-string-to-regular-expression}
*/
async function businessRule(inputData, inputMetaData) {
let functionName = businessRule.name;
await loggers.consoleLog(namespacePrefix + functionName, msg.cBEGIN_Function);
await loggers.consoleLog(namespacePrefix + functionName, msg.cinputDataIs + JSON.stringify(inputData));
await loggers.consoleLog(namespacePrefix + functionName, msg.cinputMetaDataIs + inputMetaData);
let returnData = [true, {}];
let rules = [];
let ruleInputData, ruleInputMetaData;
let ruleOutput = '';
let businessRuleOutput = await configurator.getConfigurationSetting(wrd.csystem, cfg.cenableBusinessRuleOutput);
let businessRuleMetricsEnabled = await configurator.getConfigurationSetting(wrd.csystem, cfg.cenableBusinessRulePerformanceMetrics);
let businessRuleStartTime = '';
let businessRuleEndTime = '';
let businessRuleDeltaTime = '';
// First go through each rule that should be executed and determine if
// there are any inputs that need to be passed into the business rule.
for (let i = 1; i < inputData.length; i++) {
// Begin the i-th iteration fo the inputData array. i is:
await loggers.consoleLog(namespacePrefix + functionName, msg.cBEGIN_theIthIterationOfInputDataArray + i);
let currentRuleArg = inputData[i]; // Check to see if this rule has inputs separate from the rule name.
// currentRule is:
await loggers.consoleLog(namespacePrefix + functionName, msg.ccurrentRuleIs + JSON.stringify(currentRuleArg));
if (i === 1) {
// rules = lexical.parseBusinessRuleArgument(currentRuleArg, i);
rules = await ruleBroker.processRules([currentRuleArg, i], [biz.cparseBusinessRuleArgument]);
} else if (i === 2) {
// ruleInputData = lexical.parseBusinessRuleArgument(currentRuleArg, i);
ruleInputData = await ruleBroker.processRules([currentRuleArg, i], [biz.cparseBusinessRuleArgument]);
} else if (i === 3 && inputData.length <= 4) {
// ruleInputMetaData = lexical.parseBusinessRuleArgument(currentRuleArg, i);
ruleInputMetaData = await ruleBroker.processRules([currentRuleArg, i], [biz.cparseBusinessRuleArgument]);
} else if (i === 3 && inputData.length > 4) {
// // In this case all of the arguments will have been combined into a single array and added to the ruleInputData.
ruleInputMetaData = [];
for (let j = 3; j <= inputData.length - 1; j++) {
let currentRuleArrayArg = inputData[j];
// let tempArg = lexical.parseBusinessRuleArgument(currentRuleArrayArg, j);
let tempArg = await ruleBroker.processRules([currentRuleArrayArg, j], [biz.cparseBusinessRuleArgument]);
// console.log('tempArg is: ' + tempArg);
if (tempArg) {
ruleInputMetaData.push(tempArg);
}
} // End-for (let j = 3; j <= inputData.length - 1; j++)
break;
} // End-Else-if (i === 3 && inputData.length > 4)
} // End-for (let i = 1; i < inputData.length; i++)
// rules is:
await loggers.consoleLog(namespacePrefix + functionName, msg.crulesIs + JSON.stringify(rules));
// ruleInputData is:
await loggers.consoleLog(namespacePrefix + functionName, msg.cruleInputDataIs + ruleInputData);
// ruleInputMetaData is:
await loggers.consoleLog(namespacePrefix + functionName, msg.cruleInputMetaData + JSON.stringify(ruleInputMetaData));
if (businessRuleMetricsEnabled === true) {
// Here we will capture the start time of the business rule we are about to execute.
// After executing we will capture the end time and then
// compare the difference to determine how many milliseconds it took to run the business rule.
businessRuleStartTime = await ruleBroker.processRules([gen.cYYYYMMDD_HHmmss_SSS, ''], [biz.cgetNowMoment]);
// Business Rule Start time is:
await loggers.consoleLog(namespacePrefix + functionName, msg.cBusinessRuleStartTimeIs + businessRuleStartTime);
} // End-if (businessRuleMetricsEnabled === true)
ruleOutput = await ruleBroker.processRules([ruleInputData, ruleInputMetaData], rules);
returnData[1] = ruleOutput;
if (businessRuleMetricsEnabled === true) {
let performanceTrackingObject = {};
businessRuleEndTime = await ruleBroker.processRules([gen.cYYYYMMDD_HHmmss_SSS, ''], [biz.cgetNowMoment]);
// BusinessRule End time is:
await loggers.consoleLog(namespacePrefix + functionName, msg.cBusinessRuleEndTimeIs + businessRuleEndTime);
// Now compute the delta time so we know how long it took to run that business rule.
businessRuleDeltaTime = await ruleBroker.processRules([businessRuleStartTime, businessRuleEndTime], [biz.ccomputeDeltaTime]);
// BusinessRule run-time is:
await loggers.consoleLog(namespacePrefix + functionName, msg.cBusinessRuleRunTimeIs + businessRuleDeltaTime);
// Check to make sure the business rule performance tracking stack exists or does not exist.
if (D[cfg.cbusinessRulesPerformanceTrackingStack] === undefined) {
await stack.initStack(cfg.cbusinessRulesPerformanceTrackingStack);
}
if (D[cfg.cbusinessRulesNamesPerformanceTrackingStack] === undefined) {
await stack.initStack(cfg.cbusinessRulesNamesPerformanceTrackingStack);
}
performanceTrackingObject = {Name: rules[0], RunTime: businessRuleDeltaTime};
if (await stack.contains(cfg.cbusinessRulesNamesPerformanceTrackingStack, rules[0]) === false) {
await stack.push(cfg.cbusinessRulesNamesPerformanceTrackingStack, rules[0]);
}
await stack.push(cfg.cbusinessRulesPerformanceTrackingStack, performanceTrackingObject);
// stack.print(cfg.cBusinessRulePerformanceTrackingStack);
// stack.print(cfg.cBusinessRuleNamesPerformanceTrackingStack);
} // End-if (businessRuleMetricsEnabled === true)
if (businessRuleOutput === true) {
// Rule output is:
console.log(msg.cRuleOutputIs + JSON.stringify(ruleOutput));
}
await loggers.consoleLog(namespacePrefix + functionName, msg.creturnDataIs + JSON.stringify(returnData));
await loggers.consoleLog(namespacePrefix + functionName, msg.cEND_Function);
return returnData;
}
/**
* @function commandGenerator
* @description Takes a set of input parameters such as a command and the number of times it should be executed.
* Then this command will enqueue that command that number of times to the command queue.
* @param {array<boolean|string|integer>} inputData An array that could actually contain anything,
* depending on what the user entered. But the function filters all of that internally and
* extracts the command that should be executed and the number of times it should be executed.
* inputData[0] === 'commandGenerator'
* inputData[1] === command string
* inputData[2] === number of times to enqueue the above command string
* @param {string} inputMetaData Not used for this command.
* @return {array<boolean,string|integer|boolean|object|array>} An array with a boolean True or False value to
* indicate if the application should exit or not exit, followed by the command output.
* @author Seth Hollingsead
* @date 2022/02/24
*/
async function commandGenerator(inputData, inputMetaData) {
let functionName = commandGenerator.name;
await loggers.consoleLog(namespacePrefix + functionName, msg.cBEGIN_Function);
await loggers.consoleLog(namespacePrefix + functionName, msg.cinputDataIs + JSON.stringify(inputData));
await loggers.consoleLog(namespacePrefix + functionName, msg.cinputMetaDataIs + inputMetaData);
let returnData = [true, {}];
let errorMessage = '';
let legitNumberIndex = -1;
let replaceCharacterWithCharacterRule = [biz.creplaceCharacterWithCharacter];
let primaryCommandDelimiter = await configurator.getConfigurationSetting(wrd.csystem, cfg.cprimaryCommandDelimiter);
if (primaryCommandDelimiter === null || primaryCommandDelimiter !== primaryCommandDelimiter || primaryCommandDelimiter === undefined) {
primaryCommandDelimiter = bas.cSpace;
}
let secondaryCommandArgsDelimiter = await configurator.getConfigurationSetting(wrd.csystem, cfg.csecondaryCommandDelimiter);
let tertiaryCommandDelimiter = await configurator.getConfigurationSetting(wrd.csystem, cfg.ctertiaryCommandDelimiter);
let commandString = '';
if (inputData.length === 3) {
commandString = inputData[1];
} else if (inputData.length >= 4) {
for (let i = 1; i < inputData.length - 1; i++) {
if (i === 1) {
commandString = inputData[1];
} else {
commandString = commandString + bas.cBackTickQuote + inputData[i].trim() + bas.cBackTickQuote;
}
} // End-for (let i = 1; i < inputData.length - 1; i++)
}
// NOTE: the str.replace only replaces the first instance of a string value, not all values.
// but we might have another issue in the sense that if the string begins and ends with "[" & "]" respectively,
// we might not want to replace those characters.
// Because it might be that the command should take responsibility or that in such a special case,
// i.e. treating the whole block as a single array and doing it's own split operation.
// commandString = commandString.replace(secondaryCommandArgsDelimiter, primaryCommandDelimiter);
// commandString = commandString.replace(tertiaryCommandDelimiter, secondaryCommandArgsDelimiter);
// commandString before attempted delimiter swap is:
await loggers.consoleLog(namespacePrefix + functionName, msg.ccommandStringBeforeAttemptedDelimiterSwapIs + commandString);
// replaceCharacterWithCharacterRule is:
await loggers.consoleLog(namespacePrefix + functionName, msg.creplaceCharacterWithCharacterRuleIs + JSON.stringify(replaceCharacterWithCharacterRule));
// let secondaryCommandDelimiterRegEx = new RegExp(bas.cBackSlash + secondaryCommandArgsDelimiter, bas.cg);
// let secondaryCommandDelimiterRegEx = new RegExp(`[${secondaryCommandArgsDelimiter}]`, bas.cg);
commandString = await ruleBroker.processRules([commandString, [secondaryCommandArgsDelimiter, primaryCommandDelimiter]], replaceCharacterWithCharacterRule);
// After attempting to replace the secondaryCommandArgsDelimiter with the primaryCommandDelimiter commandString is:
await loggers.consoleLog(namespacePrefix + functionName, msg.ccommandGeneratorMessage1 + commandString);
// let tertiaryCommandDelimiterRegEx = new RegExp(bas.cBackSlash + tertiaryCommandDelimiter, bas.cg);
// let tertiaryCommandDelimiterRegEx = new RegExp(`[${tertiaryCommandDelimiter}]`, bas.cg);
commandString = await ruleBroker.processRules([commandString, [tertiaryCommandDelimiter, secondaryCommandArgsDelimiter]], replaceCharacterWithCharacterRule);
// After attempting to replace the teriaryCommandDelimiter with the secondaryCommandArgsDelimiter commandString is:
await loggers.consoleLog(namespacePrefix + functionName, msg.ccommandGeneratorMessage2 + commandString);
let currentCommand = await commandBroker.getValidCommand(commandString, primaryCommandDelimiter);
let commandArgs = await commandBroker.getCommandArgs(commandString, primaryCommandDelimiter);
await loggers.consoleLog(namespacePrefix + functionName, msg.ccurrentCommandIs + currentCommand);
await loggers.consoleLog(namespacePrefix + functionName, msg.ccommandArgsIs + JSON.stringify(commandArgs));
if (currentCommand !== false) {
if (inputData.length >= 3) {
for (let j = 2; j <= inputData.length - 1; j++) {
if (isNaN(inputData[j].trim()) === false) {
legitNumberIndex = j;
break;
} // End-if (isNaN(inputData[j].trim()) === false)
} // End-for (let j = 2; j <= inputData.length - 1; j++)
} // End-if (inputData.length >= 3)
if (isNaN(inputData[legitNumberIndex]) === false) { // Make sure the user passed in a number for the second argument.
let numberOfCommands = parseInt(inputData[legitNumberIndex]);
if (numberOfCommands > 0) {
await queue.initQueue(sys.cCommandQueue + wrd.cTemp);
for (let i = 0; i < numberOfCommands; i++) {
await queue.enqueue(sys.cCommandQueue + wrd.cTemp, commandString);
} // End-for (let i = 0; i < numberOfCommands; i++)
// Now migrate the temporary command queue to the primary command queue,
// pushing all command entities it to the front of the command queue.
let commandToQueue = await queue.queueContents(sys.cCommandQueue + wrd.cTemp);
if (await configurator.getConfigurationSetting(wrd.csystem, cfg.clogAllCommands) === true) {
await stack.push(sys.cSystemCommandLog, commandToQueue);
}
await queue.enqueueFront(sys.cCommandQueue, commandToQueue);
returnData[1] = true;
} else {
// WARNING: advanced.commandGenerator: Must enter a number greater than 0, number entered:
errorMessage = msg.ccommandGeneratorMessage3 + numberOfCommands;
console.log(errorMessage);
returnData[1] = errorMessage;
}
} else {
// WARNING: advanced.commandGenerator: Number entered for the number of commands to generate is not a number:
errorMessage = msg.ccommandGeneratorMessage4 + inputData[2];
console.log(errorMessage);
returnData[1] = errorMessage;
}
} else {
// WARNING: advanced.commandGenerator: The specified command:
// was not found, please enter a valid command and try again.
errorMessage = msg.ccommandGeneratorMessage5 + commandString + msg.ccommandGeneratorMessage6;
console.log(errorMessage);
returnData[1] = errorMessage;
}
await loggers.consoleLog(namespacePrefix + functionName, msg.creturnDataIs + JSON.stringify(returnData));
await loggers.consoleLog(namespacePrefix + functionName, msg.cEND_Function);
return returnData;
}
/**
* @function commandAliasGenerator
* @description Requests a set of inputs from the user for a command name,
* and a series of command words and a list of command word acronyms.
* The command then calls a series of business rules to in-turn generate all
* possible combinations of command words and command word acronyms.
* @param {array<object|boolean|string|integer>} inputData An array that could actually contain anything,
* depending on what the user entered. But the function filters all of that internally and
* parses the data string object into a JSON object with values that are the command words and command word abbreviations.
* inputData[0] === 'commandAliasGenerator'
* inputData[1] === A JSON object containing the data necessary for defining all command words and command aliases.
* @NOTE Test string for argument driven interface for this command:
* {"constants":"c,const","Generator":"g,gen,genrtr","List":"l,lst"}
* @param {string} inputMetaData Not used for this command.
* @return {array<boolean,string|integer|boolean|object|array>} An array with a boolean True or False value to
* indicate if the application should exit or not exit, followed by the command output.
* @author Seth Hollingsead
* @date 2022/02/25
*/
async function commandAliasGenerator(inputData, inputMetaData) {
let functionName = commandAliasGenerator.name;
await loggers.consoleLog(namespacePrefix + functionName, msg.cBEGIN_Function);
await loggers.consoleLog(namespacePrefix + functionName, msg.cinputDataIs + JSON.stringify(inputData));
await loggers.consoleLog(namespacePrefix + functionName, msg.cinputMetaDataIs + inputMetaData);
let returnData = [true, {}];
let commandName = '';
let commandWordAliasList = '';
let validCommandName = false;
let validCommandWordAliasList = false;
let validCommandInput = false;
let commandAliasDataStructure = {};
// Command can be called by passing parameters and bypass the prompt system.
console.log(msg.ccommandAliasGeneratorMessage1);
// EXAMPLE: {"constants":"c,const","Generator":"g,gen,genrtr","List":"l,lst"}
console.log(msg.ccommandAliasGeneratorMessage2);
if (inputData.length === 0) {
while (validCommandName === false) {
console.log(msg.cCommandNamePrompt1);
console.log(msg.cCommandNamePrompt2);
console.log(msg.cCommandNamePrompt3);
console.log(msg.cCommandNamePrompt4);
console.log(msg.cCommandNamePrompt5);
commandName = await ruleBroker.processRules([bas.cGreaterThan, ''], [biz.cprompt]);
validCommandName = await ruleBroker.processRules([commandName, ''], [biz.cisValidCommandNameString]);
if (validCommandName === false) {
// INVALID INPUT: Please enter a valid camel-case command name.
console.log(msg.ccommandAliasGeneratorMessage3);
} // End-if (validCommandName === false)
} // End-while (validCommandName === false)
let camelCaseCommandNameArray = await ruleBroker.processRules([commandName, ''], [biz.cconvertCamelCaseStringToArray]);
// camelCaseCommandNameArray is:
await loggers.consoleLog(namespacePrefix + functionName, msg.ccamelCaseCommandNameArrayIs + JSON.stringify(camelCaseCommandNameArray));
for (const element of camelCaseCommandNameArray) {
let commandWord = element;
// current commandWord is:
console.log(msg.ccurrentCommandWordIs + commandWord);
validCommandWordAliasList = false;
if (commandWord !== '') {
commandAliasDataStructure[commandWord] = {};
while (validCommandWordAliasList === false) {
console.log(msg.cCommandWordAliasPrompt1);
console.log(msg.cCommandWordAliasPrompt2);
console.log(msg.cCommandWordAliasPrompt3 + bas.cSpace + commandWord);
commandWordAliasList = await ruleBroker.processRules([bas.cGreaterThan, ''], [biz.cprompt]);
validCommandWordAliasList = await ruleBroker.processRules([commandWordAliasList, ''], [biz.cisStringList]);
if (validCommandWordAliasList === false) {
// INVALID INPUT: Please enter a valid command word alias list.
console.log(msg.ccommandAliasGeneratorMessage4);
} else if (commandWordAliasList !== '') { // As long as the user entered something we should be able to proceed!
validCommandWordAliasList = true;
}
} // End-while (validCommandWordAliasList === false)
commandAliasDataStructure[commandWord] = commandWordAliasList;
validCommandInput = true;
} // End-if (commandWord !== '')
} // End-for (const element of camelCaseCommandNameArray)
} else if (inputData.length === 2) {
try {
commandAliasDataStructure = JSON.parse(inputData[1]);
validCommandInput = true;
} catch (err) {
// PARSER ERROR:
console.log(msg.cPARSER_ERROR + err.message);
// INVALID COMMAND INPUT: Please enter valid command data when trying to call with parameters.
console.log(msg.ccommandAliasGeneratorMessage5);
returnData[1] = msg.ccommandAliasGeneratorMessage5;
// EXAMPLE: {"constants":"c,const","Generator":"g,gen,genrtr","List":"l,lst"}
console.log(msg.ccommandAliasGeneratorMessage2);
}
} else {
// INVALID COMMAND INPUT: Please enter valid command data when trying to call with parameters.
console.log(msg.ccommandAliasGeneratorMessage5);
returnData[1] = msg.ccommandAliasGeneratorMessage5;
// EXAMPLE: {"constants":"c,const","Generator":"g,gen,genrtr","List":"l,lst"}
console.log(msg.ccommandAliasGeneratorMessage2);
}
if (validCommandInput === true) {
// commandAliasDataStructure is:
await loggers.consoleLog(namespacePrefix + functionName, msg.ccommandAliasDataStructureIs + JSON.stringify(commandAliasDataStructure));
// At this point the user should have entered all valid data and we should be ready to proceed.
// Pass the data object to a business rule to do the above task.
returnData[1] = await ruleBroker.processRules([commandAliasDataStructure, ''], [biz.cgenerateCommandAliases]);
} // End-if (validCommandInput === true)
await loggers.consoleLog(namespacePrefix + functionName, msg.creturnDataIs + JSON.stringify(returnData));
await loggers.consoleLog(namespacePrefix + functionName, msg.cEND_Function);
return returnData;
}
export default {
commandSequencer,
workflow,
businessRule,
commandGenerator,
commandAliasGenerator
};