UNPKG

simpleitjs

Version:
285 lines (284 loc) 10.1 kB
"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; }