whs
Version:
Super-fast 3D framework for Web Applications & Games. Based on Three.js
162 lines (145 loc) • 4.03 kB
JavaScript
import {createStore} from 'redux';
import {DependencyError} from './errors';
/**
* @class ModuleManager
* @category core
* @param {Object} object handler
* @description Solves modules dependencies
* @memberof module:core
*/
export class ModuleManager {
constructor(object) {
this.handler = object;
this.currentModule = null;
this.store = createStore((state = [{}, ''], action) => {
state[0][action.key] = action.data;
state[1] = action.key;
return state;
});
this.modules = {};
}
/**
* @method active
* @instance
* @description Sets .currentModule to provided module.
* @param {Object} module the module to make current
* @memberof module:core.ModuleManager
*/
active(module) {
this.currentModule = module;
}
/**
* @method reset
* @instance
* @description Set's .currentModule to null.
* @memberof module:core.ModuleManager
*/
reset() {
this.currentModule = null;
}
/**
* @method define
* @instance
* @description Define the module in manager
* @param name The module name
* @memberof module:core.ModuleManager
*/
define(name) {
this.modules[name] = this.currentModule;
}
/**
* @method use
* @instance
* @description Get the defined module from manager
* @param name The module name
* @memberof module:core.ModuleManager
*/
use(name) {
return this.modules[name];
}
/**
* @method set
* @instance
* @description An alias for .add() <br/><br/>
* Use this method if you know that you will overwrite existing dependency.<br/>
* Use it in your app, but not in module that you provide to other people.
* @param {String} key the key of the dependency
* @param {Object} data the value of the dependency
* @memberof module:core.ModuleManager
*/
set(key, data) {
this.store.dispatch({
type: 'ADD',
key,
data
});
}
/**
* @method get
* @instance
* @description Returns dependency in store object, by key.
* @param {String} key the key of the dependency
* @memberof module:core.ModuleManager
* @return {Object|Module}
* @throws {DependencyError} if dependency is not in the store
* @example <caption>Get the 'hello' dependency</caption>
* manager.get('hello'); // -> {world: true}
*/
get(key) {
if (!this.store.getState()[0][key]) {
throw new DependencyError(
'ModuleManager',
`Module requires '${key}' dependency`,
this.currentModule
);
}
return this.store.getState()[0][key];
}
/**
* @method has
* @instance
* @description Returns whether manager has a dependency with the given key
* @param {String} key the key of the dependency
* @memberof module:core.ModuleManager
* @return {Boolean} Promise that is resolved when all promises completed.
* @example <caption>Check whether the store has the 'hello' dependency</caption>
* manager.has('hello'); // -> true
*/
has(key) {
return Boolean(this.store.getState()[0][key]);
}
/**
* @method update
* @instance
* @description Updates deps
* @param {Object} [depsMap={}]
* @memberof module:core.ModuleManager
*/
update(depsMap = {}) {
this.store.subscribe(() => {
const [data, changedKey] = this.store.getState();
const callback = depsMap[changedKey];
if (callback) callback(data[changedKey]);
});
}
/**
* @method add
* @alias module:core.ModuleManager#set
* @memberof module:core.ModuleManager
*/
add(...data) {
console.warn('.add() method is deprecated. Use .set() instead');
return this.set(...data);
}
/**
* @method require
* @instance
* @description Require module
* @param {String} name Defined name
* @param {Function} moduleExecutor Function that returns applied module
* @memberof module:core.ModuleManager
*/
require(name, moduleExecutor) {
if (this.use(name) === undefined) this.handler.applyModule(moduleExecutor());
}
}