UNPKG

@haystacks/async

Version:

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

830 lines (802 loc) 47 kB
/** * @file system.js * @module system * @description Contains all of the system level commands. * @requires module:commandBroker * @requires module:ruleBroker * @requires module:workflowBroker * @requires module:configurator * @requires module:loggers * @requires module:data * @requires module:stack * @requires {@link https://www.npmjs.com/package/@haystacks/constants|@haystacks/constants} * @requires {@link https://www.npmjs.com/package/figlet|figlet} * @requires {@link https://www.npmjs.com/package/path|path} * @author Seth Hollingsead * @date 2022/04/20 * @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 stack from '../../structures/stack.js'; // External imports import hayConst from '@haystacks/constants'; import figlet from 'figlet'; import path from 'path'; const {bas, biz, cfg, msg, sys, wrd} = hayConst; const baseFileName = path.basename(import.meta.url, path.extname(import.meta.url)); // framework.commandsBlob.commands.system. const namespacePrefix = wrd.cframework + bas.cDot + sys.ccommandsBlob + bas.cDot + wrd.ccommands + bas.cDot + baseFileName + bas.cDot; /** * @function echoCommand * @description Returns the input as the output without any changes. * @param {array<boolean|string|integer>} inputData String that should be echoed. * inputData[0] === 'echoCommand' * @param {string} inputMetaData Not used for this business rule. * @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/04 */ async function echoCommand(inputData, inputMetaData) { let functionName = echoCommand.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 = ''; if (inputData) { inputData.shift(); console.log(inputData.join(bas.cSpace)); returnData[1] = inputData.join(bas.cSpace); } else { // Nothing to echo. errorMessage = msg.cNothingToEcho; 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 exit * @description Returns false so the entire application can exit. * @param {array<boolean|string|integer>} inputData Not used for this command. * inputData[0] === 'exit' * @param {string} inputMetaData Not used for this command. * @return {array<boolean,string|integer|boolean|object|array>} An array with a boolean False value to * indicate if the application exit, followed by the command output. * @author Seth Hollingsead * @date 2022/02/04 */ async function exit(inputData, inputMetaData) { let functionName = exit.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 = [false, true]; await loggers.consoleLog(namespacePrefix + functionName, msg.creturnDataIs + JSON.stringify(returnData)); await loggers.consoleLog(namespacePrefix + functionName, msg.cEND_Function); return returnData; } /** * @function version * @description Displays the current version number for the current application. * @param {array<boolean|string|integer>} inputData Not used for this command. * inputData[0] = 'version' * inputData[1] === 'application|framework' (optional) * @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/04 */ async function version(inputData, inputMetaData) { let functionName = version.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 configVersion = ''; let appContext = ''; if (inputData.length === 2) { appContext = inputData[1]; if (appContext.toUpperCase() === wrd.cAPPLICATION) { configVersion = await configurator.getConfigurationSetting(wrd.csystem, sys.cApplicationVersionNumber); } else if (appContext.toUpperCase() === wrd.cFRAMEWORK) { configVersion = await configurator.getConfigurationSetting(wrd.csystem, sys.cFrameworkVersionNumber); } else if (appContext.toUpperCase().includes(wrd.cPLUGIN)) { configVersion = await configurator.getConfigurationSetting(wrd.csystem, sys.cPluginVersionNumber); } else { configVersion = await configurator.getConfigurationSetting(wrd.csystem, sys.cApplicationVersionNumber); } } else { configVersion = await configurator.getConfigurationSetting(wrd.csystem, sys.cApplicationVersionNumber); } console.log(configVersion); returnData[1] = configVersion; await loggers.consoleLog(namespacePrefix + functionName, msg.creturnDataIs + JSON.stringify(returnData)); await loggers.consoleLog(namespacePrefix + functionName, msg.cEND_Function); return returnData; } /** * @function about * @description Displays the message about the current application. * @param {array<boolean|string|integer>} inputData Not used for this command. * inputData[0] === 'about' * inputData[1] === 'application|framework' (optional) * @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/04 */ async function about(inputData, inputMetaData) { let functionName = about.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 configDescription = ''; let appContext = ''; if (inputData.length === 2) { appContext = inputData[1]; if (appContext.toUpperCase() === wrd.cAPPLICATION) { configDescription = await configurator.getConfigurationSetting(wrd.csystem, sys.cApplicationDescription); } else if (appContext.toUpperCase() === wrd.cFRAMEWORK) { configDescription = await configurator.getConfigurationSetting(wrd.csystem, sys.cFrameworkDescription); } else if (appContext.toUpperCase().includes(wrd.cPLUGIN)) { configDescription = await configurator.getConfigurationSetting(wrd.csystem, sys.cPluginDescription); } else { configDescription = await configurator.getConfigurationSetting(wrd.csystem, sys.cApplicationDescription); } } else { configDescription = await configurator.getConfigurationSetting(wrd.csystem, sys.cApplicationDescription); } console.log(configDescription); returnData[1] = configDescription; await loggers.consoleLog(namespacePrefix + functionName, msg.creturnDataIs + JSON.stringify(returnData)); await loggers.consoleLog(namespacePrefix + functionName, msg.cEND_Function); return returnData; } /** * @function name * @description Displays the name of the current application in standard font format, nothing special. * Optional argument to output in figlet font. * @param {array<boolean|string|integer>} inputData An array that could really contain anything depending * on what the user entered, but the function converts and filters out for a boolean * True or False value internally to the function. * inputData[0] === 'name' * inputData[1] === 'application|framework' (optional) * inputData[2] === 'true|false' (optional) * @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/04 */ async function name(inputData, inputMetaData) { let functionName = name.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 reportedName = ''; let figletFont = ''; let appContext = ''; let useFancyFont = false; if (inputData.length === 2) { appContext = inputData[1]; } // End-if (inputData.length === 2) if (inputData.length === 3) { appContext = inputData[1]; useFancyFont = await ruleBroker.processRules([inputData[2], ''], [biz.cstringToDataType]); } // End-if (inputData.length === 3) if (appContext !== '') { if (appContext.toUpperCase() === wrd.cAPPLICATION) { reportedName = await configurator.getConfigurationSetting(wrd.csystem, sys.cApplicationName); } else if (appContext.toUpperCase() === wrd.cFRAMEWORK) { reportedName = await configurator.getConfigurationSetting(wrd.csystem, sys.cFrameworkName); } else if (appContext.toUpperCase().includes(wrd.cPLUGIN)) { reportedName = await configurator.getConfigurationSetting(wrd.csystem, sys.cPluginName); } else { reportedName = await configurator.getConfigurationSetting(wrd.csystem, sys.cApplicationName); } } else { reportedName = await configurator.getConfigurationSetting(wrd.csystem, sys.cApplicationName); } if (useFancyFont === true) { figletFont = await configurator.getConfigurationSetting(wrd.csystem, cfg.cfigletFont); console.log(figlet.textSync(reportedName, {font: figletFont, horizontalLayout: wrd.cfull})); } else { console.log(reportedName); } returnData[1] = reportedName; await loggers.consoleLog(namespacePrefix + functionName, msg.creturnDataIs + JSON.stringify(returnData)); await loggers.consoleLog(namespacePrefix + functionName, msg.cEND_Function); return returnData; } /** * @function clearScreen * @description Clears all data from the console cache by printing a bunch of blank lines to the screen. * @param {string} inputData Not used for this command. * @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/04 */ // eslint-disable-next-line no-unused-vars async function clearScreen(inputData, inputMetaData) { let functionName = clearScreen.name; await loggers.consoleLog(namespacePrefix + functionName, msg.cBEGIN_Function); // loggers.consoleLog(namespacePrefix + functionName, msg.cinputDataIs + JSON.stringify(inputData)); // loggers.consoleLog(namespacePrefix + functionName, msg.cinputMetaDataIs + JSON.stringify(inputMetaData)); let returnData = [true, {}]; // console.clear(); // This will clear the screen, but not the cache, you can still scroll up and see the previous commands. // process.stdout.write('\u001B[2J\u-001B[0;0f'); // Same as above. // eslint-disable-next-line no-undef process.stdout.write('\u001b[H\u001b[2J\u001b[3J'); returnData[1] = true; await loggers.consoleLog(namespacePrefix + functionName, msg.creturnDataIs + JSON.stringify(returnData)); await loggers.consoleLog(namespacePrefix + functionName, msg.cEND_Function); return returnData; } /** * @function help * @description Displays all the information about all of the commands in the system, * including both system defined commands and client defined commands. * @param {array<boolean|string|integer>} inputData An array that could possibly include the name of this command, * and a list of top-level command data structure data types to print help for. * That way we can parameterize and optimize the help to print commands specific to the Haystacks platform, * the host application, loaded plugins, or various combinations of these. * inputData[0] = 'help' * inputData[1] = Could be a coma-separated string list of command catagories to get help for. * inputData[n] = Could be additional list of command catagories to get help for if the user entered a space-separated list. * Options are: Framework,Platform,Application,App,Plugins,Plugin * @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 */ // eslint-disable-next-line no-unused-vars async function help(inputData, inputMetaData) { let functionName = help.name; await loggers.consoleLog(namespacePrefix + functionName, msg.cBEGIN_Function); let returnData = [true, []]; let commandNamespaceTypesInputArray = []; // Use this to process any inputs the user may have entered. let commandNamespaceTypesConfirmedArray = []; // Use this once we've confirmed valid user entry for inputs given. let validUserEntry = false; let errorMessage = ''; let namespaceAllCommandsDataObject = []; let validCommandNamespaceTypes = [wrd.cFramework, wrd.cApplication, wrd.cPlugins]; // Process user input(s). if (Array.isArray(inputData) && inputData.length === 2) { // The user entered only 1 parameter namespace, but that could actually be a coma-separated list. // inputData.length is: await loggers.consoleLog(namespacePrefix + functionName, msg.cinputDataLengthIs + inputData.length); if (inputData[1].includes(bas.cComa)) { commandNamespaceTypesInputArray = inputData[1].split(bas.cComa); } else if (inputData[1].includes(bas.cSemiColon)) { commandNamespaceTypesInputArray = inputData[1].split(bas.cSemiColon); } else if (inputData[1].includes(bas.cForwardSlash)) { commandNamespaceTypesInputArray = inputData[1].split(bas.cForwardSlash); } else if (inputData[1].includes(bas.cBackSlash)) { commandNamespaceTypesInputArray = inputData[1].split(bas.cBackSlash); } else { // shift the data1! await loggers.consoleLog(namespacePrefix + functionName, msg.cshiftData1); inputData.shift(); commandNamespaceTypesInputArray = inputData; } } else if (Array.isArray(inputData) && inputData.length > 2) { // shift the data2! await loggers.consoleLog(namespacePrefix + functionName, msg.cshiftData2); inputData.shift(); commandNamespaceTypesInputArray = inputData; } // commandNamespaceTypesInputArray is: await loggers.consoleLog(namespacePrefix + functionName, msg.ccommandNamespaceTypesInputArrayIs + JSON.stringify(commandNamespaceTypesInputArray)); // This is where we need to process the array of inputs to normalize them to the command types available by the system, // or run a generic search to find the command namespace alias data. // Available official types are: Framework,Platform,Application,App,Plugins,Plugin if (commandNamespaceTypesInputArray.length > 0) { for (let commandNamespaceEntityKey in commandNamespaceTypesInputArray) { let commandNamespaceEntity = commandNamespaceTypesInputArray[commandNamespaceEntityKey] if (commandNamespaceEntity.toUpperCase().trim() === wrd.cFRAMEWORK || commandNamespaceEntity.toUpperCase().trim() === wrd.cPLATFORM) { commandNamespaceTypesConfirmedArray.push(wrd.cFramework); } else if (commandNamespaceEntity.toUpperCase().trim() === wrd.cAPPLICATION || commandNamespaceEntity.toUpperCase().trim() === wrd.cAPP) { commandNamespaceTypesConfirmedArray.push(wrd.cApplication); } else if (commandNamespaceEntity.toUpperCase().trim() === wrd.cPLUGINS || commandNamespaceEntity.toUpperCase().trim() === wrd.cPLUGIN) { commandNamespaceTypesConfirmedArray.push(wrd.cPlugins); } else if (commandNamespaceEntity === '') { // Just ignore it! } else { // Not sure what the user may have entered here, but it could be some valid namespace, so just add it to the array, and assume best intent. // If its going to error out, then it will print an error some place else. commandNamespaceTypesConfirmedArray.push(commandNamespaceEntity); } } // End-for (let commandNamespaceEntity in commandNamespaceTypesInputArray) if (commandNamespaceTypesConfirmedArray.length > 0) { validUserEntry = true; } } else { // User didn't enter any parameters at all....just gather them all! commandNamespaceTypesConfirmedArray = validCommandNamespaceTypes; validUserEntry = true; } // commandNamespaceTypesConfirmedArray is: await loggers.consoleLog(namespacePrefix + functionName, msg.ccommandNamespaceTypesConfirmedArrayIs + JSON.stringify(commandNamespaceTypesConfirmedArray)); if (validUserEntry) { if (commandNamespaceTypesConfirmedArray.length > 0) { for (const commandNamespaceTypeConfirmedKey in commandNamespaceTypesConfirmedArray) { const commandNamespaceTypeConfirmedEntity = commandNamespaceTypesConfirmedArray[commandNamespaceTypeConfirmedKey]; if (commandNamespaceTypeConfirmedEntity === wrd.cFramework) { // processing framework commands await loggers.consoleLog(namespacePrefix + functionName, msg.cprocessingFrameworkCommands); let frameworkCommandAliases = await commandBroker.getAllCommandAliasData(D[sys.cCommandsAliases][wrd.cFramework]); if (frameworkCommandAliases) { if (Object.keys(namespaceAllCommandsDataObject).length != 0) { // frameworkCommandAliases is: await loggers.consoleLog(namespacePrefix + functionName, msg.cframeworkCommandAliasesIs + JSON.stringify(frameworkCommandAliases)); namespaceAllCommandsDataObject = await ruleBroker.processRules([namespaceAllCommandsDataObject, frameworkCommandAliases], [biz.cobjectDeepMerge]); } else { namespaceAllCommandsDataObject = frameworkCommandAliases; } } // End-if (frameworkCommandAliases) } else if (commandNamespaceTypeConfirmedEntity === wrd.cApplication) { // processing application commands await loggers.consoleLog(namespacePrefix + functionName, msg.cprocessingApplicationCommands); let applicationCommandAliases = await commandBroker.getAllCommandAliasData(D[sys.cCommandsAliases][wrd.cApplication]); if (applicationCommandAliases) { if (Object.keys(namespaceAllCommandsDataObject).length != 0) { // applicationCommandAliases is: await loggers.consoleLog(namespacePrefix + functionName, msg.capplicationCommandAliasesIs + JSON.stringify(applicationCommandAliases)); namespaceAllCommandsDataObject = await ruleBroker.processRules([namespaceAllCommandsDataObject, applicationCommandAliases], [biz.cobjectDeepMerge]); } else { namespaceAllCommandsDataObject = applicationCommandAliases; } } // End-if (applicationCommandAliases) } else if (commandNamespaceTypeConfirmedEntity === wrd.cPlugins) { if (await configurator.getConfigurationSetting(wrd.csystem, cfg.cenablePluginLoader)) { // processing plugins commands await loggers.consoleLog(namespacePrefix + functionName, msg.cprocessingPluginsCommands); let pluginsCommandAliases = await commandBroker.getAllCommandAliasData(D[sys.cCommandsAliases][wrd.cPlugins]); if (pluginsCommandAliases) { if (Object.keys(namespaceAllCommandsDataObject).length != 0) { // pluginsCommandAliases is: await loggers.consoleLog(namespacePrefix + functionName, msg.cpluginsCommandAliasesIs + JSON.stringify(pluginsCommandAliases)); namespaceAllCommandsDataObject = await ruleBroker.processRules([namespaceAllCommandsDataObject, pluginsCommandAliases], [biz.cobjectDeepMerge]); } else { namespaceAllCommandsDataObject = pluginsCommandAliases; } } // End-if (pluginsCommandAliases) } // End-if (await configurator.getConfigurationSetting(wrd.csystem, cfg.cenablePluginLoader)) } else { // calling getCommandNamespaceDataObject() function, // because the user entered some namespace we should look for! // processing commands for: await loggers.consoleLog(namespacePrefix + functionName, msg.cprocessingCommandsFor + commandNamespaceTypeConfirmedEntity); let namespaceCommandsData = await commandBroker.getCommandNamespaceDataObject(undefined, commandNamespaceTypeConfirmedEntity); // namespaceCommandsData is: await loggers.consoleLog(namespacePrefix + functionName, msg.cnamespaceCommandsDataIs + JSON.stringify(namespaceCommandsData)); if (namespaceCommandsData === false) { // ERROR: The command namespace was not found. // Please make sure you have entered the correct name and try again. errorMessage = msg.chelpCommandMessage01 + bas.cSpace + msg.chelpCommandMessage02; console.log(errorMessage); } else { // NOW call getAllCommandAliasData with the above found data! await loggers.consoleLog(namespacePrefix + functionName, msg.chelpCommandMessage03); let extraUserEnteredCommandAliases = await commandBroker.getAllCommandAliasData(namespaceCommandsData); if (extraUserEnteredCommandAliases) { if (Object.keys(namespaceAllCommandsDataObject).length != 0) { // extraUserEnteredCommandAliases is: await loggers.consoleLog(namespacePrefix + functionName, msg.cextraUserEnteredCommandAliasesIs + JSON.stringify(extraUserEnteredCommandAliases)); namespaceAllCommandsDataObject = await ruleBroker.processRules([namespaceAllCommandsDataObject, extraUserEnteredCommandAliases], [biz.cobjectDeepMerge]); } else { namespaceAllCommandsDataObject = extraUserEnteredCommandAliases; } } // End-if (extraUserEnteredCommandAliases) } } // namespaceAllCommandsDataObject is: await loggers.consoleLog(namespacePrefix + functionName, msg.cnamespaceAllCommandsDataObjectIs + JSON.stringify(namespaceAllCommandsDataObject)); } // End-for (const commandNamespaceTypeConfirmedKey in commandNamespaceTypesConfirmedArray) } else { // Should never get here, but just in case we do, protect the system and get all the command alias data so the command can still finish successfully. namespaceAllCommandsDataObject = await commandBroker.getAllCommandAliasData(D[sys.cCommandsAliases]); } returnData[1] = await ruleBroker.processRules([namespaceAllCommandsDataObject, ''], [biz.carrayDeepClone]); // namespaceAllCommandsDataObject is: await loggers.consoleLog(namespacePrefix + functionName, msg.cnamespaceAllCommandsDataObjectIs + JSON.stringify(namespaceAllCommandsDataObject[0])); await loggers.consoleTableLog(baseFileName + bas.cDot + functionName, namespaceAllCommandsDataObject[0], [wrd.cName, wrd.cDescription]); } await loggers.consoleLog(namespacePrefix + functionName, msg.creturnDataIs + JSON.stringify(returnData)); await loggers.consoleLog(namespacePrefix + functionName, msg.cEND_Function); return returnData; } /** * @function workflowHelp * @description Displays all the information about all the workflows in the system, * including both system defined workflows & client defined workflows. * @param {array<boolean|string|integer>} inputData An array that could possibly include the name of this command, * and a list of top-level workflow catagories data structures to be printed. * That way we can parameterize and optimize the workflow help to print workflows specific to the Haystacks platform, * the host application, loaded plugins, or various combinations of these. * inputData[0] = 'workflowHelp' * inputData[1] = Could be a coma-separated string list of command catagories to get workflow help for. * inputData[n] = Could be additional list of command catagories to get help for if the user entered a space-separated list. * Options are: Framework,Platform,Application,App,Plugins,Plugin * @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 workflowHelp(inputData, inputMetaData) { let functionName = workflowHelp.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 workflowNamespaceTypesInputArray = []; // Use this to process any inputs the user may have entered. let workflowNamespaceTypesConfirmedArray = []; // Use this once we've confirmed vaid user entry for inputs given. let validUserEntry = false; let namespaceAllWorkflowsDataObject = []; let validWorkflowsNamespaceTypes = [wrd.cFramework, wrd.cApplication, wrd.cPlugins]; // Process user input(s). if (Array.isArray(inputData) && inputData.length === 2) { // The user entered only 1 parameter namespace, but that could actually be a coma-separated list. // inputData.length is: await loggers.consoleLog(namespacePrefix + functionName, msg.cinputDataLengthIs + inputData.length); if (inputData[1].includes(bas.cComa)) { workflowNamespaceTypesInputArray = inputData[1].split(bas.cComa); } else if (inputData[1].includes(bas.cSemiColon)) { workflowNamespaceTypesInputArray = inputData[1].split(bas.cSemiColon); } else if (inputData[1].includes(bas.cForwardSlash)) { workflowNamespaceTypesInputArray = inputData[1].split(bas.cForwardSlash); } else if (inputData[1].includes(bas.cBackSlash)) { workflowNamespaceTypesInputArray = inputData[1].split(bas.cBackSlash); } else { // shift the data1! await loggers.consoleLog(namespacePrefix + functionName, msg.cshiftData1); inputData.shift(); workflowNamespaceTypesInputArray = inputData; } } else if (Array.isArray(inputData) && inputData.length > 2) { // shift the data2! await loggers.consoleLog(namespacePrefix + functionName, msg.cshiftData2); inputData.shift(); workflowNamespaceTypesInputArray = inputData; } // workflowNamespaceTypesInputArray is: await loggers.consoleLog(namespacePrefix + functionName, msg.cworkflowNamespaceTypesInputArrayIs + JSON.stringify(workflowNamespaceTypesInputArray)); // This is where we need to process the array of inputs to normalize them to the workflow types available by the system, // or run a generic search to find the workflow data. // Available official types are: Framework,Platform,Application,App,Plugins,Plugin if (workflowNamespaceTypesInputArray.length > 0) { for (let workflowNamespaceEntityKey in workflowNamespaceTypesInputArray) { let workflowNamespaceEntity = workflowNamespaceTypesInputArray[workflowNamespaceEntityKey]; if (workflowNamespaceEntity.toUpperCase().trim() === wrd.cFRAMEWORK || workflowNamespaceEntity.toUpperCase().trim() === wrd.cPLATFORM) { workflowNamespaceTypesConfirmedArray.push(wrd.cFramework); } else if (workflowNamespaceEntity.toUpperCase().trim() === wrd.cAPPLICATION || workflowNamespaceEntity.toUpperCase().trim() === wrd.cAPP) { workflowNamespaceTypesConfirmedArray.push(wrd.cApplication); } else if (workflowNamespaceEntity.toUpperCase().trim() === wrd.cPLUGINS || workflowNamespaceEntity.toUpperCase().trim() === wrd.cPLUGIN) { workflowNamespaceTypesConfirmedArray.push(wrd.cPlugins); } else if (workflowNamespaceEntity === '') { // Just ignore it! } else { // Not sure what the user may have entered here, but it could be some valid namespace, so just add it to the array, and assume best intent. // If its going to error out, then it will print an error some place else. workflowNamespaceTypesConfirmedArray.push(workflowNamespaceEntity); } } // End-for (let workflowNamespaceEntityKey in workflowNamespaceTypesInputArray) if (workflowNamespaceTypesConfirmedArray.length > 0) { validUserEntry = true; } } else { // User didn't enter any parameters at al....just gather them all! workflowNamespaceTypesConfirmedArray = validWorkflowsNamespaceTypes; validUserEntry = true; } // workflowNamespaceTypesConfirmedArray is: await loggers.consoleLog(namespacePrefix + functionName, msg.cworkflowNamespaceTypesConfirmedArrayIs + JSON.stringify(workflowNamespaceTypesConfirmedArray)); if (validUserEntry) { if (workflowNamespaceTypesConfirmedArray.length > 0) { for (const workflowNamespaceTypeConfirmedKey in workflowNamespaceTypesConfirmedArray) { const workflowNamespaceTypeConfirmedEntity = workflowNamespaceTypesConfirmedArray[workflowNamespaceTypeConfirmedKey]; if (workflowNamespaceTypeConfirmedEntity === wrd.cFramework) { // processing framework workflows await loggers.consoleLog(namespacePrefix + functionName, msg.cprocessingFrameworkWorkflows); let frameworkWorkflows = await workflowBroker.getAllWorkflows(D[sys.cCommandWorkflows][wrd.cFramework]); if (frameworkWorkflows) { if (namespaceAllWorkflowsDataObject.length != 0) { // frameworkWorkflows is: await loggers.consoleLog(namespacePrefix + functionName, msg.cframeworkWorkflowsIs + JSON.stringify(frameworkWorkflows)); namespaceAllWorkflowsDataObject.push(...frameworkWorkflows); } else { namespaceAllWorkflowsDataObject = frameworkWorkflows; } } // End-if (frameworkWorkflows) } else if (workflowNamespaceTypeConfirmedEntity === wrd.cApplication) { // processing application workflows await loggers.consoleLog(namespacePrefix + functionName, msg.cprocessingApplicationWorkflows); let applicationWorkflows = await workflowBroker.getAllWorkflows(D[sys.cCommandWorkflows][wrd.cApplication]); if (applicationWorkflows) { if (namespaceAllWorkflowsDataObject.length != 0) { // applicationWorkflows is: await loggers.consoleLog(namespacePrefix + functionName, msg.capplicationWorkflowsIs + JSON.stringify(applicationWorkflows)); namespaceAllWorkflowsDataObject.push(...applicationWorkflows); } else { namespaceAllWorkflowsDataObject = applicationWorkflows; } } // End-if (applicationWorkflows) } else if (workflowNamespaceTypeConfirmedEntity === wrd.cPlugins) { if (await configurator.getConfigurationSetting(wrd.csystem, cfg.cenablePluginLoader)) { // processing plugins workflows await loggers.consoleLog(namespacePrefix + functionName, msg.cprocessingPluginsWorkflows); let pluginWorkflows = await workflowBroker.getAllWorkflows(D[sys.cCommandWorkflows][wrd.cPlugins]); if (pluginWorkflows) { if (namespaceAllWorkflowsDataObject.length != 0) { // pluginWorkflows is: await loggers.consoleLog(namespacePrefix + functionName, msg.cpluginWorkflowsIs + JSON.stringify(pluginWorkflows)); namespaceAllWorkflowsDataObject.push(...pluginWorkflows); } else { namespaceAllWorkflowsDataObject = pluginWorkflows; } } // End-if (pluginWorkflows) } // End-if (await configurator.getConfigurationSetting(wrd.csystem, cfg.cenablePluginLoader)) } else { // calling getWorkflowNamespaceDataObject() function, // because the user entered some namespace we should look for! // processing workflows for: await loggers.consoleLog(namespacePrefix + functionName, msg.cprocessingWorkflowsFor + workflowNamespaceTypeConfirmedEntity); let namespaceWorkflowData = await workflowBroker.getWorkflowNamespaceDataObject(undefined, workflowNamespaceTypeConfirmedEntity); // namespaceWorkflowData is: await loggers.consoleLog(namespacePrefix + functionName, msg.cnamespaceWorkflowDataIs + JSON.stringify(namespaceWorkflowData)); if (namespaceWorkflowData === false) { // ERROR: The workflow namespace was not found. // Please make sure you have entered the correct name and try again. errorMessage = msg.cworkflowHelpCommandMessage01 + bas.cSpace + msg.chelpCommandMessage02; console.log(errorMessage); } else { // NOW call getAllWorkflows with the above found data! await loggers.consoleLog(namespacePrefix + functionName, msg.cworkfowHelpMessage03); let extraUserEnteredWorkflows = await workflowBroker.getAllWorkflows(namespaceWorkflowData); if (extraUserEnteredWorkflows) { if (namespaceAllWorkflowsDataObject.length != 0) { // extraUserEnteredWorkflows is: await loggers.consoleLog(namespacePrefix + functionName, msg.cextraUserEnteredWorkflowsIs + JSON.stringify(extraUserEnteredWorkflows)); // namespaceAllWorkflowsDataObject = await ruleBroker.processRules([namespaceAllWorkflowsDataObject, extraUserEnteredWorkflows], [biz.cobjectDeepMerge]); namespaceAllWorkflowsDataObject.push(...extraUserEnteredWorkflows); } else { namespaceAllWorkflowsDataObject = extraUserEnteredWorkflows; } } // End-if (extraUserEnteredWorkflows) } } // namespaceAllWorkflowsDataObject is: await loggers.consoleLog(namespacePrefix + functionName, msg.cnamespaceAllWorkflowsDataObjectIs + JSON.stringify(namespaceAllWorkflowsDataObject)); } // End-for (const workflowNamespaceTypeConfirmedKey in workflowNamespaceTypesConfirmedArray) } else { // Should never get here, but just in case we do, protect the system and get all the workflows data so the command can still finish successfully. // just call getAllWorkflows functions with no input, // will return all and print all. namespaceAllWorkflowsDataObject = await workflowBroker.getAllWorkflows(); } returnData[1] = await ruleBroker.processRules([namespaceAllWorkflowsDataObject, ''], [biz.carrayDeepClone]); // namespaceAllWorkflowsDataObject is: await loggers.consoleLog(namespacePrefix + functionName, msg.cnamespaceAllWorkflowsDataObjectIs + JSON.stringify(namespaceAllWorkflowsDataObject)); await loggers.consoleTableLog(baseFileName + bas.cDot + functionName, namespaceAllWorkflowsDataObject); } await loggers.consoleLog(namespacePrefix + functionName, msg.creturnDataIs + JSON.stringify(returnData)); await loggers.consoleLog(namespacePrefix + functionName, msg.cEND_Function); return returnData; } /** * @function printCommands * @description Prints out a RAW dump of the commands data structure, useful for debugging the commands in the live environment. * @param {string} inputData Not used for this command. * @param {string} inputMetaData Not used for this command. * @return {array<boolean,array<string>>} An array with a boolean True or False value to * indicate if the application should exit or not exit, followed by an empty. * @author Seth Hollingsead * @date 2023/11/10 */ async function printCommands(inputData, inputMetaData) { let functionName = printCommands.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, []]; console.log(msg.ccommandsAre, D[wrd.cCommands]); await loggers.consoleLog(namespacePrefix + functionName, msg.creturnDataIs + JSON.stringify(returnData)); await loggers.consoleLog(namespacePrefix + functionName, msg.cEND_Function); return returnData; } /** * @function printBusinessRules * @description Prints out a RAW dump of the business rules data structure, useful for debugging the business rules in the live environment. * @param {string} inputData Not used for this command. * @param {string} inputMetaData Not used for this command. * @return {array<boolean,array<string>>} An array with a boolean True or False value to * indicate if the application should exit or not exit, followed by an empty. * @author Seth Hollingsead * @date 2023/11/10 */ async function printBusinessRules(inputData, inputMetaData) { let functionName = printBusinessRules.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, []]; console.log(msg.cbusinessRulesAre, D[sys.cbusinessRules]); await loggers.consoleLog(namespacePrefix + functionName, msg.creturnDataIs + JSON.stringify(returnData)); await loggers.consoleLog(namespacePrefix + functionName, msg.cEND_Function); return returnData; } /** * @function printUserCommandsLog * @description Prints out the command log of all the commands the user has entered since the start of the application for this instance it was running. * @param {string} inputData Not used for this command. * @param {string} inputMetaData Not used for this command. * @return {array<boolean,array<string>>} An array with a boolean True or False value to * indicate if the application should exit or not exit, followed by an array of strings that is the user entered commands. * @author Seth Hollingsead * @date 2023/02/14 */ async function printUserCommandsLog(inputData, inputMetaData) { let functionName = printUserCommandsLog.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, []]; if (await configurator.getConfigurationSetting(wrd.csystem, cfg.clogUserEnteredCommands) === true) { if (await stack.isEmpty(sys.cUserEnteredCommandLog) === false) { let userEnteredCommandLogArray = await stack.getStackContents(sys.cUserEnteredCommandLog); let userEnteredCommandLog = userEnteredCommandLogArray.join(bas.cComa + bas.cNewLine + bas.cCarriageReturn); returnData[1] = userEnteredCommandLog; console.log(userEnteredCommandLog); } else { // User commands log is empty. console.log(msg.cUserCommandsLogIsEmpty); returnData[1] = ''; } } else { // NOTE: The user entered command log setting is not enabled. // Change the setting logUserEnteredCommands to enable user entered command log data to be captured for printing. console.log(msg.cprintUserCommandLogMessage01 + bas.cSpace + msg.cprintUserCommandLogMessage02); returnData[1] = false; } await loggers.consoleLog(namespacePrefix + functionName, msg.creturnDataIs + JSON.stringify(returnData)); await loggers.consoleLog(namespacePrefix + functionName, msg.cEND_Function); return returnData; } /** * @function printAllCommandsLog * @description Prints out a log of all the commands executed by the system since the start of the application for this instance it was running. * @param {string} inputData Not used for this command. * @param {string} inputMetaData Not used for this command. * @return {array<boolean,array<string>>} An array with a boolean True or False value to * indicate if the application should exit or not exit, followed by an array of strings that is the user entered commands. * @author Seth Hollingsead * @date 2023/02/14 */ async function printAllCommandsLog(inputData, inputMetaData) { let functionName = printAllCommandsLog.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, []]; if (await configurator.getConfigurationSetting(wrd.csystem, cfg.clogAllCommands) === true) { if (await stack.isEmpty(sys.cSystemCommandLog) === false) { let allCommandsLogArray = await stack.getStackContents(sys.cSystemCommandLog); let allCommandsLog = allCommandsLogArray.join(bas.cComa + bas.cNewLine + bas.cCarriageReturn); returnData[1] = allCommandsLog; console.log(allCommandsLog); } else { // All commands log is empty. console.log(msg.cAllCommandsLogIsEmpty); returnData[1] = ''; } } else { // NOTE: The command log setting is not enabled. // Change the setting logAllCommands to enable command log data to be captured for printing. console.log(msg.cprintAllCommandLogMessage01 + bas.cSpace + msg.cprintAllCommandLogMessage02); returnData[1] = false; } await loggers.consoleLog(namespacePrefix + functionName, msg.creturnDataIs + JSON.stringify(returnData)); await loggers.consoleLog(namespacePrefix + functionName, msg.cEND_Function); return returnData; } /** * @function clearUserCommandsLog * @description Wipes out the user command log, destroying all evidence of whatever commands the user has entered. * @param {string} inputData Not used for this command. * @param {string} inputMetaData Not used for this command. * @return {array<boolean,boolean>} An array with a boolean True or False value to * indicate if the application should exit or not exit, followed by another boolean value to indicate if the operation was successful or not. * @author Seth Hollingsead * @date 2023/02/14 */ async function clearUserCommandsLog(inputData, inputMetaData) { let functionName = clearUserCommandsLog.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, []]; if (await configurator.getConfigurationSetting(wrd.csystem, cfg.clogUserEnteredCommands) === true) { if (await configurator.getConfigurationSetting(wrd.csystem, cfg.cenableUserCommandsLogClearing) === true) { returnData[1] = await stack.clearStack(sys.cUserEnteredCommandLog); } else { // NOTE: User commands log clearing setting is not enabled. console.log(msg.cclearUserCommandsLogMessage01); returnData[1] = false; } } else { // NOTE: The user entered command log setting is not enabled. console.log(msg.cprintUserCommandLogMessage01); returnData[1] = false; } await loggers.consoleLog(namespacePrefix + functionName, msg.creturnDataIs + JSON.stringify(returnData)); await loggers.consoleLog(namespacePrefix + functionName, msg.cEND_Function); return returnData; } /** * @function clearAllCommandsLog * @description Wipes out the all commands log, destroying all evidence of whatever commands were executed by the system. * @param {string} inputData Not used for this command. * @param {string} inputMetaData Not used for this command. * @return {array<boolean,boolean>} An array with a boolean True or False value to * indicate if the application should exit or not exit, followed by another boolean value to indicate if the operation was successful or not. * @author Seth Hollingsead * @date 2023/02/14 */ async function clearAllCommandsLog(inputData, inputMetaData) { let functionName = clearAllCommandsLog.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, []]; if (await configurator.getConfigurationSetting(wrd.csystem, cfg.clogAllCommands) === true) { if (await configurator.getConfigurationSetting(wrd.csystem, cfg.cenableAllCommandsLogClearing) === true) { returnData[1] = await stack.clearStack(sys.cSystemCommandLog); } else { // NOTE: All commands log clearing setting is not enabled. console.log(msg.cclearAllCommandsLogMessage01); returnData[1] = false; } } else { // NOTE: The command log setting is not enabled. console.log(msg.cprintAllCommandLogMessage01); returnData[1] = false; } await loggers.consoleLog(namespacePrefix + functionName, msg.creturnDataIs + JSON.stringify(returnData)); await loggers.consoleLog(namespacePrefix + functionName, msg.cEND_Function); return returnData; } export default { echoCommand, exit, version, about, name, clearScreen, help, workflowHelp, printCommands, printBusinessRules, printUserCommandsLog, printAllCommandsLog, clearUserCommandsLog, clearAllCommandsLog };