updux/src/effects.ts

60 lines
1.7 KiB
TypeScript

import { AnyAction } from '@reduxjs/toolkit';
import { MiddlewareAPI } from '@reduxjs/toolkit';
import { Dispatch } from '@reduxjs/toolkit';
export interface EffectMiddleware<S = any, D extends Dispatch = Dispatch> {
(api: MiddlewareAPI<D, S>): (
next: Dispatch<AnyAction>,
) => (action: AnyAction) => any;
}
const composeMw = (mws) => (api) => (originalNext) =>
mws.reduceRight((next, mw) => mw(api)(next), originalNext);
export const augmentGetState = (originalGetState, selectors) => {
const getState = () => originalGetState();
for (const s in selectors) {
getState[s] = (...args) => {
let result = selectors[s](originalGetState());
if (typeof result === 'function') return result(...args);
return result;
};
}
return getState;
};
const augmentDispatch = (originalDispatch, actions) => {
const dispatch = (action) => originalDispatch(action);
for (const a in actions) {
dispatch[a] = (...args) => dispatch(actions[a](...args));
}
return dispatch;
};
export const augmentMiddlewareApi = (api, actions, selectors) => {
return {
...api,
getState: augmentGetState(api.getState, selectors),
dispatch: augmentDispatch(api.dispatch, actions),
actions,
selectors,
};
};
export function buildEffectsMiddleware(
effects = [],
actions = {},
selectors = {},
) {
return (api) => {
const newApi = augmentMiddlewareApi(api, actions, selectors);
let mws = effects.map((e) => e(newApi));
return (originalNext) => {
return mws.reduceRight((next, mw) => mw(next), originalNext);
};
};
}