UNPKG

haystacks-tt

Version:

A simple Haystacks-async based command line typing tutor program for Windows, Mac & Linux.

315 lines (299 loc) 19.5 kB
/** * @file clientCommands.js * @module clientCommands * @description Contains all client defined commands for execution client actions with various operations. * @requires module:application.business.constants * @requires module:application.configuration.constants * @requires module:application.constants * @requires module:application.message.constants * @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/figlet|figlet} * @requires {@link https://www.npmjs.com/package/path|path} * @author Seth Hollingsead * @date 2022/03/13 * @copyright Copyright © 2022-… by Seth Hollingsead. All rights reserved */ // Internal imports import * as app_biz from '../../constants/application.business.constants.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'; // External imports import haystacks from '@haystacks/async'; 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)); // buildRelease.commands.clientCommands.clientCommands. const namespacePrefix = apc.cApplicationName + bas.cDot + wrd.ccommands + bas.cDot + wrd.cclient + wrd.cCommands + bas.cDot + baseFileName + bas.cDot; /** * @function customEchoCommand * @description A quick command to validate that the new * dynamic data storage technique for client commands is working. * @param {string} inputData The string input data. * @param {string} inputMetaData The string of input meta-data. * @return {string} An echo of the input Data with some hard-coded modifier. * @author Seth Hollingsead * @date 2022/03/13 */ async function customEchoCommand(inputData, inputMetaData) { let functionName = customEchoCommand.name; await haystacks.consoleLog(namespacePrefix, functionName, msg.cBEGIN_Function); await haystacks.consoleLog(namespacePrefix, functionName, msg.cinputDataIs + JSON.stringify(inputData)); await haystacks.consoleLog(namespacePrefix, functionName, msg.cinputMetaDataIs + inputMetaData); let returnData = [false, false]; returnData[1] = inputData + app_msg.cclientStringParsingDotCustomEcho; console.log(returnData[1]); await haystacks.consoleLog(namespacePrefix, functionName, msg.creturnDataIs + JSON.stringify(returnData)); await haystacks.consoleLog(namespacePrefix, functionName, msg.cEND_Function); return returnData; } /** * @function resolveAppPath * @description Resolves the app path, based on the root path of the build-release app path. * @param {array<string>} inputData An array of strings that contain the name of the command being executed, * and the root path for the build-release application. * inputData[0] = 'resolveAppPath' - The name of this command. * inputData[1] = 'C:/HaystacksTT/build/buildRelease/' - The path for the build release application. * @param {string} inputMetaData Not used for this command. * @return {array<boolean|boolean>} * @author Seth Hollingsead * @date 2023/03/16 */ async function resolveAppPath(inputData, inputMetaData) { let functionName = resolveAppPath.name; await haystacks.consoleLog(namespacePrefix, functionName, msg.cBEGIN_Function); await haystacks.consoleLog(namespacePrefix, functionName, msg.cinputDataIs + JSON.stringify(inputData)); await haystacks.consoleLog(namespacePrefix, functionName, msg.cinputMetaDataIs + inputMetaData); let returnData = [true, false]; let buildReleaseRootPathArray = []; let pathSeparator = ''; if (inputData && Array.isArray(inputData) && inputData.length === 2) { let buildReleaseRootPath = inputData[1]; // buildReleaseRootPath is: await haystacks.consoleLog(namespacePrefix, functionName, app_msg.cbuildReleaseRootPathIs + buildReleaseRootPath); if (buildReleaseRootPath.includes(bas.cForwardSlash)) { pathSeparator = bas.cForwardSlash; buildReleaseRootPathArray = buildReleaseRootPath.split(bas.cForwardSlash); } else if (buildReleaseRootPath.includes(bas.cBackSlash)) { pathSeparator = bas.cBackSlash; buildReleaseRootPathArray = buildReleaseRootPath.split(bas.cBackSlash); } // buildReleaseRootPathArray is: await haystacks.consoleLog(namespacePrefix, functionName, app_msg.cbuildReleaseRootPathArrayIs + JSON.stringify(buildReleaseRootPathArray)); await haystacks.setConfigurationSetting(wrd.csystem, app_cfg.cpathSeparator, pathSeparator); buildReleaseRootPathArray.pop(); buildReleaseRootPathArray.pop(); let appRootPath = buildReleaseRootPathArray.join(pathSeparator); // appRootPath is: await haystacks.consoleLog(namespacePrefix, functionName, app_msg.cappRootPathIs + appRootPath); await haystacks.setConfigurationSetting(wrd.csystem, cfg.cappRootPath, appRootPath); returnData[1] = appRootPath; } // End-if (inputData && Array.isArray(inputData) && inputData.length === 2) await haystacks.consoleLog(namespacePrefix, functionName, msg.creturnDataIs + JSON.stringify(returnData)); await haystacks.consoleLog(namespacePrefix, functionName, msg.cEND_Function); return returnData; } /** * @function rectifyAppMetaData * @description Works out the details of the application meta-data, path and loading of the file, parsing, * processing and printing of info to the console log. * @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. */ async function rectifyAppMetaData(inputData, inputMetaData) { let functionName = rectifyAppMetaData.name; await haystacks.consoleLog(namespacePrefix, functionName, msg.cBEGIN_Function); await haystacks.consoleLog(namespacePrefix, functionName, msg.cinputDataIs + JSON.stringify(inputData)); await haystacks.consoleLog(namespacePrefix, functionName, msg.cinputMetaDataIs + inputMetaData); let returnData = [true, false]; // apc.cFullDevResourcesPath let appRootPath = await haystacks.getConfigurationSetting(wrd.csystem, cfg.cappRootPath); // appRootPath is: await haystacks.consoleLog(namespacePrefix, functionName, app_msg.cappRootPathIs + appRootPath); let appResourcesRootPath = appRootPath + apc.cFullDevResourcesPath; // appResourcesRootPath is: await haystacks.consoleLog(namespacePrefix, functionName, app_msg.cappResourcesRootPathIs + appResourcesRootPath); await haystacks.setConfigurationSetting(wrd.csystem, app_cfg.cappResourcesRootPath, appResourcesRootPath) await haystacks.setConfigurationSetting(wrd.csystem, app_cfg.csourcePath, apc.cAppDevPath); await haystacks.setConfigurationSetting(wrd.csystem, app_cfg.cdestinationPath, apc.cAppProdPath); await haystacks.setConfigurationSetting(wrd.csystem, app_cfg.csourceResourcesPath, apc.cAppDevPath + apc.cResourcesCommonPath); await haystacks.setConfigurationSetting(wrd.csystem, app_cfg.cdestinationResourcesPath, apc.cAppProdPath + apc.cResourcesCommonPath); await haystacks.consoleLog(namespacePrefix, functionName, msg.creturnDataIs + JSON.stringify(returnData)); await haystacks.consoleLog(namespacePrefix, functionName, msg.cEND_Function); return returnData; } /** * @function deployMetaData * @description Copies application meta-data from the source to the destination. * @param {object} inputData The data that should be transferred to the output file & path. * @param {string} inputMetaData The path the data should be written out to. * @return {boolean} A True or False value to indicate if the data was copied successfully or not. * @author Seth Hollingsead * @date 2022/03/14 Happy Pi day!! 3.141562653589793238462643383279502884197169399 */ async function deployMetaData(inputData, inputMetaData) { let functionName = deployMetaData.name; await haystacks.consoleLog(namespacePrefix, functionName, msg.cBEGIN_Function); await haystacks.consoleLog(namespacePrefix, functionName, msg.cinputDataIs + JSON.stringify(inputData)); await haystacks.consoleLog(namespacePrefix, functionName, msg.cinputMetaDataIs + inputMetaData); let returnData = [true, false]; // inputData.shift(); // Remove the first element of the array, because that is what is used to call this command. // @Reference: {@Link https://stackoverflow.com/questions/9153571/is-there-a-way-to-get-version-from-package-json-in-nodejs-code} let applicationMetaDataPathAndFilename = await haystacks.getConfigurationSetting(wrd.csystem, cfg.cappRootPath); applicationMetaDataPathAndFilename = applicationMetaDataPathAndFilename + bas.cForwardSlash + sys.cpackageDotJson; applicationMetaDataPathAndFilename = path.resolve(applicationMetaDataPathAndFilename); // applicationMetaDataPathAndFilename is: await haystacks.consoleLog(namespacePrefix, functionName, app_msg.capplicationMetaDataPathAndFilenameIs + applicationMetaDataPathAndFilename); let applicationMetaData = await haystacks.executeBusinessRules([applicationMetaDataPathAndFilename, false], [biz.cloadDataFile]); let applicationName = applicationMetaData[wrd.cname]; let applicationVersion = applicationMetaData[wrd.cversion]; let applicationDescription = applicationMetaData[wrd.cdescription]; let metaDataOutput = {}; let figletFont = ''; figletFont = await haystacks.getConfigurationSetting(wrd.csystem, cfg.cfigletFont); console.log(figlet.textSync(applicationName, {font: figletFont, horizontalLayout: wrd.cfull})) console.log(msg.ccurrentVersionIs + applicationVersion); console.log(msg.cApplicationDescriptionIs + applicationDescription); metaDataOutput = { Name: applicationName, Version: applicationVersion, Description: applicationDescription } // Update all these generic fields that come from the metaData.json file. await haystacks.setConfigurationSetting(wrd.csystem, sys.cFrameworkVersionNumber, applicationVersion); await haystacks.setConfigurationSetting(wrd.csystem, sys.cFrameworkName, applicationName); await haystacks.setConfigurationSetting(wrd.csystem, sys.cFrameworkDescription, applicationDescription); let metaDataPathAndFilename = await haystacks.getConfigurationSetting(wrd.csystem, app_cfg.cappResourcesRootPath); metaDataPathAndFilename = path.resolve(metaDataPathAndFilename + sys.cmetaDatadotJson); // metaDataPathAndFilename is: await haystacks.consoleLog(namespacePrefix, functionName, msg.cmetaDataPathAndFilenameIs + metaDataPathAndFilename); // metaDataOutput is: await haystacks.consoleLog(namespacePrefix, functionName, msg.cmetaDataOutputIs + JSON.stringify(metaDataOutput)); returnData[1] = await haystacks.executeBusinessRules([metaDataPathAndFilename, metaDataOutput], [biz.csaveDataFile]); await haystacks.consoleLog(namespacePrefix, functionName, msg.creturnDataIs + JSON.stringify(returnData)); await haystacks.consoleLog(namespacePrefix, functionName, msg.cEND_Function); return returnData; } /** * @function deployApplication * @description Executes the deployment of the application, part of the build-deploy-release cycle. * This command copies the non-source code files from the src folder structure to the bin folder structure. * @param {string} inputData The path the non-code files should be copied from. (SOURCE) * @param {string} inputMetaData The path the non-code files should be copied to. (DESTINATION) * @return {boolean} a True or False value to indicate if the deployment was successful or not. * @author Seth Hollingsead * @date 2022/04/05 */ async function deployApplication(inputData, inputMetaData) { let functionName = deployApplication.name; await haystacks.consoleLog(namespacePrefix, functionName, msg.cBEGIN_Function); await haystacks.consoleLog(namespacePrefix, functionName, msg.cinputDataIs + JSON.stringify(inputData)); await haystacks.consoleLog(namespacePrefix, functionName, msg.cinputMetaDataIs + inputMetaData); let returnData = [true, false]; let passAllConstantsValidation = await haystacks.getConfigurationSetting(wrd.csystem, cfg.cpassAllConstantsValidation); let passAllCommandAliasesDuplicateChecks = await haystacks.getConfigurationSetting(wrd.csystem, cfg.cpassedAllCommandAliasesDuplicateChecks); let passAllWorkflowDuplicateChecks = await haystacks.getConfigurationSetting(wrd.csystem, cfg.cpassedAllWorkflowDuplicateChecks); if (passAllConstantsValidation === true && passAllCommandAliasesDuplicateChecks === true && passAllWorkflowDuplicateChecks === true) { // DEPLOY APPLICATION console.log(msg.cDEPLOY_APPLICATION); let appRootPath = await haystacks.getConfigurationSetting(wrd.csystem, cfg.cappRootPath); // appRootPath is: await haystacks.consoleLog(namespacePrefix, functionName, app_msg.cappRootPathIs + appRootPath); let sourcePath = appRootPath + await haystacks.getConfigurationSetting(wrd.csystem, app_cfg.csourcePath); let destinationPath = appRootPath + await haystacks.getConfigurationSetting(wrd.csystem, app_cfg.cdestinationPath); // sourcePath is: await haystacks.consoleLog(namespacePrefix, functionName, app_msg.csourcePathIs + sourcePath); // destinationPath is: await haystacks.consoleLog(namespacePrefix, functionName, app_msg.cdestinationPathIs + destinationPath); let deploymentStatus = await haystacks.executeBusinessRules([[sourcePath, destinationPath], []], [biz.ccopyAllFilesAndFoldersFromFolderToFolder]); if (deploymentStatus === true) { await haystacks.consoleLog(namespacePrefix, functionName, app_msg.cDeploymentWasCompleted + true); await haystacks.setConfigurationSetting(wrd.csystem, app_cfg.cdeploymentCompleted, true); returnData[1] = true; } else { await haystacks.consoleLog(namespacePrefix, functionName, app_msg.cDeploymentFailed); } } else { if (passAllConstantsValidation === false) { // ERROR: Release failed because of a failure in the constants validation system. Please fix ASAP before attempting another deployment. console.log(app_msg.cdeployApplicationMessage1a + app_msg.cdeployApplicationMessage2a); } // End-if (passAllConstantsValidation === false) if (passAllCommandAliasesDuplicateChecks === false) { // ERROR: Release failed because of a failure in the commands alias validation system. Please fix ASAP before attempting another deployment. console.log(app_msg.cdeployApplicationMessage1b + app_msg.cdeployApplicationMessage2a); } // End-if (passAllCommandAliasesDuplicateChecks === false) } await haystacks.consoleLog(namespacePrefix, functionName, msg.creturnDataIs + JSON.stringify(returnData)); await haystacks.consoleLog(namespacePrefix, functionName, msg.cEND_Function); return returnData; } /** * @function releaseApplication * @description Executes teh release of the application, part of the build-deploy-release cycle. * Scans the specified release folder path and determines if there is a zip file for the current release or not. * If there is not, then the system will build a zip file from the bin folder excluding the release folder, * and save the resulting archie to the release folder. * @param {string} inputData The path or the bin folder where the latest source code will have been deployed. (SOURCE) * @param {string} inputMetaData The path for the release folder where the release zip archive file should be saved. (RELEASE) * @return {boolean} A True or False value to indicate if the zip archive was created successfully or not. * @author Seth Hollingsead * @date 2022/04/07 */ async function releaseApplication(inputData, inputMetaData) { let functionName = releaseApplication.name; await haystacks.consoleLog(namespacePrefix, functionName, msg.cBEGIN_Function); await haystacks.consoleLog(namespacePrefix, functionName, msg.cinputDataIs + JSON.stringify(inputData)); await haystacks.consoleLog(namespacePrefix, functionName, msg.cinputMetaDataIs + inputMetaData); let returnData = [true, false]; let errorMessage = ''; let passAllConstantsValidation = await haystacks.getConfigurationSetting(wrd.csystem, cfg.cpassAllConstantsValidation); let passAllCommandAliasesDuplicateChecks = await haystacks.getConfigurationSetting(wrd.csystem, cfg.cpassedAllCommandAliasesDuplicateChecks); let passAllWorkflowDuplicateChecks = await haystacks.getConfigurationSetting(wrd.csystem, cfg.cpassedAllWorkflowDuplicateChecks); if (passAllConstantsValidation === true && passAllCommandAliasesDuplicateChecks === true && passAllWorkflowDuplicateChecks === true) { // RELEASE APPLICATION console.log(msg.cRELEASE_APPLICATION); let appRootPath = await haystacks.getConfigurationSetting(wrd.csystem, cfg.cappRootPath) // appRootPath is: await haystacks.consoleLog(namespacePrefix, functionName, app_msg.cappRootPathIs + appRootPath); // NOTE: The destinationResourcesPath works out to be the root/bin of the framework, for this next operation that will be our source path. // These source and destination paths are for the bin and release folder paths, used by the zip package to package the release. let sourcePath = appRootPath + await haystacks.getConfigurationSetting(wrd.csystem, app_cfg.cdestinationPath); let destinationPath = appRootPath + apc.cReleasePath; // sourcePath is: await haystacks.consoleLog(namespacePrefix, functionName, app_msg.csourcePathIs + sourcePath); // destinationPath is: await haystacks.consoleLog(namespacePrefix, functionName, app_msg.cdestinationPathIs + destinationPath); returnData[1] = await haystacks.executeBusinessRules([sourcePath, destinationPath], [app_biz.cbuildReleasePackage]); } else { // Technically it should never even get here, because this same condition is caught at the deployApplication command. // The deployApplication command should be executing before this command. if (passAllConstantsValidation === false) { // ERROR: Release failed because of a failure in the constants validation system. Please fix ASAP before attempting another deployment. errorMessage = app_msg.cdeployApplicationMessage1a + app_msg.cdeployApplicationMessage2a; console.log(errorMessage); returnData[1] = errorMessage; } // End-if (passAllConstantsValidation === false) if (passAllCommandAliasesDuplicateChecks === false) { // ERROR: Release failed because of a failure in the commands alias validation system. Please fix ASAP before attempting another deployment. errorMessage = app_msg.cdeployApplicationMessage1b + app_msg.cdeployApplicationMessage2a; console.log(errorMessage); returnData[1] = errorMessage; } // End-if (passAllCommandAliasesDuplicateChecks === false) } await haystacks.consoleLog(namespacePrefix, functionName, msg.creturnDataIs + JSON.stringify(returnData)); await haystacks.consoleLog(namespacePrefix, functionName, msg.cEND_Function); return returnData; } export default { customEchoCommand, resolveAppPath, rectifyAppMetaData, deployMetaData, deployApplication, releaseApplication };