jumbo-core
Version:
Modern lightweight fast enterprise level MVW framework for Node.js
210 lines • 8.74 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const RequestException_1 = require("../exceptions/RequestException");
if (Jumbo.config.jumboDebugMode) {
console.log("[DEBUG] REQUIRE: ControllerFactory");
}
const FUNC_PARAM_REGEX = /^[\s\S]*?\(([\s\S]*?)\)/;
const CTOR_PARAM_REGEX = /^[\s\S]*?constructor\s*\(([\s\S]*?)\)/;
exports.MAIN_SUBAPP_NAME = "_default";
const istanceKey = Symbol.for("Jumbo.Application.ControllerFactory");
let instance = global[istanceKey] || null;
let locator = null;
class ControllerFactory {
constructor() {
this.subApp = {};
if (new.target != ControllerFactoryActivator) {
throw new Error("You cannot call private constructor!");
}
this.loadControllersAndActions();
this.clearRequireCache();
}
static get instance() {
if (instance == null) {
global[istanceKey] = instance = Reflect.construct(ControllerFactory, [], ControllerFactoryActivator);
setImmediate(() => {
locator = Jumbo.Application.Locator.instance;
});
}
return instance;
}
getSubAppId(subApp) {
return subApp.toLowerCase();
}
getControllerId(controller) {
controller = controller.toLowerCase();
if (controller.slice(-10) == "controller")
return controller;
return controller + "controller";
}
getActionId(action, method = "action") {
method = method.toLowerCase();
action = action.toLowerCase();
if (action.slice(0, method.length) == method)
return action;
return method + action;
}
getSubAppName(subApp) {
return this.getSubAppInfo(this.getSubAppId(subApp)).name;
}
getControllerName(controller, subAppId = exports.MAIN_SUBAPP_NAME) {
return this.getControllerInfo(this.getControllerId(controller), subAppId).name;
}
getActionName(action, controllerId, subAppId = exports.MAIN_SUBAPP_NAME, method = "action") {
return this.getActionInfo(this.getActionId(action, method), controllerId, subAppId).name;
}
getSubAppInfo(subAppId) {
let subAppInfo = this.subApp[subAppId];
if (!subAppInfo)
throw new Error(`Sub-app ${subAppId} was not found.`);
return subAppInfo;
}
getControllerInfo(controllerId, subAppId) {
let subAppInfo = this.getSubAppInfo(subAppId);
let controllerInfo = subAppInfo.controllers[controllerId];
if (!controllerInfo)
throw new Error(`Controller ${controllerId} was not found in sub-app ${subAppId}`);
return controllerInfo;
}
getActionInfo(actionId, controllerId, subAppId) {
let controllerInfo = this.getControllerInfo(controllerId, subAppId);
let actionInfo = controllerInfo.actions[actionId];
if (!actionInfo)
throw new Error(`Action ${actionId} was not found in controller ${controllerId} in sub-app ${subAppId}`);
return actionInfo;
}
createController(controllerId, subAppId, scope) {
let ctrlInfo = this.getControllerInfo(controllerId, subAppId);
let Controller = ctrlInfo.getClass();
return scope.resolveUnregistered(Controller);
}
getTargetPoint(subApp, controller, action, method = undefined) {
let controllerId = this.getControllerId(controller);
let actionId = this.getActionId(action, method);
let subId = subApp;
if (subApp == locator.main) {
subId = exports.MAIN_SUBAPP_NAME;
}
let sa = this.subApp[subId];
if (!sa)
throw new RequestException_1.RequestException(`Subapp '${subApp}' doesn't exist.`);
let ctrl = sa.controllers[controllerId];
if (!ctrl)
throw new RequestException_1.RequestException(`Controller '${controller}' of sub-app '${subApp}' doesn't exist.`);
let act = ctrl.actions[actionId] || ctrl.actions[this.getActionId(action)];
if (!act && method == undefined) {
act = this.findAction(ctrl.actions, actionId);
}
if (!act) {
throw new RequestException_1.RequestException(`Action '${actionId}' doesn't exists in controller '${controller}' of sub-app '${subApp}'.`);
}
return {
subApp: sa.name,
controller: ctrl.name,
action: act.name
};
}
getFunctionParameters(func) {
return this.getParameters(func, FUNC_PARAM_REGEX);
}
getConstructorParameters(func) {
return this.getParameters(func, CTOR_PARAM_REGEX);
}
findAction(actions, action) {
action = action.toLowerCase();
let actNames = Object.keys(actions);
let actionVariant = [];
for (let method of Locator_1.ActionTypes) {
actionVariant.push(method + action);
}
let actionName = actNames.find(act => actionVariant.includes(act));
if (actionName != undefined) {
return actions[actionName];
}
return undefined;
}
getParameters(func, regex) {
let matchArgs = func.toString().match(regex);
let args = [];
if (matchArgs) {
args = matchArgs[1].replace(/\s/g, "").split(",");
if (args.length == 1 && args[0] == "") {
args = [];
}
}
return args;
}
loadActionsFromController(ctrl) {
let proto = ctrl.prototype;
let actions = {};
for (let actionName of Object.getOwnPropertyNames(proto)) {
for (let actionType of Locator_1.ActionTypes) {
if (actionName.substr(0, actionType.length) == actionType) {
let args = this.getFunctionParameters(proto[actionName]);
actions[actionName.toLowerCase()] = {
name: actionName,
params: args,
method: actionType == "action" ? null : actionType.toUpperCase()
};
}
}
}
return actions;
}
loadControllersFromNamespace(namespace, subAppId, appendTo = {}) {
for (let controllerName of Object.getOwnPropertyNames(namespace)) {
let item = namespace[controllerName];
if (item.constructor == Object) {
this.loadControllersFromNamespace(item, subAppId, appendTo);
continue;
}
else if (item.prototype == undefined) {
Jumbo.Logging.Log.error(`Controllers.${controllerName} doesn't export class.`);
continue;
}
appendTo[controllerName.toLowerCase()] = {
name: controllerName,
params: this.getConstructorParameters(item.prototype.constructor),
getClass: () => item,
actions: this.loadActionsFromController(item)
};
}
return appendTo;
}
camelToKebabCase(subApp) {
return subApp.charAt(0).toLowerCase() + subApp.substr(1).replace(/[A-Z]/g, function (char) {
return "-" + char.toLowerCase();
});
}
loadControllersAndActions() {
const AppNamespace = require("jumbo-core/autoloader/autoloader").App;
if (Object.keys(AppNamespace.SubApps).length) {
let subApps = Object.getOwnPropertyNames(AppNamespace.SubApps);
let sc = subApps.length;
let subAppName;
for (let sp = 0; sp < sc; sp++) {
subAppName = subApps[sp];
this.subApp[subAppName.toLowerCase()] = {
name: subAppName,
dir: this.camelToKebabCase(subAppName),
controllers: this.loadControllersFromNamespace(AppNamespace.SubApps[subAppName].Controllers, subAppName.toLowerCase()),
};
}
}
this.subApp[exports.MAIN_SUBAPP_NAME] = {
name: exports.MAIN_SUBAPP_NAME,
dir: Jumbo.APP_DIR,
controllers: this.loadControllersFromNamespace(AppNamespace.Controllers, exports.MAIN_SUBAPP_NAME)
};
}
clearRequireCache() {
}
}
exports.ControllerFactory = ControllerFactory;
class ControllerFactoryActivator extends ControllerFactory {
}
const Locator_1 = require("jumbo-core/application/Locator");
if (Jumbo.config.jumboDebugMode) {
console.log("[DEBUG] REQUIRE: ControllerFactory END");
}
//# sourceMappingURL=ControllerFactory.js.map