UNPKG

@haystacks/async

Version:

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

795 lines (749 loc) 73.9 kB
/** * @file warden.js * @module warden * @description Contains all the functions to manage the entire application framework at the highest level. * Also provides an interface to easily manage all the framework features & various functionality from a single entry point. * @requires module:dataBroker * @requires module:ruleBroker * @requires module:chiefCommander * @requires module:chiefConfiguration * @requires module:chiefData * @requires module:chiefPlugin * @requires module:chiefTheme * @requires module:chiefWorkflow * @requires module:configurator * @requires module:loggers * @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 2021/10/15 * @copyright Copyright © 2022-… by Seth Hollingsead. All rights reserved */ // Internal imports import dataBroker from '../brokers/dataBroker.js'; import ruleBroker from '../brokers/ruleBroker.js'; import chiefCommander from './chiefCommander.js'; import chiefConfiguration from './chiefConfiguration.js'; import chiefConstant from './chiefConstant.js'; import chiefData from './chiefData.js'; import chiefPlugin from './chiefPlugin.js'; import chiefTheme from './chiefTheme.js'; import chiefWorkflow from './chiefWorkflow.js'; import configurator from '../executrix/configurator.js'; import loggers from '../executrix/loggers.js'; import stack from '../structures/stack.js'; // eslint-disable-next-line no-unused-vars import D from '../structures/data.js'; // External imports import hayConst from '@haystacks/constants'; import path from 'path'; const {bas, biz, cmd, cfg, gen, msg, sys, wrd} = hayConst; const baseFileName = path.basename(import.meta.url, path.extname(import.meta.url)); // framework.controllers.warden. const namespacePrefix = wrd.cframework + bas.cDot + wrd.ccontrollers + bas.cDot + baseFileName + bas.cDot; /** * @function processRootPath * @description Processes the root path of the application using business rules. * @NOTE: By calling path.resolve(__dirname); This does not return the true root path of the application. * It returns the path to the currently executing file, or the file that was executed first. * which is: C:/Calculator2/Application/Calculator2/ * But what we really need for the root path is just C:/Calculator2/ * @param {string} inputPath The path for the entry point to the framework, ie: main.js * @param {string} actualFrameworkName The name of the framework that the application is expecting to use. * @return {string} The true root path of the application. * @author Seth Hollingsead * @date 2021/10/12 * @NOTE Cannot use the loggers here, because dependency data will have never been loaded. */ async function processRootPath(inputPath, actualFrameworkName) { // let functionName = processRootPath.name; // console.log(`BEGIN ${namespacePrefix}${functionName} function`); // console.log(`inputPath is: ${inputPath}`); await ruleBroker.bootStrapBusinessRules(); await chiefCommander.bootStrapCommands(); let resolvedPath = await ruleBroker.processRules([inputPath, actualFrameworkName], [biz.cparseSystemRootPath]); await dataBroker.setupDataStorage(); resolvedPath = path.normalize(resolvedPath); // console.log(`resolvedPath is: ${resolvedPath}`); // console.log(`END ${namespacePrefix}${functionName} function`); return resolvedPath; } /** * @function initFrameworkSchema * @description Setup all the framework data and configuration settings. * @param {object} configData All of the configuration data that should be parsed as part of the setup process. * @return {void} * @author Seth Hollingsead * @date 2021/10/12 */ async function initFrameworkSchema(configData) { let functionName = initFrameworkSchema.name; // console.log(`BEGIN ${namespacePrefix}${functionName} function`); // console.log(`configData is: ${JSON.stringify(configData)}`); await loggers.consoleLog(namespacePrefix + functionName, msg.cBEGIN_Function); await loggers.consoleLog(namespacePrefix + functionName, msg.cconfigDataIs + JSON.stringify(configData)); const appConfigPath = configData[cfg.cappConfigPath]; const frameworkConfigPath = configData[cfg.cframeworkConfigPath]; await chiefConfiguration.setupConfiguration(appConfigPath, frameworkConfigPath); await configurator.setConfigurationSetting(wrd.csystem, cfg.cschemasLoaded, false); // re-declare the input now that the configuration is setup. await loggers.consoleLog(namespacePrefix + functionName, msg.cBEGIN_Function); await loggers.consoleLog(namespacePrefix + functionName, msg.cconfigDataIs + JSON.stringify(configData)); let getJsonRule = [biz.cgetJsonData]; let applicationMetaDataPathAndFilename = ''; let frameworkMetaDataPathAndFilename = ''; let pluginMetaDataPathAndFilename = ''; let applicationMetaData = {}; let frameworkMetaData = {}; let pluginMetaData = {}; applicationMetaDataPathAndFilename = configData[cfg.cclientMetaDataPath]; frameworkMetaDataPathAndFilename = configData[cfg.cframeworkFullMetaDataPath]; await loggers.consoleLog(namespacePrefix + functionName, msg.capplicationMetaDataPathAndFilenameIs + applicationMetaDataPathAndFilename); await loggers.consoleLog(namespacePrefix + functionName, msg.cframeworkMetaDataPathAndFilenameIs + frameworkMetaDataPathAndFilename); applicationMetaData = await ruleBroker.processRules([applicationMetaDataPathAndFilename, ''], getJsonRule); frameworkMetaData = await ruleBroker.processRules([frameworkMetaDataPathAndFilename, ''], getJsonRule); await loggers.consoleLog(namespacePrefix + functionName, msg.capplicationMetaDataIs + JSON.stringify(applicationMetaData)); await loggers.consoleLog(namespacePrefix + functionName, msg.cframeworkMetaDataIs + JSON.stringify(frameworkMetaData)); if (configData[sys.cPluginName]) { pluginMetaDataPathAndFilename = configData[cfg.cpluginFullMetaDataPath]; await loggers.consoleLog(namespacePrefix + functionName, msg.cpluginMetaDataPathAndFilenameIs + pluginMetaDataPathAndFilename); pluginMetaData = await ruleBroker.processRules([pluginMetaDataPathAndFilename, ''], getJsonRule); await loggers.consoleLog(namespacePrefix + functionName, msg.cpluginMetaDataIs + JSON.stringify(pluginMetaData)); } await configurator.setConfigurationSetting(wrd.csystem, cfg.cclientRootPath, configData[cfg.cclientRootPath]); await configurator.setConfigurationSetting(wrd.csystem, cfg.cappConfigResourcesPath, configData[cfg.cappConfigResourcesPath]); await configurator.setConfigurationSetting(wrd.csystem, cfg.cappConfigReferencePath, configData[cfg.cappConfigReferencePath]); await configurator.setConfigurationSetting(wrd.csystem, cfg.cclientMetaDataPath, configData[cfg.cclientMetaDataPath]); await configurator.setConfigurationSetting(wrd.csystem, cfg.cclientCommandAliasesPath, configData[cfg.cclientCommandAliasesPath]); await configurator.setConfigurationSetting(wrd.csystem, cfg.cclientWorkflowsPath, configData[cfg.cclientWorkflowsPath]); await configurator.setConfigurationSetting(wrd.csystem, cfg.cframeworkRootPath, configData[cfg.cframeworkRootPath]); if (configData[sys.cPluginName]) { await configurator.setConfigurationSetting(wrd.csystem, cfg.cpluginRootPath, configData[cfg.cpluginRootPath]); await configurator.setConfigurationSetting(wrd.csystem, cfg.cpluginReleaseResourcesPath, configData[cfg.cpluginReleaseResourcesPath]); await configurator.setConfigurationSetting(wrd.csystem, cfg.cpluginWorkflowsPath, configData[cfg.cpluginWorkflowsPath]); await configurator.setConfigurationSetting(wrd.csystem, cfg.cpluginCommandAliasesPath, configData[cfg.cpluginCommandAliasesPath]); } await configurator.setConfigurationSetting(wrd.csystem, cfg.cappConfigPath, configData[cfg.cappConfigPath]); await configurator.setConfigurationSetting(wrd.csystem, cfg.cframeworkResourcesPath, configData[cfg.cframeworkResourcesPath]); await configurator.setConfigurationSetting(wrd.csystem, cfg.cframeworkFullMetaDataPath, configData[cfg.cframeworkFullMetaDataPath]); await configurator.setConfigurationSetting(wrd.csystem, cfg.cframeworkConfigPath, configData[cfg.cframeworkConfigPath]); await configurator.setConfigurationSetting(wrd.csystem, cfg.cframeworkThemesPath, configData[cfg.cframeworkThemesPath]); await configurator.setConfigurationSetting(wrd.csystem, cfg.cframeworkSchemasPath, configData[cfg.cframeworkSchemasPath]); await configurator.setConfigurationSetting(wrd.csystem, cfg.capplicationSchemasPath, configData[cfg.capplicationSchemasPath]); await configurator.setConfigurationSetting(wrd.csystem, cfg.cframeworkCommandAliasesPath, configData[cfg.cframeworkCommandAliasesPath]); await configurator.setConfigurationSetting(wrd.csystem, cfg.cframeworkWorkflowsPath, configData[cfg.cframeworkWorkflowsPath]); await loggers.consoleLog(namespacePrefix + functionName, msg.cclientRootPathIs + configData[cfg.cclientRootPath]); await loggers.consoleLog(namespacePrefix + functionName, msg.cappConfigResourcesPathIs + configData[cfg.cappConfigResourcesPath]); await loggers.consoleLog(namespacePrefix + functionName, msg.cappConfigReferencePathIs + configData[cfg.cappConfigReferencePath]); await loggers.consoleLog(namespacePrefix + functionName, msg.cclientMetaDataPathIs + configData[cfg.cclientMetaDataPath]); await loggers.consoleLog(namespacePrefix + functionName, msg.cclientCommandAliasesPathIs + configData[cfg.cclientCommandAliasesPath]); await loggers.consoleLog(namespacePrefix + functionName, msg.cclientWorkflowsPathIs + configData[cfg.cclientWorkflowsPath]); await loggers.consoleLog(namespacePrefix + functionName, msg.cframeworkRootPathIs + configData[cfg.cframeworkRootPath]); if (configData[sys.cPluginName]) { await loggers.consoleLog(namespacePrefix + functionName, msg.cpluginRootPathIs + configData[cfg.cpluginRootPath]); await loggers.consoleLog(namespacePrefix + functionName, msg.cpluginReleaseResourcesPathIs + configData[cfg.cpluginReleaseResourcesPath]); await loggers.consoleLog(namespacePrefix + functionName, msg.cpluginWorkflowsPathIs + configData[cfg.cpluginWorkflowsPath]); await loggers.consoleLog(namespacePrefix + functionName, msg.cpluginCommandAliasesPathIs + configData[cfg.cpluginCommandAliasesPath]); } await loggers.consoleLog(namespacePrefix + functionName, msg.cappConfigPathIs + configData[cfg.cappConfigPath]); await loggers.consoleLog(namespacePrefix + functionName, msg.cframeworkResourcesPathIs + configData[cfg.cframeworkResourcesPath]); await loggers.consoleLog(namespacePrefix + functionName, msg.cframeworkFullMetaDataPathIs + configData[cfg.cframeworkFullMetaDataPath]); await loggers.consoleLog(namespacePrefix + functionName, msg.cframeworkConfigPathIs + configData[cfg.cframeworkConfigPath]); await loggers.consoleLog(namespacePrefix + functionName, msg.cframeworkThemesPathIs + configData[cfg.cframeworkThemesPath]); await loggers.consoleLog(namespacePrefix + functionName, msg.cframeworkSchemasPathIs + configData[cfg.cframeworkSchemasPath]); await loggers.consoleLog(namespacePrefix + functionName, msg.capplicationSchemasPathIs + configData[cfg.capplicationSchemasPath]); await loggers.consoleLog(namespacePrefix + functionName, msg.cframeworkCommandAliasesPathIs + configData[cfg.cframeworkCommandAliasesPath]); await loggers.consoleLog(namespacePrefix + functionName, msg.cframeworkWorkflowsPathIs + configData[cfg.cframeworkWorkflowsPath]); // Make sure the color data gets loaded as well! File: colors.csv (This is used by the colorizer to colorize the fonts for the console output) await chiefData.setupAllCsvData(cfg.cframeworkConfigPath, wrd.ccolors); let applicationMetaDataName = await configurator.getAmbiguousDataElement(applicationMetaData, [wrd.cname, wrd.cName, wrd.cNAME]); let applicationMetaDataVersion = await configurator.getAmbiguousDataElement(applicationMetaData, [wrd.cversion, wrd.cVersion, wrd.cVERSION]); let applicationMetaDataDescription = await configurator.getAmbiguousDataElement(applicationMetaData, [wrd.cdescription, wrd.cDescription, wrd.cDESCRIPTION]); await configurator.setConfigurationSetting(wrd.csystem, sys.cApplicationName, applicationMetaDataName); await configurator.setConfigurationSetting(wrd.csystem, sys.cApplicationVersionNumber, applicationMetaDataVersion); await configurator.setConfigurationSetting(wrd.csystem, sys.cApplicationDescription, applicationMetaDataDescription); await loggers.consoleLog(namespacePrefix + functionName, msg.cApplicationNameIs + applicationMetaDataName); await loggers.consoleLog(namespacePrefix + functionName, msg.cApplicationVersionNumberIs + applicationMetaDataVersion); await loggers.consoleLog(namespacePrefix + functionName, msg.cApplicationDescriptionIs + applicationMetaDataDescription); let frameworkMetaDataName = await configurator.getAmbiguousDataElement(frameworkMetaData, [wrd.cname, wrd.cName, wrd.cNAME]); let frameworkMetaDataVersion = await configurator.getAmbiguousDataElement(frameworkMetaData, [wrd.cversion, wrd.cVersion, wrd.cVERSION]); let frameworkMetaDataDescription = await configurator.getAmbiguousDataElement(frameworkMetaData, [wrd.cdescription, wrd.cDescription, wrd.cDESCRIPTION]); await configurator.setConfigurationSetting(wrd.csystem, sys.cFrameworkName, frameworkMetaDataName); await configurator.setConfigurationSetting(wrd.csystem, sys.cFrameworkVersionNumber, frameworkMetaDataVersion); await configurator.setConfigurationSetting(wrd.csystem, sys.cFrameworkDescription, frameworkMetaDataDescription); await loggers.consoleLog(namespacePrefix + functionName, msg.cFrameworkNameIs + frameworkMetaDataName); await loggers.consoleLog(namespacePrefix + functionName, msg.cFrameworkVersionNumberIs + frameworkMetaDataVersion); await loggers.consoleLog(namespacePrefix + functionName, msg.cFrameworkDescriptionIs + frameworkMetaDataDescription); // Don't forget this could be a plugin, if the build-release is running and building a plugin for release. if (configData[sys.cPluginName]) { let pluginMetaDataName = await configurator.getAmbiguousDataElement(pluginMetaData, [wrd.cname, wrd.cName, wrd.cNAME]); let pluginMetaDataVersion = await configurator.getAmbiguousDataElement(pluginMetaData, [wrd.cversion, wrd.cVersion, wrd.cVERSION]); let pluginMetaDataDescription = await configurator.getAmbiguousDataElement(pluginMetaData, [wrd.cdescription, wrd.cDescription, wrd.cDESCRIPTION]); await configurator.setConfigurationSetting(wrd.csystem, sys.cPluginName, pluginMetaDataName); await configurator.setConfigurationSetting(wrd.csystem, sys.cPluginVersionNumber, pluginMetaDataVersion); await configurator.setConfigurationSetting(wrd.csystem, sys.cPluginDescription, pluginMetaDataDescription); await loggers.consoleLog(namespacePrefix + functionName, msg.cpluginNameIs + pluginMetaDataName); await loggers.consoleLog(namespacePrefix + functionName, msg.cPluginVersionNumberIs + pluginMetaDataVersion); } if (await configurator.getConfigurationSetting(wrd.csystem, cfg.cenableConstantsValidation) === true) { let resolvedFrameworkConstantsPathActual = path.resolve(configData[cfg.cframeworkConstantsPath]); let resolvedClientConstantsPathActual = path.resolve(configData[cfg.cclientConstantsPath]); await loggers.consoleLog(namespacePrefix + functionName, msg.cresolvedFrameworkConstantsPathActualIs + resolvedFrameworkConstantsPathActual); await loggers.consoleLog(namespacePrefix + functionName, msg.cresolvedClientConstantsPathActualIs + resolvedClientConstantsPathActual); await configurator.setConfigurationSetting(wrd.csystem, cfg.cframeworkConstantsPath, resolvedFrameworkConstantsPathActual); await configurator.setConfigurationSetting(wrd.csystem, cfg.capplicationConstantsPath, resolvedClientConstantsPathActual); await chiefConstant.initializeConstantsValidationData(); // This just makes sure that the data structure is created on the D-Data structure. let frameworkConstantsValidationData = await chiefConstant.generateFrameworkConstantsValidationData(); let applicationConstantsValidationData = await configData[cfg.capplicationConstantsValidationData].call(); await loggers.consoleLog(namespacePrefix + functionName, msg.cframeworkConstantsValidationDataIs + JSON.stringify(frameworkConstantsValidationData)); await loggers.consoleLog(namespacePrefix + functionName, msg.capplicationConstantsValidationDataIs + JSON.stringify(applicationConstantsValidationData)); await chiefConstant.addConstantsValidationData(frameworkConstantsValidationData, wrd.cFramework); await chiefConstant.addConstantsValidationData(applicationConstantsValidationData, wrd.cApplication); } // End-if (configurator.getConfigurationSetting(wrd.csystem, cfg.cenableConstantsValidation) === true) let enableLogFileOutputSetting = await configurator.getConfigurationSetting(wrd.csystem, cfg.clogFileEnabled); if (enableLogFileOutputSetting === true) { await loggers.consoleLog(namespacePrefix + functionName, msg.cCaptureSessionDateTimeStampLogFileName); let sessionDateTimeStamp = await ruleBroker.processRules([await configurator.getConfigurationSetting(wrd.csystem, cfg.cdateTimeStamp), ''], [biz.cgetNowMoment]); await loggers.consoleLog(namespacePrefix + functionName, msg.csessionDateTimeStampIs + sessionDateTimeStamp); let logFileName = sessionDateTimeStamp + bas.cUnderscore + applicationMetaData[wrd.cVersion] + bas.cUnderscore + applicationMetaData[wrd.cName] + gen.cDotLog; await loggers.consoleLog(namespacePrefix + functionName, msg.clogFileNameIs + logFileName); await configurator.setConfigurationSetting(wrd.csystem, cfg.clogFileName, logFileName); } // End-if (enableLogFileOutputSetting === true) await mergeClientBusinessRules(configData[sys.cclientBusinessRules]); await mergeClientCommands(configData[sys.cclientCommands]); await loadCommandAliases(''); // This function will now pick up the defaults already saved in the configuration system. await loadCommandWorkflows(''); // Same as above. // Setup all themes if (await configurator.getConfigurationSetting(wrd.csystem, cfg.cdebugSettings) === true) { await chiefTheme.initThemes(); let frameworkThemesPath = configData[cfg.cframeworkThemesPath]; // frameworkThemesPath is: await loggers.consoleLog(namespacePrefix + functionName, msg.cframeworkThemesPathIs + frameworkThemesPath); let frameworkThemeData = await chiefTheme.generateThemeDataFromThemeRootPath(frameworkThemesPath); // frameworkThemeData is: await loggers.consoleLog(namespacePrefix + functionName, msg.cframeworkThemeDataIs + JSON.stringify(frameworkThemeData)); if (frameworkThemeData) { await chiefTheme.addThemeData(frameworkThemeData, wrd.cFramework); } if (configData[cfg.cclientThemesPath]) { let applicationThemesPath = configData[cfg.cclientThemesPath]; // applicationThemesPath is: await loggers.consoleLog(namespacePrefix + functionName, msg.capplicationThemesPathIs + applicationThemesPath); let applicationThemeData = await chiefTheme.generateThemeDataFromThemeRootPath(applicationThemesPath); // applicationThemeData is: await loggers.consoleLog(namespacePrefix + functionName, msg.capplicationThemeDataIs + JSON.stringify(applicationThemeData)); await chiefTheme.addThemeData(applicationThemeData, wrd.cApplication); } } // Setup all schemas await loadAllSchemas(); // NOTE: We need this here, because the plugin itself will try to create an instance of haystacks to re-use its functionality. // When that happens the plugin will send execution back here and haystacks would again try to load the plugin from within the plugin! // We MUST prevent this from happening. So I've dropped this here to allow the plugin to control the loading of nested plugins. // ------------- // NOTE: Apparently this is not an issue for the plugin?!? Maybe? // console.log('--Determine if the plugin is the one loading haystacks.'); // if (configData[cfg.cenablePluginLoader] != null || configData[cfg.cenablePluginLoader] != undefined) { // console.log('--Plugin IS LOADING Haystacks!!') // console.log('--Determine if the plugin has disabled the plugin loader setting.'); // if (configData[cfg.cenablePluginLoader] === false) { // console.log('--Plugin loader setting has been disabled successfully!'); // await configurator.setConfigurationSetting(wrd.csystem, cfg.cenablePluginLoader, false); // console.log('--Force the configruation setting to disable the plugin loader!'); // } // console.log('--DONE checking and disabling the plugin loader setting.'); // } // console.log('--DONE checking if the plugin is the one loading the haystacks.'); // console.log('--Now check if the plugin Loader setting is enabled or not'); if (await configurator.getConfigurationSetting(wrd.csystem, cfg.cenablePluginLoader) === true) { // console.log('--Plugin loader is still enabled!'); let pluginRegistryPath = path.resolve(configData[cfg.cclientRegisteredPlugins]); // pluginRegistryPath is: await loggers.consoleLog(namespacePrefix + functionName, msg.cpluginRegistryPathIs + pluginRegistryPath); await configurator.setConfigurationSetting(wrd.csystem, cfg.cpluginRegistryPath, pluginRegistryPath); let pluginRegistryData = await chiefPlugin.loadPluginRegistryData(pluginRegistryPath); // pluginRegistryData is: await loggers.consoleLog(namespacePrefix + functionName, msg.cpluginRegistryDataIs + JSON.stringify(pluginRegistryData)); await configurator.setConfigurationSetting(wrd.csystem, cfg.cpluginsRootPath, pluginRegistryData[wrd.cpath]); let pluginPersistedSuccess = await chiefPlugin.persistPluginRegistryToDataStructure(pluginRegistryData); if (pluginPersistedSuccess === true) { // The loaded data was saved to the D-data structure, we can continue processing on it now. // Should first scan it to determine if it contains any registered plugins. // We can add those to the load list. // Then should scan the specified path to determine if there are any other plugins that should be loaded and registered. // Then add them to the load list as well. // Examine if there are any plugins in an excluded list, and don't add them to the load list, and don't register them. if (await configurator.getConfigurationSetting(wrd.csystem, cfg.csynchronizePluginRegistryWithPluginFolder) === true) { await syncPluginRegistryWithPath(); } await loadPluginsFromRegistry(); } } if (await configurator.getConfigurationSetting(wrd.csystem, cfg.clogUserEnteredCommands) === true) { await stack.initStack(sys.cUserEnteredCommandLog); } if (await configurator.getConfigurationSetting(wrd.csystem, cfg.clogAllCommands) === true) { await stack.initStack(sys.cSystemCommandLog); } // We can pass in a name of a configuration setting that has a path to load plugin data this way. // console.log('Contents of D are: ' + JSON.stringify(D)); // console.log(`END ${namespacePrefix}${functionName} function`); await loggers.consoleLog(namespacePrefix + functionName, msg.cEND_Function); } /** * @function resetRulesAndCommands * @description Clears and then re-initializes the Haystacks platform framework business rules and commands. * This is needed because: When Haystacks is used to load plugins, the plugin needs to make a call back to Haystacks * to load all the plugin resource non-code files. When the plugin does that it is creating a new instance of Haystacks. * The new instance of Haystacks created by the plugin is not the same instance as the original instance of Haystacks. * We get around that by injecting all of the data from the original Haystacks into the new plugin-instance of Haystacks. * However, when trying to call the business rules or commands using the dependency injected data, the business rules are not found, * and cannot be executed. It turns out because the paths are completely different. * The original instance of Haystacks initialized all its business rules and commands from the original instance path. * So when executing those business rules and those commands it executes that code from those files using that path. * However, when trying to pump those same business rules and commands into the plugin instance and then execute the same code, * the plugin instance doesn't have access to or know about the paths to those business rules or commands. * So therefore the solution is to have the plugin instance of Haystacks to clear and re-initialize its own business rules and commands. * That way the plugin instance of Haystacks, when it tries to execute its own business rules and commands it will be doing so using, * its own path to those business rules and commands and should therefore work as expected. * @return {void} * @author Seth Hollingsead * @date 2023/02/12 */ async function resetRulesAndCommands() { let functionName = resetRulesAndCommands.name; await loggers.consoleLog(namespacePrefix + functionName, msg.cBEGIN_Function); await chiefCommander.reinitializeCommands(); await ruleBroker.resetBusinessRules(); await loggers.consoleLog(namespacePrefix + functionName, msg.cEND_Function); } /** * @function mergeClientBusinessRules * @description Merges the map of client defined business rule names and client defined business rule function calls * with the existing D-data structure that should already have all of the system defined business rule. * @param {object} clientBusinessRules A map of client defined business rule names and client defined business rule function calls. * @return {void} * @author Seth Hollingsead * @date 2022/02/09 */ async function mergeClientBusinessRules(clientBusinessRules) { let functionName = mergeClientBusinessRules.name; await loggers.consoleLog(namespacePrefix + functionName, msg.cBEGIN_Function); // console.log(`clientBusinessRules is: ${JSON.stringify(clientBusinessRules)}`); await ruleBroker.addClientRules(clientBusinessRules); await loggers.consoleLog(namespacePrefix + functionName, msg.cEND_Function); } /** * @function mergeClientCommands * @description Merges the map of client defined command names and client defined command function calls * with the existing D-data structure that should already have all of the system defined commands. * @param {object} clientCommands A map of client defined command names and client defined command function calls. * @return {void} * @author Seth Hollingsead * @date 2022/02/09 */ async function mergeClientCommands(clientCommands) { let functionName = mergeClientCommands.name; await loggers.consoleLog(namespacePrefix + functionName, msg.cBEGIN_Function); // console.log(`clientCommands is: ${JSON.stringify(clientCommands)}`); await chiefCommander.addClientCommands(clientCommands); await loggers.consoleLog(namespacePrefix + functionName, msg.cEND_Function); } /** * @function loadCommandAliases * @description Loads and merges both the system defined command aliases XML file and * the client defined command aliases XML file, or an optional user defined command aliases path. * @param {string} commandAliasesPath The configuration name of the configuration setting where * the path to the commands aliases XML file is stored, that should be loaded (OPTIONAL). * @return {void} * @author Seth Hollingsead * @date 2022/02/09 */ async function loadCommandAliases(commandAliasesPathConfigName) { let functionName = loadCommandAliases.name; await loggers.consoleLog(namespacePrefix + functionName, msg.cBEGIN_Function); // commandAliasesPathConfigName is: await loggers.consoleLog(namespacePrefix + functionName, msg.ccommandAliasesPathConfigNameIs + commandAliasesPathConfigName); let resolvedSystemCommandsAliasesPath; let resolvedClientCommandsAliasesPath; let resolvedPluginCommandAliasesPath; let resolvedCustomCommandsAliasesPath; if (commandAliasesPathConfigName) { resolvedCustomCommandsAliasesPath = path.resolve(await configurator.getConfigurationSetting(wrd.csystem, commandAliasesPathConfigName)); // resolvedCustomCommandsAliasesPath is: await loggers.consoleLog(namespacePrefix + functionName, msg.cresolvedCustomCommandsAliasesPathIs + resolvedCustomCommandsAliasesPath); await chiefCommander.loadCommandAliasesFromPath(commandAliasesPathConfigName, wrd.cPlugin); } else { resolvedSystemCommandsAliasesPath = await configurator.getConfigurationSetting(wrd.csystem, cfg.cframeworkCommandAliasesPath); resolvedClientCommandsAliasesPath = await configurator.getConfigurationSetting(wrd.csystem, cfg.cclientCommandAliasesPath); // resolvedSystemCommandsAliasesPath is: await loggers.consoleLog(namespacePrefix + functionName, msg.cresolvedSystemCommandsAliasesPathIs + resolvedSystemCommandsAliasesPath); // resolvedClientCommandsAliasesPath is: await loggers.consoleLog(namespacePrefix + functionName, msg.cresolvedClientCommandsAliasesPathIs + resolvedClientCommandsAliasesPath); await chiefCommander.loadCommandAliasesFromPath(cfg.cframeworkCommandAliasesPath, sys.cFramework); await chiefCommander.loadCommandAliasesFromPath(cfg.cclientCommandAliasesPath, wrd.cApplication); if (await configurator.getConfigurationSetting(wrd.csystem, sys.cPluginName)) { await configurator.getConfigurationSetting(wrd.csystem, cfg.cpluginWorkflowsPath); resolvedPluginCommandAliasesPath = await configurator.getConfigurationSetting(wrd.csystem, cfg.cpluginCommandAliasesPath); // resolvedPluginCommandAliasesPath is: await loggers.consoleLog(namespacePrefix + functionName, msg.cresolvedPluginCommandsAliasesPathIs + resolvedPluginCommandAliasesPath); await chiefCommander.loadCommandAliasesFromPath(cfg.cpluginCommandAliasesPath, wrd.cPlugin); } } // console.log('ALL Loaded command aliases is: ' + JSON.stringify(D[sys.cCommandsAliases])); await loggers.consoleLog(namespacePrefix + functionName, msg.cEND_Function); } /** * @function loadCommandWorkflows * @description Loads and merges both the system defined command workflows XML file and * client defined command workflows XML file, or an optional user defined workflow path. * @param {string} workflowPathConfigName The configuration name of the configuration setting where * the path to the workflows XML file is stored, that should be loaded (OPTIONAL). * @return {void} * @author Seth Hollingsead * @date 2022/02/16 */ async function loadCommandWorkflows(workflowPathConfigName) { let functionName = loadCommandWorkflows.name; await loggers.consoleLog(namespacePrefix + functionName, msg.cBEGIN_Function); // workflowPathConfigName is: await loggers.consoleLog(namespacePrefix + functionName, msg.cworkflowPathConfigurationNameIs + workflowPathConfigName); let resolvedSystemWorkflowsPath; let resolvedClientWorkflowsPath; let resolvedPluginWorkflowsPath; let resolvedCustomWorkflowsPath; if (workflowPathConfigName) { resolvedCustomWorkflowsPath = path.resolve(await configurator.getConfigurationSetting(wrd.csystem, workflowPathConfigName)); // resolvedCustomWorkflowsPath is: await loggers.consoleLog(namespacePrefix + functionName, msg.cresolvedCustomWorkflowsPathIs + resolvedCustomWorkflowsPath); await chiefWorkflow.loadCommandWorkflowsFromPath(workflowPathConfigName, wrd.cPlugin); } else { resolvedSystemWorkflowsPath = await configurator.getConfigurationSetting(wrd.csystem, cfg.cframeworkWorkflowsPath); resolvedClientWorkflowsPath = await configurator.getConfigurationSetting(wrd.csystem, cfg.cclientWorkflowsPath); // resolvedSystemWorkflowsPath is: await loggers.consoleLog(namespacePrefix + functionName, msg.cresolvedSystemWorkflowsPathIs + resolvedSystemWorkflowsPath); // resolvedClientWorkflowsPath is: await loggers.consoleLog(namespacePrefix + functionName, msg.cresolvedClientWorkflowsPathIs + resolvedClientWorkflowsPath); await chiefWorkflow.loadCommandWorkflowsFromPath(cfg.cframeworkWorkflowsPath, sys.cFramework); await chiefWorkflow.loadCommandWorkflowsFromPath(cfg.cclientWorkflowsPath, wrd.cApplication); if (await configurator.getConfigurationSetting(wrd.csystem, sys.cPluginName)) { await configurator.getConfigurationSetting(wrd.csystem, cfg.cpluginWorkflowsPath); resolvedPluginWorkflowsPath = await configurator.getConfigurationSetting(wrd.csystem, cfg.cpluginWorkflowsPath); // resolvedPluginWorkflowsPath is: await loggers.consoleLog(namespacePrefix + functionName, msg.cpluginWorkflowsPathIs + resolvedPluginWorkflowsPath); await chiefWorkflow.loadCommandWorkflowsFromPath(cfg.cpluginWorkflowsPath, wrd.cPlugin); } } await loggers.consoleLog(namespacePrefix + functionName, msg.cEND_Function); } /** * @function loadAllSchemas * @description Loads all of the schema data that will be used to control code behavior and business rule dissemination of execution logic. * @return {boolean} True or False to indicate if all of the schema's were loaded and stored or not. * @author Seth Hollingsead * @date 2024/10/23 */ async function loadAllSchemas() { let functionName = loadAllSchemas.name; await loggers.consoleLog(namespacePrefix + functionName, msg.cBEGIN_Function); let returnData = false; await dataBroker.initSchemaStorage(); let frameworkSchemasPath = await configurator.getConfigurationSetting(wrd.csystem, cfg.cframeworkSchemasPath); // frameworkSchemasPath is: await loggers.consoleLog(namespacePrefix + functionName, msg.cframeworkSchemasPathIs + frameworkSchemasPath); let applicationSchemasPath = await configurator.getConfigurationSetting(wrd.csystem, cfg.capplicationSchemasPath); // applicationSchemasPath is: await loggers.consoleLog(namespacePrefix + functionName, msg.capplicationSchemasPathIs + applicationSchemasPath); if (frameworkSchemasPath) { let frameworkSchemasData = await chiefData.loadAllJsonData(frameworkSchemasPath, wrd.cSchemas); // frameworkSchemasData is: await loggers.consoleLog(namespacePrefix + functionName, msg.cframeworkSchemasDataIs + JSON.stringify(frameworkSchemasData)); returnData = await chiefData.storeAllSchemaData([frameworkSchemasData]); await configurator.setConfigurationSetting(wrd.csystem, cfg.cschemasLoaded, true); } if (applicationSchemasPath) { let applicationSchemasData = await chiefData.loadAllJsonData(applicationSchemasPath, wrd.cSchemas); // applicationSchemasData is: await loggers.consoleLog(namespacePrefix + functionName, msg.capplicationSchemasDataIs + JSON.stringify(applicationSchemasData)); returnData = await chiefData.storeAllSchemaData([applicationSchemasData]); } // await loggers.consoleLog(namespacePrefix + functionName, 'Contents of D are: ' + JSON.stringify(D)); await loggers.consoleLog(namespacePrefix + functionName, msg.creturnDataIs + JSON.stringify(returnData)); await loggers.consoleLog(namespacePrefix + functionName, msg.cEND_Function); return returnData; } /** * @function listLoadedPlugins * @description This is a wrapper function for chiefPlugin.listLoadedPlugins. * Which is in-turn a wrapper function for pluginBroker.listAllLoadedPlugins. * @return {array<string>} A list array of the names of the plugins that are currently loaded. * @author Seth Hollingsead * @date 2023/02/06 */ async function listLoadedPlugins() { let functionName = listLoadedPlugins.name; await loggers.consoleLog(namespacePrefix + functionName, msg.cBEGIN_Function); let returnData = []; returnData = await chiefPlugin.listLoadedPlugins(); await loggers.consoleLog(namespacePrefix + functionName, msg.creturnDataIs + JSON.stringify(returnData)); await loggers.consoleLog(namespacePrefix + functionName, msg.cEND_Function); return returnData; } /** * @function listAllPluginsInRegistry * @description This is a wrapper function for chiefPlugin.getAllPluginsInRegistry. * Which is in-turn a wrapper function for pluginBroker.listPluginsInRegistry. * @return {array<string>} A list array of the names of the plugins in the plugin registry. * @author Seth Hollingsead * @date 2022/09/15 */ async function listAllPluginsInRegistry() { let functionName = listAllPluginsInRegistry.name; await loggers.consoleLog(namespacePrefix + functionName, msg.cBEGIN_Function); let returnData = []; returnData = await chiefPlugin.getAllPluginsInRegistry(); await loggers.consoleLog(namespacePrefix + functionName, msg.creturnDataIs + JSON.stringify(returnData)); await loggers.consoleLog(namespacePrefix + functionName, msg.cEND_Function); return returnData; } /** * @function listAllPluginsInRegistryPath * @description This is a wrapper function for chiefPlugin.getAllPluginsInRegistryPath. * Which is in-turn a wrapper function for pluginBroker.listPluginsInRegistryPath. * @return {array<string>} A list array of the names of the plugins in the plugin registry. * @author Seth Hollingsead * @date 2022/09/15 */ async function listAllPluginsInRegistryPath() { let functionName = listAllPluginsInRegistryPath.name; await loggers.consoleLog(namespacePrefix + functionName, msg.cBEGIN_Function); let returnData = []; returnData = await chiefPlugin.getAllPluginsInRegistryPath(); await loggers.consoleLog(namespacePrefix + functionName, msg.creturnDataIs + JSON.stringify(returnData)); await loggers.consoleLog(namespacePrefix + functionName, msg.cEND_Function); return returnData; } /** * @function numberOfPluginsInRegistry * @description This is a wrapper function for chiefPlugin.countAllPluginsInRegistry. * Which is in-turn a wrapper function for pluginBroker.countPluginsInRegistry. * @return {integer} The count of the number of plugins listed in the plugin registry data hive. * @author Seth Hollingsead * @date 2022/09/15 */ async function numberOfPluginsInRegistry() { let functionName = numberOfPluginsInRegistry.name; await loggers.consoleLog(namespacePrefix + functionName, msg.cBEGIN_Function); let returnData = 0; returnData = await chiefPlugin.countAllPluginsInRegistry(); await loggers.consoleLog(namespacePrefix + functionName, msg.creturnDataIs + JSON.stringify(returnData)); await loggers.consoleLog(namespacePrefix + functionName, msg.cEND_Function); return returnData; } /** * @function numberOfPluginsInRegistryPath * @description This is a wrapper function for chiefPlugin.countAllPluginsInRegistryPath. * Which is in-turn a wrapper function for pluginBroker.countPluginsInRegistryPath. * @return {integer} The count of the number of plugin sub-folders in the plugins path listed in the plugin registry data hive. * @author Seth Hollingsead * @date 2022/09/15 */ async function numberOfPluginsInRegistryPath() { let functionName = numberOfPluginsInRegistryPath.name; await loggers.consoleLog(namespacePrefix + functionName, msg.cBEGIN_Function); let returnData = 0; returnData = await chiefPlugin.countAllPluginsInRegistryPath(); await loggers.consoleLog(namespacePrefix + functionName, msg.creturnDataIs + JSON.stringify(returnData)); await loggers.consoleLog(namespacePrefix + functionName, msg.cEND_Function); return returnData; } /** * @function registerPluginByNameAndPath * @description This is a wrapper function for chiefPlugin.registerNamedPlugin. * Which is in-turn a wrapper function for pluginBroker.registerPlugin. * @param {string} pluginName The name of the plugin that should be registered. * @param {string} pluginPath The path to the plugin, to be added to the plugin registry. * This should be the path to the plugin/package.json file, but not including the package.json as part of the path URI. * @return {boolean} True or False to indicate if the plugin was added to the plugin registry successfully or not. * @author Seth Hollingsead * @date 2022/09/15 */ async function registerPluginByNameAndPath(pluginName, pluginPath) { let functionName = registerPluginByNameAndPath.name; await loggers.consoleLog(namespacePrefix + functionName, msg.cBEGIN_Function); // pluginName is: await loggers.consoleLog(namespacePrefix + functionName, msg.cpluginNameIs + pluginName); // pluginPath is: await loggers.consoleLog(namespacePrefix + functionName, msg.cpluginPathIs + pluginPath); let returnData = false; returnData = await chiefPlugin.registerNamedPlugin(pluginName, pluginPath); await loggers.consoleLog(namespacePrefix + functionName, msg.creturnDataIs + JSON.stringify(returnData)); await loggers.consoleLog(namespacePrefix + functionName, msg.cEND_Function); return returnData; } /** * @function unregisterPluginByName * @description This is a wrapper function for chiefPlugin.unregisterNamedPlugin. * Which is in-turn a wrapper function for pluginBroker.unregisterPlugin. * @param {string} pluginName The name of the plugin that should be removed from the plugin registry. * @return {boolean} True or False to indicate if the plugin was removed from the plugin registry successfully or not. * @author Seth Hollingsead * @date 2022/09/15 */ async function unregisterPluginByName(pluginName) { let functionName = unregisterPluginByName.name; await loggers.consoleLog(namespacePrefix + functionName, msg.cBEGIN_Function); // pluginName is: await loggers.consoleLog(namespacePrefix + functionName, msg.cpluginNameIs + pluginName); let returnData = false; returnData = await chiefPlugin.unregisterNamedPlugin(pluginName); await loggers.consoleLog(namespacePrefix + functionName, msg.creturnDataIs + JSON.stringify(returnData)); await loggers.consoleLog(namespacePrefix + functionName, msg.cEND_Function); return returnData; } /** * @function unregisterPlugins * @description This is a wrapper function for chiefPlugin.unregisterPlugins. * Which is in-turn a wrapper function for pluginBroker.unregisterPlugins. * @param {array<string>} pluginsListArray A list array of plugin names that should be removed from the plugin registry. * @return {boolean} True or False to indicate if all the plugins were successfully removed from the plugin registry or not. * @author Seth Hollingsead * @date 2023/02/07 */ async function unregisterPlugins(pluginsListArray) { let functionName = unregisterPlugins.name; await loggers.consoleLog(namespacePrefix + functionName, msg.cBEGIN_Function); // pluginsListArray is: await loggers.consoleLog(namespacePrefix + functionName, msg.cpluginsListArrayIs + JSON.stringify(pluginsListArray)); let returnData = false; returnData = await chiefPlugin.unregisterPlugins(pluginsListArray); await loggers.consoleLog(namespacePrefix + functionName, msg.creturnDataIs + JSON.stringify(returnData)); await loggers.consoleLog(namespacePrefix + functionName, msg.cEND_Function); return returnData; } /** * @function syncPluginRegistryWithPath * @description This is a wrapper function for chiefPlugin.synchronizePluginRegistryWithPath * Which is in-turn a wrapper function for pluginBroker.synchPluginRegistryWithPluginRegistryPath. * @return {boolean} True or False to indicate if the synchronization was performed successfully or not. * @author Seth Hollingsead * @date 2022/09/15 * @NOTE It is expected that the number of plugins loaded at any one time will not be crazy high. * The function that is called in pluginBroker.synchPluginRegistryWithPluginRegistryPath will * do a O(n^2) brute force search, * if the number of plugins needed at any one time ever grows much over 100, then this solution will need to be re-evaluated! */ async function syncPluginRegistryWithPath() { let functionName = syncPluginRegistryWithPath.name; await loggers.consoleLog(namespacePrefix + functionName, msg.cBEGIN_Function); let returnData = false; returnData = await chiefPlugin.synchronizePluginRegistryWithPath(); await loggers.consoleLog(namespacePrefix + functionName, msg.creturnDataIs + JSON.stringify(returnData)); await loggers.consoleLog(namespacePrefix + functionName, msg.cEND_Function); return returnData; } /** * @function clearAllPluginRegistry * @description This is a wrapper function for chiefPlugin.clearPluginRegistry. * Which is in-turn a wrapper function for pluginBroker.unregisterAllPlugins. * @return {boolean} True or False to indicate if the plugin registry data hive was cleared successfully or not. * @author Seth Hollingsead * @date 2022/09/15 */ async function clearAllPluginRegistry() { let functionName = clearAllPluginRegistry.name; await loggers.consoleLog(namespacePrefix + functionName, msg.cBEGIN_Function); let returnData = false; returnData = await chiefPlugin.clearPluginRegistry(); await loggers.consoleLog(namespacePrefix + functionName, msg.creturnDataIs + JSON.stringify(returnData)); await loggers.consoleLog(namespacePrefix + functionName, msg.cEND_Function); return returnData; } /** * @function writePluginRegistryToDisk * @description This is a wrapper function for chiefPlugin.savePluginRegistryDisk. * Which is in-turn a wrapper function for pluginBroker.savePluginRegistry. * @return {boolean} True or False to indicate if the plugin registry was successfully saved to the disk or not. * @author Seth Hollingsead * @date 2022/09/15 */ async function writePluginRegistryToDisk() { let functionName = writePluginRegistryToDisk.name; await loggers.consoleLog(namespacePrefix + functionName, msg.cBEGIN_Function); let returnData = false; returnData = await chiefPlugin.savePluginRegistryDisk(); await loggers.consoleLog(namespacePrefix + functionName, msg.creturnDataIs + JSON.stringify(returnData)); await loggers.consoleLog(namespacePrefix + functionName, msg.cEND_Function); return returnData; } /** * @function loadPlugin * @description Calls the plugin initializePlugin function to get the plugin data: * Business rules, Commands, Workflows, Constants, Configurations, dependencies ist (dependant plugins), etc... * @param {string} pluginPath The fully qualified path where to load the plugin from, * or the folder name that will contain the plugin in the plugin registry path. * @return {boolean} True or False to indicate if the plugin was loaded successfully or not. * @author Seth Hollingsead * @date 2022/09/15 */ async function loadPlugin(pluginPath) { let functionName = loadPlugin.name; await loggers.consoleLog(namespacePrefix + functionName, msg.cBEGIN_Function); // pluginPath is: await loggers.consoleLog(namespacePrefix + functionName, msg.cpluginPathIs + pluginPath); let returnData = false; let pluginPathArray = []; pluginPathArray[0] = pluginPath; returnData = await loadPlugins(pluginPathArray); await loggers.consoleLog(namespacePrefix + functionName, msg.creturnDataIs + JSON.stringify(returnData)); await loggers.consoleLog(namespacePrefix + functionName, msg.cEND_Function); return returnData; } /** * @function loadPlugins * @description Calls the plugin initializePlugin function to get the plugin data, for each of the plugins in the input array of plugin paths: * Business rules, Commands, Workflows, Constants, Configurations, dependencies list (dependant plugins), etc... * @param {array<string>} pluginsPaths An array of fully qualified paths where to load the plugins from. * @return {boolean} True or False to indicate if all the plugins were loaded or not. * @author Seth Hollingsead * @date 2022/09/01 */ async function loadPlugins(pluginsPaths) { let functionName = loadPlugins.name; await loggers.consoleLog(namespacePrefix + functionName, msg.cBEGIN_Function); // pluginsPaths are: await loggers.consoleLog(namespacePrefix + functionName, msg.cpluginsPathsAre + JSON.stringify(pluginsPaths)); let returnData = false; let pluginsMetaData = await chiefPlugin.loadAllPluginsMetaData(pluginsPaths); let pluginsExecutionPaths = await chiefPlugin.loadAllPluginsExecutionPaths(pluginsMetaData, pluginsPaths); let allPluginsData = await chiefPlugin.loadAllPlugins(pluginsExecutionPaths, pluginsMetaData); let allPluginsDataIntegrated = await chiefPlugin.integrateAllPluginsData(allPluginsData); let loadedVerification = await chiefPlugin.verifyAllPluginsLoaded(); if (allPluginsDataIntegrated === true && loadedVerification === true) { // If and ONLY if both are true, then set returnData to true. // This means all the plugins were loaded successfully and all the data from all the plugins was also integrated successfully. returnData = true; } await loggers.consoleLog(namespacePrefix + functionName, msg.creturnDataIs + returnData); await loggers.consoleLog(namespacePrefix + functionName, msg.cEND_Function); return returnData; } /** * @function loadPluginsFromRegistry * @description Calls the plugin initializePlugin function to get teh plugin data, for each of the plugins and their paths from the plugin registry. * Business rules, Commands, Workflows, Constants, Configurations, dependencies list (dependant plugins), etc... * @return {boolean} True or False to ndicate if all the plugins were loaded or not. * @author Seth Hollingsead * @date 2022/09/16 */ async function loadPluginsFromRegistry() { let functionName = loadPluginsFromRegistry.name; await loggers.consoleLog(namespacePrefix + functionName, msg.cBEGIN_Function); let returnData = false; let pluginPathsArray = await chiefPlugin.getAllPluginsPathsInRegistry(); // pluginPathsArray is: await loggers.consoleLog(namespacePrefix + functionName, msg.cpluginPathsArrayIs + JSON.stringify(pluginPathsArray)); returnData = await loadPlugins(pluginPathsArray); await loggers.consoleLog(namespacePrefix + functionName, msg.creturnDataIs + returnData); await loggers.consoleLog(namespacePrefix + functionName, msg.cEND_Function)