simpleitjs
Version:
Simple light frontend framework
285 lines (284 loc) • 10.1 kB
JavaScript
"use strict";
/// <reference path="./module-scope.ts" />
var __spreadArrays = (this && this.__spreadArrays) || function () {
for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
for (var r = Array(s), k = 0, i = 0; i < il; i++)
for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
r[k] = a[j];
return r;
};
var moduleCollection = [];
var readyModules = {};
var modules = {};
var ModuleScopeMain;
if (typeof window === "undefined") {
ModuleScopeMain = require('./module-scope');
}
else {
var win = window;
ModuleScopeMain = win.ModuleScope;
}
var ModuleType;
(function (ModuleType) {
ModuleType[ModuleType["Standard"] = 0] = "Standard";
ModuleType[ModuleType["Class"] = 1] = "Class";
})(ModuleType || (ModuleType = {}));
/**
* Creates a new Module, attaches dependencies
* @param {string} Name 1st aargument, name of module to be registed.
* @param {string[]} Dependencies 2nd to 2nd last argument, dependencies of the module.
* @param {Function} ReadyFnc Last argument, resolved ready function.
* @returns {{name:string;dependencies:string[];readyFnc:Function;scope:Object}}
*/
var Module = /** @class */ (function () {
function Module() {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
this.type = ModuleType.Standard;
var dependencies = [];
var allReady = true;
for (var i = 1; i < arguments.length - 1; i++) {
dependencies.push(arguments[i]);
if (!readyModules[arguments[i]]) {
allReady = false;
}
}
this.name = arguments[0];
this.dependencies = dependencies;
this.readyFnc = arguments[arguments.length - 1];
this.scope = new ModuleScopeMain();
this.moduleHolder = new ModuleScopeMain();
if (typeof arguments[arguments.length - 2] == "object") {
this.constructionOpts = arguments[arguments.length - 2];
dependencies.pop();
}
if (typeof arguments[arguments.length - 3] == "object") {
this.moduleOpts = arguments[arguments.length - 3];
dependencies.pop();
}
if (this.moduleOpts) {
this.type = this.moduleOpts.type;
}
moduleCollection.push(this);
if (dependencies.length == 0 || allReady) {
this.releaseModule(this);
this.checkNReleaseMods();
}
else {
var res = this.checkInterDependency(this);
if (res) {
this.releaseModules(res);
}
}
}
/**
* Returns list of unresolved modules.
* @param {string[]} mods modules names
*/
Module.prototype.getUnResolvedModules = function (mods) {
var unreadyMods = [];
for (var i = 0; i < mods.length; i++) {
if (!readyModules[mods[i]]) {
unreadyMods.push(mods[i]);
}
}
return unreadyMods;
};
/**
* Returns module by name
* @param {string} name module name
* @returns {Module}
*/
Module.getModuleByName = function (name) {
for (var i = 0; i < moduleCollection.length; i++) {
if (moduleCollection[i].name == name) {
return moduleCollection[i];
}
}
return null;
};
Module.prototype.checkInterDependency = function (module, overTimeReady) {
if (overTimeReady === void 0) { overTimeReady = {}; }
var unReadyMods = this.getUnResolvedModules(module.dependencies);
var registered = false;
for (var i = 0; i < unReadyMods.length; i++) {
registered = false;
for (var j = 0; j < moduleCollection.length; j++) {
if (moduleCollection[j].name == unReadyMods[i]) {
registered = true;
break;
}
}
if (!registered) {
break;
}
}
if (registered) {
overTimeReady[module.name] = true;
var resArr = [module.name];
var allReady = true;
for (var i = 0; i < unReadyMods.length; i++) {
if (!overTimeReady[unReadyMods[i]]) {
allReady = false;
var mod = Module.getModuleByName(unReadyMods[i]);
if (!mod) {
return false;
}
var res = this.checkInterDependency(mod, overTimeReady);
if (res) {
for (var j = 0; j < res.length; j++) {
if (resArr.indexOf(res[i]) == -1) {
resArr.push(res[i]);
}
}
}
else {
return false;
}
}
else {
if (resArr.indexOf(unReadyMods[i]) == -1) {
resArr.push(unReadyMods[i]);
}
}
}
return resArr;
}
else {
return false;
}
};
/**
* Releases all modules with support to interdependency on each other.
* @param {string[]} moduleNames module names in string list.
*/
Module.prototype.releaseModules = function (moduleNames) {
for (var i = 0; i < moduleNames.length; i++) {
var module = Module.getModuleByName(moduleNames[i]);
if (!module) {
continue;
}
readyModules[moduleNames[i]] = true;
var inst = void 0;
if (typeof this.constructionOpts != "undefined") {
inst = new module.readyFnc(this.constructionOpts);
}
else {
inst = new module.readyFnc();
}
module.scope = new ModuleScopeMain();
modules[module.name] = inst;
}
for (var i = 0; i < moduleNames.length; i++) {
var module = Module.getModuleByName(moduleNames[i]);
if (!module) {
continue;
}
var resolvedDeps = [];
for (var j = 0; j < module.dependencies.length; j++) {
resolvedDeps.push(modules[module.dependencies[j]]);
}
module.moduleHolder = module.readyFnc.invoke.apply(module.scope, __spreadArrays([module.scope], resolvedDeps));
if (module.moduleHolder) {
modules[module.name] = module.moduleHolder;
}
else {
modules[module.name] = module.scope;
}
}
};
/**
* Checks and releases modules from main collection
*/
Module.prototype.checkNReleaseMods = function () {
for (var i = 0; i < moduleCollection.length; i++) {
var currMod = moduleCollection[i];
if (!readyModules[currMod.name] && this.areDepLoaded(currMod)) {
this.releaseModule(currMod);
}
}
};
;
/**
* Checks if dependencies are loaded or not.
* @param {Module} module Module to check
* @returns {boolean}
*/
Module.prototype.areDepLoaded = function (module) {
for (var i = 0; i < module.dependencies.length; i++) {
if (!readyModules[module.dependencies[i]]) {
return false;
}
}
return true;
};
/**
* Releases module, calls its ready function.
* @param {Module} module Module to release.
*/
Module.prototype.releaseModule = function (module) {
readyModules[module.name] = true;
var inst;
if (typeof this.constructionOpts != "undefined") {
inst = new module.readyFnc(this.constructionOpts);
}
else {
inst = new module.readyFnc();
}
module.scope = inst;
var resolvedDeps = [];
for (var j = 0; j < module.dependencies.length; j++) {
resolvedDeps.push(modules[module.dependencies[j]]);
}
module.moduleHolder = module.readyFnc.invoke.apply(module.scope, __spreadArrays([module.scope], resolvedDeps));
if (module.moduleHolder) {
modules[module.name] = module.moduleHolder;
}
else {
modules[module.name] = module.scope;
}
};
;
/**
* Returns module by name
* @param {string} name name of module to get.
*/
Module.get = function (name) {
var mod = Module.getModuleByName(name);
if (mod && mod.type === ModuleType.Class && mod.readyFnc) {
return mod.readyFnc;
}
return modules[name];
};
/**
* Extends module by calling given function, module score is provided as arg and expected new updated scope.
* Use this to extend functionality
* @param {string} name name of module to get.
* @param {Function} fnc extnding callback function.
*/
Module.extend = function (name, fnc) {
var scope = Module.get(name);
var out = fnc.call(scope, scope);
if (out) {
modules[name] = out;
var mod = Module.getModuleByName(name);
if (mod) {
mod.scope = out;
}
}
};
return Module;
}());
(function () {
if (typeof window !== "undefined") {
var win = window;
win.SimpleJS = win.SimpleJS || {};
win.SimpleJS.Module = Module;
win.SimpleJS.ModuleType = ModuleType;
}
})();
if (typeof module != "undefined" && typeof module.exports != "undefined") {
module.exports = Module;
}