gnar-edge
Version:
A sharp set of utilities: base64, drain, handleChange, jwt, notifications
65 lines (59 loc) • 3.06 kB
JavaScript
import { combineReducers } from 'redux';
import { handleActions } from 'redux-actions';
const isObject = obj => obj && typeof obj === 'object' && obj.constructor === Object;
const defaultMapReducer = (state, { payload }) => state.merge(payload);
const defaultObjectReducer = (state, { payload }) => ({ ...state, ...payload });
const simpleReducers = (obj, storeBranchName, defaultInitialState, defaultReducer) => {
const { initialState, basicReducers, customReducers } = obj;
const basicReducersBranch = `${storeBranchName}.basicReducers`;
const customReducersBranch = `${storeBranchName}.customReducers`;
const testDefaultInitialState = (defaultInitialState || (() => ({})))();
if ('basicReducers' in obj && typeof basicReducers !== 'string' && !Array.isArray(basicReducers)) {
const msg = `Expected array or string at ${basicReducersBranch}, received ${JSON.stringify(basicReducers)}`;
throw new TypeError(msg);
}
if ('customReducers' in obj && !isObject(customReducers)) {
throw new TypeError(`Expected object at ${customReducersBranch}, received ${JSON.stringify(customReducers)}`);
}
const effectiveBasicReducers =
basicReducers && typeof basicReducers === 'string' ? [ basicReducers ] : basicReducers || [];
const parsedReducers = {
...effectiveBasicReducers.reduce((memo, key, idx) => {
if (typeof key !== 'string') {
throw new TypeError(`Expected string at ${basicReducersBranch}.${idx}, received ${JSON.stringify(key)}`);
}
memo[key] = defaultReducer || (
'asMutable' in testDefaultInitialState && 'merge' in testDefaultInitialState
? defaultMapReducer
: defaultObjectReducer
);
return memo;
}, {}),
...Object.keys(customReducers || {}).reduce((memo, key) => {
const reducer = customReducers[key];
if (typeof reducer !== 'function') {
const fullBranch = `${customReducersBranch}.${key}`;
throw new TypeError(`Expected function at ${fullBranch}, received ${JSON.stringify(reducer)}`);
}
memo[key] = reducer;
return memo;
}, {})
};
return handleActions(parsedReducers, initialState || (defaultInitialState || (() => ({})))());
};
const parseReducers = (obj, parentStoreBranchName, defaultInitialState, defaultReducer) => combineReducers(
Object.keys(obj).reduce((memo, key) => {
const storeBranchName = `${parentStoreBranchName}${parentStoreBranchName ? '.' : ''}${key}`;
const val = obj[key];
memo[key] = isObject(val)
? 'basicReducers' in val || 'customReducers' in val
? simpleReducers(val, storeBranchName, defaultInitialState, defaultReducer)
: parseReducers(val, storeBranchName, defaultInitialState, defaultReducer)
: typeof val === 'string' || Array.isArray(val)
? simpleReducers({ basicReducers: val }, storeBranchName, defaultInitialState, defaultReducer)
: val;
return memo;
}, {})
);
export default (obj, defaultInitialState, defaultReducer) =>
parseReducers(obj, '', defaultInitialState, defaultReducer);