yax
Version:
Yet another store using redux. (Inspired by vuex and dva)
160 lines (124 loc) • 4.14 kB
JavaScript
import _extends from "@babel/runtime/helpers/extends";
import { createStore, applyMiddleware, compose } from 'redux';
import ModuleCollection from './module/module-collection';
import { isObject, isPromise, getNestedState, assert } from './util';
export default function yax(options, enhancer) {
if (options === void 0) {
options = {};
}
var _actions = {};
var _modules = new ModuleCollection(options); // init root module.
// this also recursively registers all sub-modules
_installModule([], _modules.root);
var middleware = function middleware() {
return function (next) {
return function (action) {
if (isObject(action)) {
var type = action.type,
payload = action.payload;
var entry = _actions[type];
if (entry) {
return entry.length > 1 ? Promise.all(entry.map(function (handler) {
return handler(payload);
})) : entry[0](payload);
}
}
return next(action);
};
};
};
var rootMW = applyMiddleware(middleware);
var _store = createStore(_modules.makeReducers(), options.state || {}, enhancer ? compose(enhancer, rootMW) : rootMW);
function registerModule(path, rawModule) {
if (typeof path === 'string') path = [path];
assert(Array.isArray(path), "module path must be a string or an Array.");
_modules.register(path, rawModule);
_installModule(path, _modules.get(path));
_resetReducers();
}
function unregisterModule(path) {
if (typeof path === 'string') path = [path];
assert(Array.isArray(path), "module path must be a string or an Array.");
_modules.unregister(path);
_resetStore();
_store.dispatch({
type: '@@yax/unregister',
path: path
});
}
return _extends({
registerModule: registerModule,
unregisterModule: unregisterModule
}, _store);
/**
* Private Methods
*/
// make localized dispatch, commit and state
function _makeLocalContext(namespace, path) {
var wrapFn = function wrapFn(type, payload, isRoot) {
var action = {
type: type,
payload: payload
};
if (isObject(type) && type.type) {
isRoot = payload;
action = type;
}
action.type = isRoot ? action.type : namespace + action.type; // redux dispatch
return _store.dispatch(action);
};
var local = {
dispatch: wrapFn,
commit: wrapFn,
select: function select(fn) {
// redux state
var rootState = _store.getState();
var state = getNestedState(rootState, path);
return fn ? fn(state, rootState) : state;
}
};
return local;
}
function _registerAction(type, handler, local) {
var entry = _actions[type] || (_actions[type] = []);
entry.push(function wrappedActionHandler(payload) {
var res = handler({
dispatch: local.dispatch,
commit: local.commit,
select: local.select
}, payload);
if (!isPromise(res)) {
res = Promise.resolve(res);
}
return res;
});
}
function _installModule(path, module) {
var namespace = _modules.getNamespace(path);
var local = module.context = _makeLocalContext(namespace, path);
module.cleanReducers();
module.forEachReducer(function (reducer, key) {
var actionType = namespace + key;
module.addReducer(actionType, reducer);
});
module.forEachAction(function (action, key) {
var actionType = namespace + key;
_registerAction(actionType, action, local);
});
module.forEachChild(function (child, key) {
_installModule(path.concat(key), child);
});
}
function _resetReducers() {
var reducer = _modules.makeReducers();
_store.replaceReducer(reducer);
}
function _resetStore() {
_actions = {}; // init all modules
_installModule([], _modules.root);
_resetReducers();
}
}
export { combineReducers, bindActionCreators, applyMiddleware, compose } from 'redux';
export { composeReducers, mapReducers } from './util';
export { mapState, mapActions } from './helpers';