UNPKG

ima

Version:

IMA.js framework for isomorphic javascript application

192 lines (174 loc) 5.82 kB
(function() { var root; if (typeof window !== 'undefined' && window !== null) { root = window; } else { root = global; } root.$IMA = root.$IMA || {}; var modules = {}; root.$IMA.Loader = { modules: modules, register: function(moduleName, dependencies, moduleFactory) { this.modules[moduleName] = { dependencies: dependencies, dependencyOf: [], factory: moduleFactory, instance: null }; }, replaceModule: function(moduleName, dependencies, moduleFactory) { var moduleDescriptor = this.modules[moduleName]; if (!moduleDescriptor) { throw new Error( 'You must register module "' + moduleName + '" at first.' ); } Object.keys(this.modules).forEach(function(modulePath) { var module = root.$IMA.Loader.modules[modulePath]; module.dependencies.forEach(function(dependency) { if (resolveModuleName(modulePath, dependency) === moduleName) { module.instance = null; } }); }); moduleDescriptor.dependencies = dependencies; moduleDescriptor.factory = moduleFactory; moduleDescriptor.dependencyOf = []; moduleDescriptor.instance = null; return resolveModule(moduleName); }, import: function(moduleName) { return Promise.resolve(this.importSync(moduleName)); }, importSync: function(moduleName) { if (!this.modules[moduleName]) { throw new Error( '$IMA.Loader.importSync: Module name ' + moduleName + ' is not registered. Update your build.js.' ); } return resolveModule(moduleName); }, initAllModules: function() { try { Object.keys(modules).forEach(function(moduleName) { resolveModule(moduleName); }); } catch (e) { return Promise.reject(e); } return Promise.resolve(); } }; function resolveModule(moduleName, dependencyOf, parentDependencySetter) { if (!modules[moduleName]) { throw new Error( '$IMA.Loader.import: Module name ' + moduleName + (dependencyOf ? ' (dependency of ' + dependencyOf + ')' : '') + ' is not registered. Update your build.js.' ); } var module = modules[moduleName]; if ( parentDependencySetter && module.dependencyOf.indexOf(parentDependencySetter) === -1 ) { // This is required for circular dependencies module.dependencyOf.push(parentDependencySetter); } if (module.instance) { return module.instance; } var moduleInstance = {}; var moduleInitializer = module.factory(function _export(key, value) { // when exporting only functions, all of them are packed as object and sent as a key if (typeof key === 'object') { Object.keys(key).forEach(function(innerKey) { moduleInstance[innerKey] = key[innerKey]; }); } else { moduleInstance[key] = value; } // The exported values have been updated, notify the modules that // depend on this one - this is required for circular dependencies. module.dependencyOf.forEach(function(dependencySetter) { dependencySetter(moduleInstance); }); }); module.instance = moduleInstance; // allow lazy circular dependencies module.dependencies.forEach(function(dependencyName, index) { var resolvedName = resolveModuleName(moduleName, dependencyName); var setter = moduleInitializer.setters[index]; var dependency = resolveModule(resolvedName, moduleName, setter); setter(dependency); }); try { moduleInitializer.execute(); } catch (error) { throw new Error( 'The module ' + moduleName + ' throw error during initialization. ' + error.message ); } return moduleInstance; } function resolveModuleName(currentModule, referencedModule) { var modulePath; if (referencedModule.substring(0, 2) === './') { if (currentModule.indexOf('/') > -1) { modulePath = currentModule.substring(0, currentModule.lastIndexOf('/')) + '/' + referencedModule.substring(2); } else { // the current module is in the application's root modulePath = referencedModule.substring(2); } } else if (referencedModule.substring(0, 3) === '../') { if (currentModule.indexOf('/') === -1) { throw new Error( 'The ' + currentModule + ' module imports from the ' + 'module ' + referencedModule + ' which may reside ' + 'outside of the application directory' ); } modulePath = currentModule.substring(0, currentModule.lastIndexOf('/')); modulePath = modulePath.substring(0, modulePath.lastIndexOf('/')) + '/' + referencedModule.substring(3); } else { return referencedModule; } modulePath = modulePath.replace(/\/\/+/g, '/'); while (modulePath.indexOf('/./') > -1) { modulePath = modulePath.replace(/\/[.][/]/g, '/'); } while (modulePath.indexOf('../') > -1) { if (modulePath.substring(0, 3) === '../') { throw new Error( 'The ' + currentModule + ' module imports from the ' + 'module ' + referencedModule + ' which may reside ' + 'outside of the application directory' ); } modulePath = modulePath.replace(/\/[^.][^/]*\/[.][.]\//g, '/'); modulePath = modulePath.replace(/^[^.][^/]*\/[.][.]\//g, ''); } modulePath = modulePath.replace(/^[.][/]/g, ''); return modulePath; } })();