@haystacks/async
Version:
A framework to build any number or any kind of native application or automation solution.
224 lines (213 loc) • 10.8 kB
JavaScript
/* eslint-disable no-undef */
/**
* @file testHarness.js
* @module testHarness
* @description This is the main init for the testHarness application.
* It contains just enough of the main program loop and/or basic argument parsing to
* effectively test the framework.
* @requires module:clientRules
* @requires module:clientCommands
* @requires module:application.command.constants
* @requires module:application.configuration.constants
* @requires module:application.constants
* @requires module:application.function.constants
* @requires module:application.message.constants
* @requires module:allApplicationConstantsValidationMetadata
* @requires {@link https://www.npmjs.com/package/@haystacks/async|@haystacks/async}
* @requires {@link https://www.npmjs.com/package/@haystacks/constants|@haystacks/constants}
* @requires {@link https://www.npmjs.com/package/url|url}
* @requires {@link https://www.npmjs.com/package/dotenv|dotenv}
* @requires {@link https://www.npmjs.com/package/path|path}
* @author Seth Hollingsead
* @date 2021/10/07
* @copyright Copyright © 2022-… by Seth Hollingsead. All rights reserved
*/
// Internal imports
import clientRules from './businessRules/clientRulesLibrary.js';
import clientCommands from './commands/clientCommandsLibrary.js';
import * as app_cfg from './constants/application.configuration.constants.js';
import * as apc from './constants/application.constants.js';
import * as app_msg from './constants/application.message.constants.js';
import allAppCV from './resources/constantsValidation/allApplicationConstantsValidationMetadata.js';
// External imports
import haystacks from '@haystacks/async';
import hayConst from '@haystacks/constants';
import url from 'url';
import dotenv from 'dotenv';
import path from 'path';
const {bas, biz, cmd, msg, sys, wrd} = hayConst;
let rootPath = '';
let baseFileName = path.basename(import.meta.url, path.extname(import.meta.url));
// application.testHarness.
let namespacePrefix = wrd.capplication + bas.cDot + baseFileName + bas.cDot;
// eslint-disable-next-line no-undef
global.appRoot = path.resolve(process.cwd());
dotenv.config();
// eslint-disable-next-line no-undef
const {NODE_ENV} = process.env;
let exitConditionArrayIndex = 0;
/**
* @function bootstrapApplication
* @description Setup all the testHarness application data and configuration settings.
* @return {void}
* @author Seth Hollingsead
* @date 2021/10/15
*/
async function bootstrapApplication() {
// let functionName = bootstrapApplication.name;
// console.log(`BEGIN ${namespacePrefix}${functionName} function`);
rootPath = url.fileURLToPath(path.dirname(import.meta.url));
let rootPathArray = [];
let pathSeparator = '';
if (rootPath.includes(bas.cBackSlash) === true) {
pathSeparator = bas.cBackSlash;
} else if (rootPath.includes(bas.cForwardSlash) === true) {
pathSeparator = bas.cForwardSlash;
}
rootPathArray = rootPath.split(pathSeparator);
rootPathArray.pop(); // remove any bin or src folder from the path.
rootPath = rootPathArray.join(pathSeparator);
let appConfig = {};
if (NODE_ENV === wrd.cdevelopment) {
appConfig = {
FrameworkName: apc.cExpectedActualFrameworkDevName,
clientRootPath: rootPath,
appConfigResourcesPath: rootPath + apc.cFullDevResourcesPath,
appConfigReferencePath: rootPath + apc.cFullDevConfigurationPath,
clientMetaDataPath: apc.cmetaDataDevPath,
clientCommandAliasesPath: rootPath + apc.cFullDevCommandsPath,
clientConstantsPath: rootPath + apc.cFullDevConstantsPath,
clientRegisteredPlugins: rootPath + apc.cFullDevPluginsRegistryPath,
clientWorkflowsPath: rootPath + apc.cFullDevWorkflowsPath,
clientThemesPath: rootPath + apc.cFullDevThemesPath,
applicationConstantsValidationData: allAppCV.initializeAllClientConstantsValidationData,
clientBusinessRules: {},
clientCommands: {}
};
} else if (NODE_ENV === wrd.cproduction) {
appConfig = {
FrameworkName: apc.cExpectedActualFrameworkProdName,
clientRootPath: rootPath,
appConfigResourcesPath: rootPath + apc.cFullProdResourcesPath,
appConfigReferencePath: rootPath + apc.cFullProdConfigurationPath,
clientMetaDataPath: apc.cmetaDataProdPath,
clientCommandAliasesPath: rootPath + apc.cFullProdCommandsPath,
clientConstantsPath: rootPath + apc.cFullProdConstantsPath,
clientRegisteredPlugins: rootPath + apc.cFullProdPluginsRegistryPath,
clientWorkflowsPath: rootPath + apc.cFullProdWorkflowsPath,
clientThemesPath: rootPath + apc.cFullProdThemesPath,
applicationConstantsValidationData: allAppCV.initializeAllClientConstantsValidationData,
clientBusinessRules: {},
clientCommands: {}
};
} else {
// WARNING: No .env file found! Going to default to the DEVELOPMENT ENVIRONMENT!
console.log(msg.cApplicationWarningMessage1a + msg.cApplicationWarningMessage1b);
appConfig = {
FrameworkName: apc.cExpectedActualFrameworkDevName,
clientRootPath: rootPath,
appConfigResourcesPath: rootPath + apc.cFullDevResourcesPath,
appConfigReferencePath: rootPath + apc.cFullDevConfigurationPath,
clientMetaDataPath: apc.cmetaDataDevPath,
clientCommandAliasesPath: rootPath + apc.cFullDevCommandsPath,
clientConstantsPath: rootPath + apc.cFullDevConstantsPath,
clientRegisteredPlugins: rootPath + apc.cFullDevPluginsRegistryPath,
clientWorkflowsPath: rootPath + apc.cFullDevWorkflowsPath,
clientThemesPath: rootPath + apc.cFullDevThemesPath,
applicationConstantsValidationData: allAppCV.initializeAllClientConstantsValidationData,
clientBusinessRules: {},
clientCommands: {}
};
}
appConfig[sys.cclientBusinessRules] = await clientRules.initClientRulesLibrary();
appConfig[sys.cclientCommands] = await clientCommands.initClientCommandsLibrary();
// console.log('appConfig is: ', appConfig);
await haystacks.initFramework(appConfig);
// console.log(`END ${namespacePrefix}${functionName} function`);
}
/**
* @function application
* @description This is the main program loop, the init for the testHarness application.
* @return {void}
* @author Seth Hollingsead
* @date 2021/10/15
*/
async function application() {
let functionName = application.name;
await haystacks.consoleLog(namespacePrefix, functionName, msg.cBEGIN_Function);
let argumentDrivenInterface = false;
let commandInput;
let commandResult;
argumentDrivenInterface = await haystacks.getConfigurationSetting(wrd.csystem, app_cfg.cargumentDrivenInterface);
if (argumentDrivenInterface === undefined) {
argumentDrivenInterface = false;
}
// argumentDrivenInterface is:
// await haystacks.consoleLog(namespacePrefix, functionName, app_msg.cargumentDrivenInterfaceIs + argumentDrivenInterface);
await haystacks.enqueueCommand(cmd.cStartupWorkflow);
// NOTE: We are processing the argument driven interface first that way even if we are not in an argument driven interface,
// arguments can still be passed in and they will be executed first, after the startup workflow is complete.
//
// We need to strip off any preceding "--" before we try to process it as an actual command.
// Also need to make sure that the command to execute actually contains the "--" or "/" or "\" or "-".
let commandToExecute = '';
// Make sure we execute any and all commands so the command queue is empty before
// we process the command args and add more commands to the command queue.
// Really this is about getting out the application name, version and about message.
while (await haystacks.isCommandQueueEmpty() === false) {
commandResult = await haystacks.processCommandQueue();
} // End-while (haystacks.isCommandQueueEmpty() === false)
// NOW process the command args and add them to the command queue for execution.
if (Array.isArray(process.argv) && process.argv.length > 2) {
// Caught the case that some arguments were passed in as input to the function.
console.log(app_msg.capplicationMessage00);
if (process.argv[2].includes(bas.cDash) === true ||
process.argv[2].includes(bas.cForwardSlash) === true ||
process.argv[2].includes(bas.cBackSlash) === true) {
commandToExecute = await haystacks.executeBusinessRule([process.argv, ''], [biz.caggregateCommandArguments]);
} else {
commandToExecute = await haystacks.executeBusinessRules([process.argv, ''], [biz.caggregateCommandArguments]);
}
if (commandToExecute !== '') {
console.log(msg.ccommandToExecuteIs + commandToExecute);
await haystacks.enqueueCommand(commandToExecute);
}
while (await haystacks.isCommandQueueEmpty() === false) {
commandResult = await haystacks.processCommandQueue();
} // End-while (haystacks.isCommandQueueEmpty() === false)
} // End-if (!process.argv && process.argv.length > 0)
// NOW the application can continue with the interactive interface fi the flag was set to false.
if (argumentDrivenInterface === false) {
// BEGIN main program loop
await haystacks.consoleLog(namespacePrefix, functionName, app_msg.capplicationMessage01);
// BEGIN command parser
await haystacks.consoleLog(namespacePrefix, functionName, app_msg.capplicationMessage02);
while(programRunning === true) {
if (await haystacks.isCommandQueueEmpty() === true) {
// biz.cprompt is some how undefined here, although other biz.c<something-else> do still work.
// We will use wrd.cprompt here because it is working. No idea what the issue is with biz.prompt.
commandInput = await haystacks.executeBusinessRules([bas.cGreaterThan, ''], [wrd.cprompt]);
await haystacks.enqueueCommand(commandInput);
} // End-if (haystacks.isCommandQueueEmpty() === true)
commandResult = await haystacks.processCommandQueue();
if (commandResult[exitConditionArrayIndex] === false) {
// END command parser
await haystacks.consoleLog(namespacePrefix, functionName, app_msg.capplicationMessage03);
programRunning = false;
// END main program loop
await haystacks.consoleLog(namespacePrefix, functionName, app_msg.capplicationMessage04);
// Exiting TEST HARNESS APPLICATION
await haystacks.consoleLog(namespacePrefix, functionName, app_msg.capplicationMessage05);
break;
} // End-if (commandResult[exitConditionArrayIndex] === false)
} // End-while (programRunning === true)
} // End-if (argumentDrivenInterface === false)
await haystacks.consoleLog(namespacePrefix, functionName, msg.cEND_Function);
}
// Launch the Test Harness application!!
let programRunning = false;
await bootstrapApplication();
programRunning = true;
await application();
process.exit();