Files
2026-08-11 22:10:12 +03:30

1048 lines
23 KiB
JavaScript

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 ...