anew
Version:
React and Redux Framework with additional power.
329 lines (254 loc) • 12.5 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
exports.default = createStore;
var _redux = require('redux');
var _reselect = require('reselect');
var _invariant = require('invariant');
var _invariant2 = _interopRequireDefault(_invariant);
var _createBatch = require('./utils/createBatch');
var _createBatch2 = _interopRequireDefault(_createBatch);
var _createReducer = require('./utils/createReducer');
var _createReducer2 = _interopRequireDefault(_createReducer);
var _createReduxAnewProps = require('./utils/createReduxAnewProps');
var _createReduxAnewProps2 = _interopRequireDefault(_createReduxAnewProps);
var _createSetState = require('./utils/createSetState');
var _createSetState2 = _interopRequireDefault(_createSetState);
var _createAnewSelectorHOC = require('./utils/createAnewSelectorHOC');
var _createAnewSelectorHOC2 = _interopRequireDefault(_createAnewSelectorHOC);
var _createPersistStore = require('./utils/createPersistStore');
var _createPersistStore2 = _interopRequireDefault(_createPersistStore);
var _validateFunctionProperty = require('./utils/validateFunctionProperty');
var _validateFunctionProperty2 = _interopRequireDefault(_validateFunctionProperty);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var takenReducerNames = ["done"];
function createStore(_ref) {
var _ref$name = _ref.name,
name = _ref$name === undefined ? 'store' : _ref$name,
_ref$state = _ref.state,
state = _ref$state === undefined ? {} : _ref$state,
_ref$reducers = _ref.reducers,
reducers = _ref$reducers === undefined ? {} : _ref$reducers,
_ref$effects = _ref.effects,
effects = _ref$effects === undefined ? {} : _ref$effects,
_ref$actions = _ref.actions,
actions = _ref$actions === undefined ? {} : _ref$actions,
_ref$selectors = _ref.selectors,
selectors = _ref$selectors === undefined ? {} : _ref$selectors,
persist = _ref.persist,
reducer = _ref.reducer,
enhancer = _ref.enhancer;
(0, _validateFunctionProperty2.default)(name, 'store creation');
/**
* Create Object to preserve reference
*/
var anewStore = {
name: name,
state: state,
reducers: reducers,
actions: actions,
selectors: selectors,
effects: _extends({}, effects),
batches: []
/**
* Create setState method for an immutable state updates.
* This also set this anewStore as the conext
*/
};anewStore.setState = (0, _createSetState2.default)(anewStore);
/**
* Reduce state to new value after dispatching an action
* @param { Object } reduxState Redux State Object (Not Used)
* @param { String } options.type Redux Type
* @param { String } options.payload Redux Payload
* @param { Object } options.state Application Combined State
* @param { Object } options.actions Chain of actions to dispatch
* @return { Object } Updated Anew State Object
*/
var anewReducer = (0, _createReducer2.default)(anewStore, reducer, persist);
/**
* Redux Store
* @type { Object }
*/
var store = (0, _redux.createStore)(anewReducer, anewStore.state, enhancer);
var reduxStore = persist ? (0, _createPersistStore2.default)(store) : store;
/**
* Create anew specific store props
* @type { Object }
*/
reduxStore.anew = (0, _createReduxAnewProps2.default)(anewStore, anewReducer);
/**
* Extend Dispatcher to include reducers, effects, and batch.
*
* Reducers: are pure functions that reduce the state to a shallow clone of
* the previous state with modification. The state object is updated via
* the dispatch method. Reducers receive the state object and a payload list as parameters.
* A reducer defined within the store that lives under an outside namespace receive both
* the active and outside namespace state objects and a payload list as parameters.
*
* Effects: are pure functions that fire regular/batched dispatches. They are useful for
* executing async logic. The context is bound to the anewStore object. Effects receive the
* store object and a payload list as parameters.
*
* Actions: are pure functions that return an action object. They are mainly used for
* user defined reducers that have user defined action types. This can be useful for
* using with pacakges that follow the standard redux api, such as `react-router-redux`.
* Actions receive a payload list as parameters.
*
* Batch: is a dispatch method for executing mutluple dispatches (reducers) via one dispatch
* call. This prevents the need for components to re-render for each dispatch fired. Batch
* also includes a done method which is used to mark the completion of a batch. The done method
* syncs the anewStore state object with the reduxStore state object and clears the
* batch registry.
*
*/
reduxStore.dispatch.reducers = {};
reduxStore.dispatch.effects = {};
reduxStore.dispatch.actions = {};
reduxStore.dispatch.batch = (0, _createBatch2.default)(reduxStore);
/**
* Transfer redux store dispatch methods.
* Avoid referencing for dispatch and batch as their references
* will be updated when stores are combined.
*/
anewStore.dispatch = function (action) {
return reduxStore.dispatch(action);
};
anewStore.batch = function (batch) {
return reduxStore.dispatch.batch(batch);
};
anewStore.batch.done = reduxStore.dispatch.batch.done;
/**
* Trasfer redux store getState methods
*/
anewStore.select = {};
/**
* Populate getState selectors
*/
var selectorKeys = Object.keys(selectors);
var selectorParams = {
select: anewStore.select,
create: (0, _createAnewSelectorHOC2.default)(anewStore, reduxStore)
};
var _loop = function _loop(i, selectorsLen) {
var selectorName = selectorKeys[i];
(0, _validateFunctionProperty2.default)(selectorName, name);
var selectorCreator = selectors[selectorName];
function selectorWithParams() {
if (!selectorParams.core && reduxStore.anew.core) {
selectorParams.core = reduxStore.anew.core.getState;
}
var selector = selectorCreator(selectorParams);
var _selector = selector.apply(undefined, arguments),
ref = _selector.ref,
value = _selector.value;
reduxStore.getState[selectorName] = ref;
anewStore.select[selectorName] = ref;
return value;
}
reduxStore.getState[selectorName] = selectorWithParams;
anewStore.select[selectorName] = selectorWithParams;
};
for (var i = 0, selectorsLen = selectorKeys.length; i < selectorsLen; i++) {
_loop(i, selectorsLen);
}
/**
* Populate dispatch reducers
*/
var reducerKeys = Object.keys(reducers);
var _loop2 = function _loop2(i, reducersLen) {
var reducerName = reducerKeys[i];
(0, _invariant2.default)(takenReducerNames.indexOf(reducerName) === -1, '"' + reducerName + ' is a reserved word. Please choose a different name " ' + ('for "' + reducerName + '" in "' + name + '"'));
var reducer = reducers[reducerName];
var reducerType = typeof reducer === 'undefined' ? 'undefined' : _typeof(reducer);
var isFunction = reducerType === 'function';
var isObject = reducerType === 'object';
(0, _invariant2.default)(isFunction || isObject, 'Store reducers can be functions or objects ' + ('Recieved "' + reducerType + '" ') + ('for "' + reducerName + '" in "' + name + '"'));
if (isFunction) {
reduxStore.dispatch.reducers[reducerName] = function () {
for (var _len = arguments.length, payload = Array(_len), _key = 0; _key < _len; _key++) {
payload[_key] = arguments[_key];
}
return reduxStore.dispatch({
type: anewStore.name + ':' + reducerName,
payload: payload
});
};
reduxStore.dispatch.batch[reducerName] = function () {
for (var _len2 = arguments.length, payload = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
payload[_key2] = arguments[_key2];
}
var batch = { type: anewStore.name + ':' + reducerName, payload: payload };
reduxStore.anew.getBatches().push(batch);
return batch;
};
anewStore.dispatch[reducerName] = reduxStore.dispatch.reducers[reducerName];
anewStore.batch[reducerName] = reduxStore.dispatch.batch[reducerName];
}
};
for (var i = 0, reducersLen = reducerKeys.length; i < reducersLen; i++) {
_loop2(i, reducersLen);
}
/**
* Populate dispatch actions
* Referencing anewStore.dispatch so when reduxStore.dispatch changes
* during combination
*/
reduxStore.dispatch.actions = (0, _redux.bindActionCreators)(anewStore.actions, anewStore.dispatch);
anewStore.actions = reduxStore.dispatch.actions;
/**
* Populate dispatch effects
*/
var effectKeys = Object.keys(effects);
var effectParams = {
actions: anewStore.actions,
batch: anewStore.batch,
dispatch: anewStore.dispatch,
effects: anewStore.effects,
select: anewStore.select
};
var _loop3 = function _loop3(i, effectsLen) {
var effectName = effectKeys[i];
var effect = effects[effectName];
var effectType = typeof effect === 'undefined' ? 'undefined' : _typeof(effect);
(0, _invariant2.default)(effectType === 'function', 'Store effects can only be functions ' + ('Recieved "' + effectType + '" ') + ('for "' + effectName + '" in "' + anewStore.name + '"'));
function effectWithParams() {
if (!effectParams.persistor && reduxStore.dispatch.persistor) {
effectParams.persistor = reduxStore.dispatch.persistor;
}
if (!effectParams.core && reduxStore.anew.core) {
var _reduxStore$anew$core = reduxStore.anew.core,
getState = _reduxStore$anew$core.getState,
_reduxStore$anew$core2 = _reduxStore$anew$core.dispatch,
_reducers = _reduxStore$anew$core2.reducers,
_effects = _reduxStore$anew$core2.effects,
_actions = _reduxStore$anew$core2.actions,
batch = _reduxStore$anew$core2.batch;
effectParams.core = {
select: getState,
dispatch: _reducers,
batch: batch,
effects: _effects,
actions: _actions
};
}
function effectsBinded() {
for (var _len3 = arguments.length, payload = Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
payload[_key3] = arguments[_key3];
}
return effect.apply(undefined, [effectParams].concat(payload));
}
reduxStore.dispatch.effects[effectName] = effectsBinded;
anewStore.effects[effectName] = effectsBinded;
return effectsBinded.apply(undefined, arguments);
}
reduxStore.dispatch.effects[effectName] = effectWithParams;
anewStore.effects[effectName] = effectWithParams;
};
for (var i = 0, effectsLen = effectKeys.length; i < effectsLen; i++) {
_loop3(i, effectsLen);
}
return reduxStore;
}