skolplattformen-backup/libs/hooks/src/middleware.ts

114 lines
3.4 KiB
TypeScript

/* eslint-disable default-case */
import { Middleware } from 'redux'
import { EntityAction, EntityStoreRootState, ExtraActionProps } from './types'
type IMiddleware = Middleware<Record<string, unknown>, EntityStoreRootState>
export const apiMiddleware: IMiddleware =
(storeApi) => (next) => (action: EntityAction<any>) => {
try {
switch (action.type) {
case 'GET_FROM_API': {
// Retrieve from cache
if (action.extra?.getFromCache) {
const cacheAction: EntityAction<any> = {
...action,
type: 'GET_FROM_CACHE',
}
storeApi.dispatch(cacheAction)
}
// Call api
const apiCall = action.extra?.apiCall
if (apiCall) {
const extra = action.extra as ExtraActionProps<any>
apiCall()
.then((res: any) => {
const resultAction: EntityAction<any> = {
...action,
type: 'RESULT_FROM_API',
data: res,
}
storeApi.dispatch(resultAction)
if (extra.saveToCache && res) {
const cacheAction: EntityAction<any> = {
...resultAction,
type: 'STORE_IN_CACHE',
}
storeApi.dispatch(cacheAction)
}
})
.catch((error) => {
const retries = extra.retries + 1
const errorAction: EntityAction<any> = {
...action,
extra: {
...extra,
retries,
},
type: 'API_ERROR',
error,
}
storeApi.dispatch(errorAction)
// Retry 3 times
if (retries < 3) {
const retryAction: EntityAction<any> = {
...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<any>) => {
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<any> = {
...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)
}