diff --git a/src/buildMiddleware/index.js b/src/buildMiddleware/index.js new file mode 100644 index 0000000..2085412 --- /dev/null +++ b/src/buildMiddleware/index.js @@ -0,0 +1,48 @@ +import { mapValues, map, get } from 'lodash-es'; +const middlewareFor = (type, middleware) => (api) => (next) => (action) => { + if (type !== '*' && action.type !== type) + return next(action); + return middleware(api)(next)(action); +}; +const sliceMw = (slice, mw) => (api) => { + const getSliceState = () => get(api.getState(), slice); + return mw(Object.assign(Object.assign({}, api), { getState: getSliceState })); +}; +export function augmentMiddlewareApi(api, actions, selectors) { + const getState = () => api.getState(); + const dispatch = (action) => api.dispatch(action); + Object.assign(getState, mapValues(selectors, (selector) => { + return (...args) => { + let result = selector(api.getState()); + if (typeof result === 'function') + return result(...args); + return result; + }; + })); + Object.assign(dispatch, mapValues(actions, (action) => { + return (...args) => api.dispatch(action(...args)); + })); + return Object.assign(Object.assign({}, api), { getState, + dispatch, + actions, + selectors }); +} +export const effectToMiddleware = (effect, actions, selectors) => { + let mw = effect; + let action = '*'; + if (Array.isArray(effect)) { + action = effect[0]; + mw = effect[1]; + mw = middlewareFor(action, mw); + } + return (api) => mw(augmentMiddlewareApi(api, actions, selectors)); +}; +const composeMw = (mws) => (api) => (original_next) => mws.reduceRight((next, mw) => mw(api)(next), original_next); +export function buildMiddleware(effects = [], actions = {}, selectors = {}, sub = {}, wrapper = undefined, dux = undefined) { + let inner = map(sub, ({ middleware }, slice) => slice !== '*' && middleware ? sliceMw(slice, middleware) : undefined).filter((x) => x); + const local = effects.map((effect) => effectToMiddleware(effect, actions, selectors)); + let mws = [...local, ...inner]; + if (wrapper) + mws = wrapper(mws, dux); + return composeMw(mws); +} diff --git a/src/buildMiddleware/index.ts b/src/buildMiddleware/index.ts.todo similarity index 100% rename from src/buildMiddleware/index.ts rename to src/buildMiddleware/index.ts.todo diff --git a/src/buildSelectors/index.js b/src/buildSelectors/index.js new file mode 100644 index 0000000..dfd7550 --- /dev/null +++ b/src/buildSelectors/index.js @@ -0,0 +1,20 @@ +import { map, mapValues, merge } from 'lodash-es'; +export function buildSelectors(localSelectors, splatSelector = {}, subduxes = {}) { + const subSelectors = map(subduxes, ({ selectors }, slice) => { + if (!selectors) + return {}; + if (slice === '*') + return {}; + return mapValues(selectors, (func) => (state) => func(state[slice])); + }); + let splat = {}; + for (const name in splatSelector) { + splat[name] = + (state) => (...args) => { + const value = splatSelector[name](state)(...args); + const res = () => value; + return merge(res, mapValues(subduxes['*'].selectors, (selector) => () => selector(value))); + }; + } + return merge({}, ...subSelectors, localSelectors, splat); +} diff --git a/src/buildSelectors/index.ts b/src/buildSelectors/index.ts.todo similarity index 100% rename from src/buildSelectors/index.ts rename to src/buildSelectors/index.ts.todo