@haystacks/async
Version:
A framework to build any number or any kind of native application or automation solution.
329 lines (317 loc) • 17.3 kB
JavaScript
/**
* @file workflowBroker.js
* @module workflowBroker
* @description Holds all fo the low level functions that manage the workflows,
* system defined workflows, client defined workflows,
* setting the workflow data and getting the workflow data.
* @requires module:loggers
* @requires module:data
* @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 loggers from '../executrix/loggers.js';
import D from '../structures/data.js';
// External imports
import hayConst from '@haystacks/constants';
import path from 'path';
const {bas, msg, sys, wrd} = hayConst;
const baseFileName = path.basename(import.meta.url, path.extname(import.meta.url));
// framework.brokers.workflowBroker.
const namespacePrefix = wrd.cframework + bas.cDot + wrd.cbrokers + bas.cDot + baseFileName + bas.cDot;
/**
* @function addPluginWorkflows
* @description Merges plugin defined workflows with the system defined workflows.
* @param {string} pluginName The name of the current plugin these workflows belong to.
* @param {object} pluginWorkflows A JSON object that contains the plugin workflows that should be merged with the system workflows.
* @return {boolean} True or False to indicate if the merge was successful or not.
* @author Seth Hollingsead
* @date 2022/10/25
*/
async function addPluginWorkflows(pluginName, pluginWorkflows) {
let functionName = addPluginWorkflows.name;
await loggers.consoleLog(namespacePrefix + functionName, msg.cBEGIN_Function);
// pluginName is:
await loggers.consoleLog(namespacePrefix + functionName, msg.cpluginNameIs + pluginName);
// pluginWorkflows is:
await loggers.consoleLog(namespacePrefix + functionName, msg.cpluginWorkflowsIs + JSON.stringify(pluginWorkflows));
let returnData = false;
try {
if (D[sys.cCommandWorkflows][wrd.cPlugins] === undefined) {
D[sys.cCommandWorkflows][wrd.cPlugins] = {};
}
D[sys.cCommandWorkflows][wrd.cPlugins][pluginName] = {};
D[sys.cCommandWorkflows][wrd.cPlugins][pluginName] = pluginWorkflows;
returnData = true;
} catch (err) {
// ERROR: Failure to merge the plugin workflows for plugin:
console.log(msg.cErrorAddPluginWorkflowsMessage01 + pluginName);
console.log(msg.cERROR_Colon + err);
}
await loggers.consoleLog(namespacePrefix + functionName, msg.creturnDataIs + returnData);
await loggers.consoleLog(namespacePrefix + functionName, msg.cEND_Function);
return returnData;
}
/**
* @function getWorkflow
* @description Given the name of the workflow that is being requested,
* get that workflow from the D-data structure workflows data hive.
* @param {string} workflowName The name of the workflow we should get workflow data for.
* @return {string|boolean} The workflow value, which ideally would be a list of commands and command parameters.
* False if no workflow by the specified name was found.
* @author Seth Hollingsead
* @date 2022/02/04
*/
async function getWorkflow(workflowName) {
let functionName = getWorkflow.name;
await loggers.consoleLog(namespacePrefix + functionName, msg.cBEGIN_Function);
// workflowName is:
await loggers.consoleLog(namespacePrefix + functionName, msg.cworkflowNameIs + workflowName);
let workflowValue = false;
let currentWorkflow = await searchWorkflow(D[sys.cCommandWorkflows], workflowName);
await loggers.consoleLog(namespacePrefix + functionName, msg.ccurrentWorkflowIs + JSON.stringify(currentWorkflow));
workflowValue = currentWorkflow;
// workflowValue is:
await loggers.consoleLog(namespacePrefix + functionName, msg.cworkflowValueIs + JSON.stringify(workflowValue));
await loggers.consoleLog(namespacePrefix + functionName, msg.cEND_Function);
return workflowValue;
}
/**
* @function doesWorkflowExist
* @description Uses the recursive searchWorkflow function to determine if the workflow can be found in the workflow data structure.
* @param {string} workflowName The name of the workflow that should be searched for.
* @return {boolean} True or False to indicate if the workflow already exists or not.
* @author Seth Hollingsead
* @date 2022/05/24
*/
async function doesWorkflowExist(workflowName) {
let functionName = doesWorkflowExist.name;
await loggers.consoleLog(namespacePrefix + functionName, msg.cBEGIN_Function);
// workflowName is:
await loggers.consoleLog(namespacePrefix + functionName, msg.cworkflowNameIs + workflowName);
let workflowFound = false;
let workflowSearchResult = await searchWorkflow(D[sys.cCommandWorkflows], workflowName);
if (workflowSearchResult) {
workflowFound = true;
}
// workflowFound is:
await loggers.consoleLog(namespacePrefix + functionName, msg.cworkflowFoundIs + workflowFound);
await loggers.consoleLog(namespacePrefix + functionName, msg.cEND_Function);
return workflowFound;
}
/**
* @function doesWorkflowExistInWorkflowData
* @description Searches through a data structure to determine if the specified workflow exists within it.
* @param {object} workflowData The workflow data structure that should be searched for the specified workflow.
* @param {string} workflowName The name of the workflow that should be searched for in the workflow data structure.
* @return {boolean} True or False to indicate if the workflow was found or not.
*/
async function doesWorkflowExistInWorkflowData(workflowData, workflowName) {
let functionName = doesWorkflowExist.name;
await loggers.consoleLog(namespacePrefix + functionName, msg.cBEGIN_Function);
// workflowName is:
await loggers.consoleLog(namespacePrefix + functionName, msg.cworkflowNameIs + workflowName);
let workflowFound = false;
let workflowSearchResult = await searchWorkflow(workflowData, workflowName);
if (workflowSearchResult) {
workflowFound = true;
}
// workflowFound is:
await loggers.consoleLog(namespacePrefix + functionName, msg.cworkflowFoundIs + workflowFound);
await loggers.consoleLog(namespacePrefix + functionName, msg.cEND_Function);
return workflowFound;
}
/**
* @function searchWorkflow
* @description This is a recursive function that searches through all the workflow
* data structures and returns the one workflow data object that matches the input name.
* @param {object} allWorkflows The workflow data that should be searched recursively for the specified workflow.
* @param {string} workflowName The name of the workflow that should be found.
* @return {object} The workflow object that corresponds to the input workflow name.
* @author Seth Hollingsead
* @date 2022/05/24
*/
async function searchWorkflow(workflowData, workflowName) {
let functionName = searchWorkflow.name;
await loggers.consoleLog(namespacePrefix + functionName, msg.cBEGIN_Function);
// workflowData is:
await loggers.consoleLog(namespacePrefix + functionName, msg.cworkflowDataIs + JSON.stringify(workflowData));
// workflowName is:
await loggers.consoleLog(namespacePrefix + functionName, msg.cworkflowNameIs + workflowName);
let workflowObject = false;
if (typeof workflowData === wrd.cobject) {
for (let workflowEntity in workflowData) {
// workflowEntity is:
await loggers.consoleLog(namespacePrefix + functionName, msg.cworkflowEntityIs + JSON.stringify(workflowEntity));
// workflow is:
await loggers.consoleLog(namespacePrefix + functionName, msg.cworkflowIs + JSON.stringify(workflowData[workflowEntity]));
if (workflowEntity != workflowName || (workflowEntity === workflowName && typeof workflowData[workflowEntity] === wrd.cobject)) {
let workflowObjectTemp = await searchWorkflow(workflowData[workflowEntity], workflowName);
if (workflowObjectTemp && typeof workflowObjectTemp != wrd.cobject) {
workflowObject = workflowObjectTemp;
break;
} // End-if (workflowObjectTemp != false && typeof workflowObjectTemp != wrd.cobject)
} else if (typeof workflowData[workflowEntity] != wrd.cobject) {
// Needed to make sure it's not a parent entity of the same name.
workflowObject = workflowData[workflowEntity];
break;
}
} // End-for (let workflowEntity in workflowData)
} // End-if (typeof workflowData === wrd.cobject)
// workflowObject is:
await loggers.consoleLog(namespacePrefix + functionName, msg.cworkflowObjectIs + workflowObject);
await loggers.consoleLog(namespacePrefix + functionName, msg.cEND_Function);
return workflowObject;
}
/**
* @function getAllWorkflows
* @description Recursively gets all of the workflows from all levels and flattens them into a single array for printing out to the workflow help command.
* @param {object} workflowDataStructure The workflow data structure that should be recursively flattened into a single array for output.
* If the input is undefined then the main CommandWorkflows data structure will be used at the root of the workflows data hive.
* @return {array<string>|boolean} An array of all the workflows currently loaded into the D-data structure under the CommandWorkflows data hive or
* a boolean True or False to indicate that a leaf-node has been found by the recursive caller.
* @author Seth Hollingsead
* @date 2022/05/25
*/
async function getAllWorkflows(workflowDataStructure) {
let functionName = getAllWorkflows.name;
await loggers.consoleLog(namespacePrefix + functionName, msg.cBEGIN_Function);
// workflowDataStructure is:
await loggers.consoleLog(namespacePrefix + functionName, msg.cworkflowDataStructureIs + JSON.stringify(workflowDataStructure));
let allWorkflows = false;
let internalWorkflowDataStructure;
if (workflowDataStructure === undefined) {
internalWorkflowDataStructure = JSON.parse(JSON.stringify(D[sys.cCommandWorkflows]));
} else {
internalWorkflowDataStructure = JSON.parse(JSON.stringify(workflowDataStructure));
}
await loggers.consoleLog(namespacePrefix + functionName, msg.cinternalWorkflowDataStructureIs + JSON.stringify(internalWorkflowDataStructure));
if (typeof internalWorkflowDataStructure === wrd.cobject) {
allWorkflows = [];
for (let workflowEntity in internalWorkflowDataStructure) {
// workflowEntity is:
await loggers.consoleLog(namespacePrefix + functionName, msg.cworkflowEntityIs + JSON.stringify(workflowEntity));
// workflowDataStructure[workflowEntity] is:
await loggers.consoleLog(namespacePrefix + functionName, msg.cinternalWorkflowDataStructureWorkflowEntityIs + JSON.stringify(internalWorkflowDataStructure[workflowEntity]));
if (typeof internalWorkflowDataStructure[workflowEntity] === wrd.cobject) {
// internalWorkflowDataStructure[workflowEntity] is of type object!
await loggers.consoleLog(namespacePrefix + functionName, msg.cinternalWorkflowDataStructureWorkflowEntityIsOfTypeObject);
let allWorkflowsTemp;
allWorkflowsTemp = await getAllWorkflows(internalWorkflowDataStructure[workflowEntity]);
// allWorkflowsTemp returned from the recursive call is:
await loggers.consoleLog(namespacePrefix + functionName, msg.callWorkflowsTempReturnedFromRecursiveCallIs + JSON.stringify(allWorkflowsTemp));
if (allWorkflowsTemp === false) {
// The recursive call returned false, so push the current entity to the output array!
await loggers.consoleLog(namespacePrefix + functionName, msg.cgetAllWorkflowsMessage01 + msg.cgetAllWorkflowsMessage02);
allWorkflows.push(workflowEntity);
// allWorkflows after pushing to the array 1 is:
await loggers.consoleLog(namespacePrefix + functionName, msg.callWorkflowsAfterPushingToArray1Is + JSON.stringify(allWorkflows));
} else {
allWorkflows = allWorkflows.concat(allWorkflowsTemp);
}
} else {
// workflowEntity is NOT an object type, so push it to the output array!
await loggers.consoleLog(namespacePrefix + functionName, msg.cgetAllWorkflowsMessage03 + msg.cgetAllWorkflowsMessage04);
allWorkflows.push(workflowEntity);
// allWorkflows after pushing to the array 2 is:
await loggers.consoleLog(namespacePrefix + functionName, msg.callWorkflowsAfterPushingToArray2Is + JSON.stringify(allWorkflows));
}
} // End-for (let workflowEntity in internalWorkflowDataStructure)
} // End-if (typeof workflowDataStructure === wrd.cobject)
// workflow is:
await loggers.consoleLog(namespacePrefix + functionName, msg.cworkflowIs + JSON.stringify(allWorkflows));
await loggers.consoleLog(namespacePrefix + functionName, msg.cEND_Function);
return allWorkflows;
}
/**
* @function getWorkflowNamespaceDataObject
* @description Recursively scans through the entire workflow metaData data structure looking for an object that matches the input namespace name.
* When that namespace is found, the entire object is returned.
* @param {object} workflowDataStructure The workflow data structure that should be recursively searched for the namespace specified.
* If the input is undefined then the main CommandWorkflows data structure will be used at the root of the workflows data hive.
* @param {string} namespaceToFind The namespace to look for in the workflow metaData data structure.
* @return {object|boolean} The namespace object if it is found, or False if the namespace object was not found.
* @author Seth Hollingsead
* @date 2022/05/25
*/
async function getWorkflowNamespaceDataObject(workflowDataStructure, namespaceToFind) {
let functionName = getWorkflowNamespaceDataObject.name;
await loggers.consoleLog(namespacePrefix + functionName, msg.cBEGIN_Function);
// workflowDataStructure is:
await loggers.consoleLog(namespacePrefix + functionName, msg.cworkflowDataStructureIs + JSON.stringify(workflowDataStructure));
// namespaceToFind is:
await loggers.consoleLog(namespacePrefix + functionName, msg.cnamespaceToFindIs + namespaceToFind);
let workflowNamespaceObject = false;
if (workflowDataStructure === undefined) {
workflowDataStructure = D[sys.cCommandWorkflows];
}
for (let workflowEntity in workflowDataStructure) {
// workflowEntity is:
await loggers.consoleLog(namespacePrefix + functionName, msg.cworkflowEntityIs + JSON.stringify(workflowEntity));
// workflowDataStructure[workflowEntity] is:
await loggers.consoleLog(namespacePrefix + functionName, msg.cworkflowDataStructureWorkflowEntityIs + JSON.stringify(workflowDataStructure[workflowEntity]));
if (workflowEntity === namespaceToFind) {
workflowNamespaceObject = workflowDataStructure[workflowEntity];
break;
} else if (typeof workflowDataStructure[workflowEntity] === wrd.cobject) {
// Search recursively
let workflowTempObject = await getWorkflowNamespaceDataObject(workflowDataStructure[workflowEntity], namespaceToFind);
if (workflowTempObject) {
// Then we must have found the namespace object we were looking for in the recursion call.
// Just return it, and skip out of the loop.
workflowNamespaceObject = workflowTempObject;
break;
}
}
} // End-for (let workflowEntity in workflowDataStructure)
// workflowNamespaceObject is:
await loggers.consoleLog(namespacePrefix + functionName, msg.cworkflowNamespaceObjectIs + JSON.stringify(workflowNamespaceObject));
await loggers.consoleLog(namespacePrefix + functionName, msg.cEND_Function);
return workflowNamespaceObject;
}
/**
* @function removePluginWorkflows
* @description Parses through the workflows and finds the workflows associated with the named plugin.
* Then removes that data shredding it from existence at the edge of a black hole.
* @param {string} pluginName The name of the plugin that should have its workflows removed from the D-data structure.
* @return {boolean} True or False to indicate if the removal of the data was completed successfully or not.
* @author Seth Hollingsead
* @date 2023/02/01
*/
async function removePluginWorkflows(pluginName) {
let functionName = removePluginWorkflows.name;
await loggers.consoleLog(namespacePrefix + functionName, msg.cBEGIN_Function);
// pluginName is:
await loggers.consoleLog(namespacePrefix + functionName, msg.cpluginNameIs + pluginName);
let returnData = false;
let allPluginsWorkflowData = D[sys.cCommandWorkflows][wrd.cPlugins];
if (allPluginsWorkflowData) {
try {
delete allPluginsWorkflowData[pluginName];
returnData = true;
} catch (err) {
// ERROR: Unable to remove the plugin workflows for the specified plugin:
console.log(msg.cremovePluginWorkflowsMessage01 + pluginName);
// ERROR:
console.log(msg.cerrorMessage + err.message);
}
} else {
// ERROR: Unable to locate the plugins workflow data. Plugin:
console.log(msg.cremovePluginWorkflowsMessage02 + pluginName);
}
await loggers.consoleLog(namespacePrefix + functionName, msg.creturnDataIs + returnData);
await loggers.consoleLog(namespacePrefix + functionName, msg.cEND_Function);
return returnData;
}
export default {
addPluginWorkflows,
getWorkflow,
doesWorkflowExist,
doesWorkflowExistInWorkflowData,
searchWorkflow,
getAllWorkflows,
getWorkflowNamespaceDataObject,
removePluginWorkflows
};