import { IReduxed, TAsyncified, TReduxed, TResolvedActions, TAllActions, TReduxHandlers, } from './types' import {createRemoteClient} from './remote' export function createActions( client: TAsyncified, type: ActionType, ) { const service = Object.keys(client).reduce((obj, method: any) => { obj[method] = function makeAction(...args: any[]) { const payload = ((client as any)[method])(...args) return { payload, type, method, status: 'pending', } } return obj }, {} as any) return service as TReduxed } export interface IState { loading: number error: string } export function createReducer( actionType: ActionType, defaultState: State, ) { const self = { withHandler>( handleAction: (state: State, action: TResolvedActions) => State, ): (state: State | undefined, action: TAllActions) => State { return (state: State = defaultState, action: TAllActions): State => { if (action.type !== actionType) { return state } if (action.status === 'pending') { return { ...state, loading: state.loading + 1, error: '', } } if (action.status === 'rejected') { return { ...state, loading: state.loading - 1, error: action.payload.message, } } return handleAction({ ...state, loading: state.loading - 1, error: '', }, action) } }, withMapping>( handlers: TReduxHandlers, ) { return self.withHandler((state, action) => { if (action.method in handlers) { const newState = handlers[action.method](state, action) return { ...state, ...newState, } } return state }) }, } return self }