reducerFactory.ts 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
  1. import { GrafanaAction, GrafanaActionCreator } from './actionCreatorFactory';
  2. import { Reducer } from 'redux';
  3. export interface ActionHandler<State, Payload> {
  4. state: State;
  5. action: GrafanaAction<Payload>;
  6. }
  7. export interface ActionHandlerConfig<State, Payload> {
  8. creator: GrafanaActionCreator<Payload>;
  9. handler: (handler: ActionHandler<State, Payload>) => State;
  10. }
  11. export interface AddActionHandler<State> {
  12. addHandler: <Payload>(config: ActionHandlerConfig<State, Payload>) => CreateReducer<State>;
  13. }
  14. export interface CreateReducer<State> extends AddActionHandler<State> {
  15. create: () => Reducer<State, GrafanaAction<any>>;
  16. }
  17. export const reducerFactory = <State>(initialState: State): AddActionHandler<State> => {
  18. const allHandlerConfigs: Array<ActionHandlerConfig<State, any>> = [];
  19. const addHandler = <Payload>(config: ActionHandlerConfig<State, Payload>): CreateReducer<State> => {
  20. if (allHandlerConfigs.some(c => c.creator.type === config.creator.type)) {
  21. throw new Error(`There is already a handlers defined with the type ${config.creator.type}`);
  22. }
  23. allHandlerConfigs.push(config);
  24. return instance;
  25. };
  26. const create = (): Reducer<State, GrafanaAction<any>> => {
  27. const reducer: Reducer<State, GrafanaAction<any>> = (state: State = initialState, action: GrafanaAction<any>) => {
  28. const validHandlers = allHandlerConfigs
  29. .filter(config => config.creator.type === action.type)
  30. .map(config => config.handler);
  31. return validHandlers.reduce((currentState, handler) => {
  32. return handler({ state: currentState, action });
  33. }, state || initialState);
  34. };
  35. return reducer;
  36. };
  37. const instance: CreateReducer<State> = {
  38. addHandler,
  39. create,
  40. };
  41. return instance;
  42. };