UNPKG

redext

Version:

A simple global store based on React Context and Hooks

96 lines (95 loc) 3.22 kB
// src/createStore.ts var merge = (original, extra) => { return extra ? { ...extra, ...original } : original; }; function createStore(config) { const { plugins = [] } = config; let models = config.models; plugins.forEach((plugin) => { if (plugin.config) { models = merge(models, plugin.config.models); } }); const on = (eventName, callback) => { plugins.forEach((plugin) => { if (plugin[eventName]) { callback(plugin[eventName]); } }); }; const getState = (initialState = {}) => { const newInitialState = {}; Object.keys(models).forEach((modelFilename) => { const model = models[modelFilename] || {}; const modelName = model.name || modelFilename; newInitialState[modelName] = Object.assign({}, model.state, initialState[modelName]); }); return newInitialState; }; const getReducer = (state = {}, action = {}) => { const newState = {}; Object.keys(models).forEach((modelFilename) => { var _a, _b; const model = models[modelFilename] || {}; const { reducers = {}, name: modelName = modelFilename } = model; let reducerState = state[modelName]; const actionType = (_b = (_a = action.type) == null ? void 0 : _a.replace) == null ? void 0 : _b.call(_a, `${modelName}/`, ""); if (actionType && actionType in reducers) { reducerState = reducers[actionType](reducerState, action.payload, action.params); } newState[modelName] = reducerState; }); return newState; }; const getEffect = (dispatch, state = {}) => { const newEffects = {}; Object.keys(models).forEach((modelFilename) => { const modelDispatcher = {}; const model = models[modelFilename] || {}; const { reducers = {}, effects: effectsFromConfig, name: modelName = modelFilename } = model; modelDispatcher.state = state[modelName]; const onModelListener = ({ actionName }) => { on("onModel", (onModel) => { onModel({ model: { ...model, name: modelName }, modelName, actionName, dispatch }); }); }; Object.keys(reducers).forEach((actionName) => { const type = `${modelName}/${actionName}`; modelDispatcher[actionName] = (payload, params) => { dispatch({ type, payload, params }); }; }); let effects; dispatch[modelName] = modelDispatcher; if (typeof effectsFromConfig === "function") { effects = effectsFromConfig(dispatch); } else { effects = effectsFromConfig || {}; } const effectObj = {}; Object.keys(effects).forEach((effectName) => { const effectFunc = (...args) => { onModelListener({ actionName: effectName }); return effects[effectName].apply(modelDispatcher, args); }; modelDispatcher[effectName] = effectFunc; effectObj[effectName] = effectFunc; }); newEffects[modelName] = effectObj; }); return { effects: newEffects, models, dispatch, on }; }; return { getState, getReducer, getEffect }; } export { createStore as default };