const path = require("path"); const execSync = require("child_process").execSync; // // Check Os Type is Windows or not ... var isWin = process.platform === "win32"; // // Prepare Exec Path ... const currentPath = __dirname; const execPathSource = path.join(currentPath, "..", ".."); // let execPath = execPathSource; if (isWin) { execPath = execPathSource; } else { execPath = replaceAll(" ", execPathSource, "\\ "); } // const cmdSeparator = isWin ? "&" : "&&"; const argPrefix = "**"; // // Default Module Versions ... const defaultModuleVersiom = "1.0.0"; // // Define Modules Descriptors by order ... const supportedModules = [ // // xExceptions ... { name: "xExceptions", cmdPrefix: "Exceptions", version: "", }, // // xCommons ... { name: "xCommons", cmdPrefix: "Commons", version: "", }, // // xModels ... { name: "xModels", cmdPrefix: "Models", version: "", }, // // xMessageService ... { name: "xMessageService", cmdPrefix: "MessageService", version: "", }, // // xStorageService ... { name: "xStorageService", cmdPrefix: "StorageService", version: "", }, // // xDataService ... { name: "xDataService", cmdPrefix: "DataService", version: "", }, // // xIdentityModels ... { name: "xIdentityModels", cmdPrefix: "IdentityModels", version: "", }, // // xHttpService ... { name: "xHttpService", cmdPrefix: "HttpService", version: "", }, // // xIdentityService ... { name: "xIdentityService", cmdPrefix: "IdentityService", version: "", }, // // xPushService ... { name: "xPushService", cmdPrefix: "PushService", version: "", }, // // xEventService ... { name: "xEventService", cmdPrefix: "EventService", version: "", }, // // xStringService ... { name: "xStringService", cmdPrefix: "StringService", version: "", }, // // xTermsAndConditionsService ... { name: "xTermsAndConditionsService", cmdPrefix: "TermsAndConditionsService", version: "", }, // // xCategoryService ... { name: "xCategoryService", cmdPrefix: "CategoryService", version: "", }, // // xTagService ... { name: "xTagService", cmdPrefix: "TagService", version: "", }, // // xFileService ... { name: "xFileService", cmdPrefix: "FileService", version: "", }, // // xWebinarService ... { name: "xWebinarService", cmdPrefix: "WebinarService", version: "", }, // // xAiModels ... { name: "xAiModels", cmdPrefix: "AiModels", version: "", }, // // xAiService ... { name: "xAiService", cmdPrefix: "AiService", version: "", }, ]; // // Define Per Module Actions ... const supportedActions = [ { name: "clean", description: "Clean Project ...", placeHolder: "dotnet clean ./Modules/MODULE_NAME/MODULE_NAME.csproj", }, { name: "restore", description: "Restore Project Dependencies ...", placeHolder: "dotnet restore ./Modules/MODULE_NAME/MODULE_NAME.csproj", }, { name: "build", description: "Build Project ...", placeHolder: "dotnet build ./Modules/MODULE_NAME/MODULE_NAME.csproj", }, { name: "rmBin", description: "Remove bin folder of Project ...", placeHolder: "shx --silent rm -rf ./Modules/MODULE_NAME/bin", }, { name: "clearPacked", description: "Removes Module Packed file from pack folder ...", placeHolder: "shx --silent rm ./Documents/pack/xDashboard.MODULE_NAME.*", }, { name: "pack", description: "Pack Project as a Nuget Package ...", placeHolder: "dotnet pack -c Release ./Modules/MODULE_NAME/MODULE_NAME.csproj", }, { name: "cp", description: "Copy Project Packed file to pack folder ...", placeHolder: "shx --silent cp ./Modules/MODULE_NAME/bin/Release/*.nupkg ./Documents/pack", }, { name: "nugetPublish", description: "Push Project Nuget Package's to Server ...", placeHolder: "npm run nugetHandler push ./Documents/pack/xDashboard.MODULE_NAME.MODULE_VERSION.nupkg", }, { name: "nugetDelete", description: "Remove Nuget Package's from Server ...", placeHolder: "npm run nugetHandler delete xDashboard.MODULE_NAME MODULE_VERSION", }, ]; // // Compound Actions ... // these type do multiple actions on a single module ... const supportedCompoundActions = [ { name: "repack", description: "repack a module as nuget package on pack folder ...", actions: ["rmBin", "build", "pack", "cp"], }, { name: "publish", description: "publish a module as nuget package on nuget server ...", actions: [ "rmBin", "pack", "cp", "nugetPublish", "npm run clearNugetTempHttpCache", "npm run rmDashboardNugets", ], }, { name: "rePublish", description: "republish a module as nuget package on nuget server ...", actions: [ "nugetDelete", "rmBin", "pack", "cp", "nugetPublish", "npm run clearNugetTempHttpCache", "npm run rmDashboardNugets", ], }, ]; // // Supported Cli Commands ... const supportedCommands = [ // // 1 { arg: "help", description: "show command helps ...", }, // // 2 { arg: "ls-commands", description: "show a list of supported commands ...", }, // // 3 { arg: "list-commands", description: "show a list of supported commands ...", }, // // 4 { arg: "ls-modules", description: "show a list of supported modules ...", }, // // 5 { arg: "list-modules", description: "show a list of supported modules ...", }, // // 6 { arg: "get", description: "retrieve an specific command text for specific module ...", }, // // 7 { arg: "get-script", description: "retrieve an specific script node of specific command for specific module ...", }, // // 8 { arg: "do", description: "run an specific command text for specific module ...", }, // // TODO: Remove this ... // 9 // { // arg: "do-on", // description: // "do an specific action on all exists or specified comma seperated modules ...", // }, // // 10 // { // arg: "get-do-on", // description: // "get specific action command on all exists or specified comma seperated modules ...", // }, // // 11 { arg: "module-scripts", description: "generate an scripts list for specific module ...", }, // // 12 { arg: "m-scripts", description: "generate an scripts list for specific module ...", }, // // 13 { arg: "scripts", description: "generate an scripts list for all modules ...", }, ]; // //#region Startup ... // // Start App ... const cmdCommands = extractCMDCommands(); if (cmdCommands == null || cmdCommands.length == 0) { doCMD({ arg: "help", index: 0 }); } else { for (var cmd of cmdCommands) { doCMD(cmd); } } //#endregion // //#region Providers ... /** * each supported cmd args must start by argPrefix to be processed, this is a method to clear it from specific value ... * @param {string} arg the arg text ... * @returns normallize arg string ... */ function normallizedArg(arg) { return `${arg}`.replace(argPrefix, ""); } /** * search all occurance of specific value on an string and replace it with specified string ... * @param {string} searchString the value which need to changed ... * @param {string} source the placeholder value for searching ... * @param {string} replaceWith a value which going to replaced with searchValue ... * @returns string */ function replaceAll(searchString, source, replaceWith) { // let result = `${source}` .split(searchString) .map((p) => p.indexOf(searchString) > -1 ? p.replace(searchString, replaceWith) : p ) .map((a, i, arr) => (i < arr.length - 1 ? a + replaceWith : a)) .join(""); // return result; } /** * retrieve all available cmd args ... * @returns an string array ... */ function getCMDs() { return supportedCommands.map((sc) => sc.arg); } /** * check an specific arg is in supported commands list or not ... * @param {string} cmd the command arg * @returns boolean */ function isCMDExists(cmd) { // cmd = normallizedArg(cmd); return getCMDs().includes(cmd); } /** * retrieve all inputted args object models ... * @returns an array of cmd arg object models ... */ function getReceivedArgs() { return process.argv.map((arg, index) => { return { arg: arg.endsWith("/") || arg.endsWith("\\") ? arg.substr(0, arg.length - 1) : arg, index: index, }; }); } /** * retrieve all exists and supported cmd args from received args ... * @returns an array of cmd arg object models ... */ function extractCMDCommands() { return getReceivedArgs() .filter( (a) => a.arg.length > 2 && a.arg.startsWith(argPrefix) && isCMDExists(a.arg) ) .map((a) => { return { arg: normallizedArg(a.arg), index: a.index }; }); } /** * check a module exists on system supported modules or not ... * @param {string} module system supported module name ... * @returns boolean */ function isModuleExists(module) { return supportedModules.findIndex((a) => a.name == module) >= 0; } /** * get supported module model object, if exists ... * * @param {string} module system supported module name ... * @param {string} version module version ... * @returns an object which represent moduleModel ... */ function getModule(module, version) { // let result = supportedModules.find((a) => a.name == module); if (result) { result = { ...result, version: version || defaultModuleVersiom, }; } // return result; } /** * retrieve just module name ... * * @param {string} moduleName desired module name ... * @returns cleared version module name ... */ function getModuleName(moduleName) { // if (!moduleName || moduleName === "") { return moduleName; } // if (!moduleName.includes("@")) { return moduleName; } // const parts = moduleName.split("@"); if (!parts || parts.length < 2) { return moduleName; } // return parts[0]; } /** * retrieve module versionm ... * * @param {string} moduleName desired module name ... * @returns module version or default module version ... */ function getModuleVersion(moduleName) { // if (!moduleName || moduleName === "") { return defaultModuleVersiom; } // if (!moduleName.includes("@")) { return defaultModuleVersiom; } // const parts = moduleName.split("@"); if (!parts || parts.length < 2) { return defaultModuleVersiom; } // return parts[1]; } /** * get npm script object model for specific single action on specific module ... * @param {string} action system supported single action name ... * @param {string} module system supported module name ... * @param {string} version module version ... * @returns script descriptor object model, null ... */ function getScript(action, module, version) { // const command = getCommand(action, module); // const actionModel = getAction(action); if (!actionModel) { throw "Invalid Action: " + action; } // const moduleModel = getModule(module, version); // return { name: actionModel.name + moduleModel.cmdPrefix, cmd: command, }; } /** * get npm script object model for specific compound action on specific module ... * @param {string} action system supported compound action name ... * @param {string} module system supported module name ... * @param {string} version module version ... * @param {bool} byScriptName determines extracted command based on script name or raw command ... * @returns script descriptor object model, null ... */ function getCompoundScript(action, module, version, byScriptNames) { // const command = getCompoundCommand(action, module, version, byScriptNames); // const actionModel = getCompoundAction(action); if (!actionModel) { throw "Invalid Action: " + action; } // const moduleModel = getModule(module, version); // return { name: actionModel.name + moduleModel.cmdPrefix, cmd: command, }; } /** * get supported single action model object, if exists ... * @param {string} action system supported action name ... * @returns an object which represent actionModel ... */ function getAction(action) { return supportedActions.find((a) => a.name == action); } /** * get supported compound action model object, if exists ... * @param {string} action system supported coumpound action name ... * @returns an object which represent actionModel ... */ function getCompoundAction(action) { return supportedCompoundActions.find((a) => a.name == action); } /** * generate command for specific single action on specific module ... * @param {string} action system supported action name ... * @param {string} module system supported module name ... * @param {string} version module version ... * @param {bool} byScriptName determines extracted command based on script name or raw command ... * @returns command string ... */ function getCommand(action, module, version, byScriptName = false) { // const actionExists = isActionExists(action); if (!actionExists) { return action; } // const actionModel = getAction(action); if (module) { // const moduleExists = isModuleExists(module); if (!moduleExists) { throw "Module not found: " + module; } } // const moduleModel = getModule(module, version); // let result = ""; // result = byScriptName ? `npm run ${getScript(action, module).name}` : replaceAll("MODULE_NAME", actionModel.placeHolder, moduleModel.name); if (actionModel.name == "nugetPublish" || actionModel.name == "nugetDelete") { result = result.replace("MODULE_VERSION", moduleModel.version); } // return result; } /** * generate command for specific compound action on specific module ... * @param {string} action system supported coumpound action name ... * @param {string} module system supported module name ... * @param {string} version module version ... * @param {bool} byScriptName determines extracted command based on script name or raw command ... * @returns command string ... */ function getCompoundCommand(action, module, version, byScriptNames = false) { // const actionExists = isCompoundActionExists(action); if (!actionExists) { throw "Compund Action Not Found: " + action; } // const moduleExists = isModuleExists(module); if (!moduleExists) { throw "Module not found: " + module; } // const actionModel = getCompoundAction(action); // let result = ""; actionModel.actions.forEach((a) => { // const cmd = getCommand(a, module, version); const script = isActionExists(a) ? getScript(a, module, version) : null; // if (result.length > 0) { result = result + ` ${byScriptNames ? "&&" : cmdSeparator} `; } // result += byScriptNames ? script == null ? cmd : "npm run " + script.name : cmd; }); // return result; } /** * check an action exists in supported single actions or not ... * @param {string} action system supported action name ... * @returns boolean */ function isActionExists(action) { return supportedActions.findIndex((a) => a.name == action) >= 0; } /** * check an action exists in supported compound actions or not ... * @param {string} action system supported compound action name ... * @returns boolean */ function isCompoundActionExists(action) { return supportedCompoundActions.findIndex((a) => a.name == action) >= 0; } /** * do specific cmd arg command ... * @param {object} param0 cmd arg object model ... */ function doCMD({ arg, index }) { // var isExists = isCMDExists(arg); if (!isExists) { throw "Command not found: " + arg; } // const args = getReceivedArgs(); // const nextArg = args[index + 1]; const actionName = nextArg == null ? null : isCMDExists(nextArg.arg) ? null : nextArg.arg; const isSingle = isActionExists(actionName); const isCompound = isCompoundActionExists(actionName); const actionModel = actionName == null ? null : isSingle ? getAction(actionName) : isCompound ? getCompoundAction(actionName) : actionName; // const nextOfNextArg = args[index + 2]; const moduleNameExpressionm = nextOfNextArg == null ? null : isCMDExists(nextOfNextArg.arg) ? null : nextOfNextArg.arg; // const moduleName = getModuleName(moduleNameExpressionm); const moduleVersion = getModuleVersion(moduleNameExpressionm); const isItExistsModule = isModuleExists(moduleName); const moduleModel = !isItExistsModule || moduleName == null ? null : getModule(moduleName, moduleVersion); // switch (arg) { // case "help": // console.log("Supported Commands: "); console.log("========================="); supportedCommands.forEach((c) => { // console.log(" "); console.warn(c.arg); console.log(c.description); }); console.log(" "); break; // case "ls-commands": case "list-commands": // console.log("Supported Actions: "); console.log("========================="); // console.log(" "); console.log("1/2 => Single Actions:"); console.log("==========================="); supportedActions.forEach((a) => { // console.log(" "); console.warn(a.name); console.log(a.description); }); console.log(" "); // console.log(" "); console.log("2/2 => Compound Actions:"); console.log("==========================="); supportedCompoundActions.forEach((a) => { // console.log(" "); console.warn(a.name); console.log(a.description); }); console.log(" "); break; // case "ls-modules": case "list-modules": // console.log("Available Modules: "); console.log("========================="); supportedModules.forEach((m, i) => { console.warn(i + 1, " => ", m.name); }); console.log(" "); break; // case "do": case "get": doOrGetCommandHandler(actionModel, moduleModel, arg !== "do"); break; // case "get-script": // if (actionModel == null) { throw "invalid action ..."; } // if (moduleModel == null) { throw "invalid module ..."; } // const script = isSingle ? getScript(actionName, moduleName) : isCompound ? getCompoundScript(actionName, moduleName) : null; // if (script == null) { console.log("there is no script for action: ", actionModel); } else { logScript(script); } break; // // TODO: Remove this ... // case "do-on": // case "get-do-on": // doOrGetOnCommandHandler(index, args, actionModel, arg !== "do-on"); // break; // case "m-scripts": case "module-scripts": // const moduleArg = args[index + 1]; const scriptModuleName = moduleArg == null ? null : isCMDExists(moduleArg.arg) ? null : !isModuleExists(moduleArg.arg) ? null : moduleArg.arg; const destModuleModel = scriptModuleName == null ? null : getModule(scriptModuleName); // if (destModuleModel == null) { throw "invalid module ..."; } // console.log( "Export all available scripts for module: ", scriptModuleName ); console.log( "====================================================================" ); console.log(" "); // // Single ... for (const a of supportedActions) { // const script = getScript(a.name, scriptModuleName); logScript(script); } // // Compound ... for (const a of supportedCompoundActions) { // const script = getCompoundScript(a.name, scriptModuleName, true); logScript(script); } break; // case "scripts": // supportedModules.forEach((m) => { // // Single ... supportedActions.forEach((a) => { // const script = getScript(a.name, m.name); logScript(script); }); // // Compound ... supportedCompoundActions.forEach((a) => { // const script = getCompoundScript(a.name, m.name, true); logScript(script); }); }); // supportedActions.forEach((a) => { // const scriptName = `${a.name}AllModules`; const scriptCmd = getAllCommandsForAction(a.name, true); // logScript({ name: scriptName, cmd: scriptCmd }); }); // supportedCompoundActions.forEach((a) => { // const scriptName = `${a.name}AllModules`; const scriptCmd = getAllCommandsForAction(a.name, true); // logScript({ name: scriptName, cmd: scriptCmd }); }); break; } } /** * handle execution, or log specific single or compound action model object on specific module model object ... * @param {object} actionModel action descriptor module ... * @param {object} moduleModel module descriptor model ... * @param {bool} justLog determines just log the command or just execute it ... */ function doOrGetCommandHandler(actionModel, moduleModel, justLog = true) { // if (!actionModel || actionModel == null) { throw "invalid action ..."; } // const isSingle = isActionExists( actionModel.name ? actionModel.name : actionModel ); const isCompound = isCompoundActionExists( actionModel.name ? actionModel.name : actionModel ); // if ((isSingle || isCompound) && moduleModel == null) { throw "invalid module ..."; } // if (!isSingle && !isCompound) { if (justLog) { console.log(actionModel); } else { executeInPath(actionModel); } } else { // const cmdText = isSingle ? getCommand(actionModel.name, moduleModel.name, moduleModel.version) : isCompound ? getCompoundCommand( actionModel.name, moduleModel.name, moduleModel.version ) : ""; // if (justLog) { console.log(cmdText); } else { executeInPath(cmdText); } } } /** * log specific script object model to console ... * @param {object} script script descriptor object model ... */ function logScript(script) { console.log(`"${script.name}": "${script.cmd}"`); } /** * execute an specific command on a path, if path is null get default execution path ... * @param {string} cmd command string ... * @param {string?} path the path for execute command on it ... */ function executeInPath(cmd, path) { // if (!path) { path = execPath; } // if (!cmd) { // console.error("command not found ..."); throw "command not found ..."; } // console.log(" "); console.log("executing: ", cmd); // try { // const cmdInPath = path === "" || path === null || path === undefined ? "" : "cd " + path + " " + cmdSeparator + " " + cmd; // execSync(cmdInPath); } catch (ex) { // const errMsg = `Execution of ${cmd} failed with reason: ${ex} ...`; console.error(errMsg); throw "execution failed ..."; } // console.log("done"); } //#endregion Providers ...