UNPKG

@haystacks/async

Version:

A framework to build any number or any kind of native application or automation solution.

513 lines (497 loc) 31 kB
/** * @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 };