/* eslint-disable default-case */ import { Middleware } from 'redux' import { EntityAction, EntityStoreRootState, ExtraActionProps } from './types' type IMiddleware = Middleware, EntityStoreRootState> export const apiMiddleware: IMiddleware = (storeApi) => (next) => (action: EntityAction) => { try { switch (action.type) { case 'GET_FROM_API': { // Retrieve from cache if (action.extra?.getFromCache) { const cacheAction: EntityAction = { ...action, type: 'GET_FROM_CACHE', } storeApi.dispatch(cacheAction) } // Call api const apiCall = action.extra?.apiCall if (apiCall) { const extra = action.extra as ExtraActionProps apiCall() .then((res: any) => { const resultAction: EntityAction = { ...action, type: 'RESULT_FROM_API', data: res, } storeApi.dispatch(resultAction) if (extra.saveToCache && res) { const cacheAction: EntityAction = { ...resultAction, type: 'STORE_IN_CACHE', } storeApi.dispatch(cacheAction) } }) .catch((error) => { const retries = extra.retries + 1 const errorAction: EntityAction = { ...action, extra: { ...extra, retries, }, type: 'API_ERROR', error, } storeApi.dispatch(errorAction) // Retry 3 times if (retries < 3) { const retryAction: EntityAction = { ...action, type: 'GET_FROM_API', extra: { ...extra, retries, }, } setTimeout(() => { storeApi.dispatch(retryAction) }, retries * 500) } }) } } } } catch (err) { // eslint-disable-next-line no-console console.error(err) } return next(action) } export const cacheMiddleware: IMiddleware = (storeApi) => (next) => (action: EntityAction) => { try { switch (action.type) { case 'GET_FROM_CACHE': { const getFromCache = action.extra?.getFromCache if (getFromCache) { getFromCache().then((res: string | null) => { if (res) { const cacheResultAction: EntityAction = { ...action, type: 'RESULT_FROM_CACHE', data: JSON.parse(res), } storeApi.dispatch(cacheResultAction) } }) } break } case 'STORE_IN_CACHE': { const saveToCache = action.extra?.saveToCache if (saveToCache && action.data) { saveToCache(JSON.stringify(action.data)) } break } } } catch (err) { // eslint-disable-next-line no-console console.error(err) } return next(action) }