import axios from 'axios' ; export const CALL_API = Symbol ( 'Call API' ) ; const callApi = ( method , url , data ) => axios ( { method , url , data } ) . then ( ( response ) => { if ( response . status === 204 ) { return { request : { } , response } ; } return { request : data , response , } ; } ) . then ( ( response ) => { if ( ! response . statusText === 'OK' ) { const error = new Error ( 'API middleware: response is not OK' ) ; error . json = response . data ; error . response = response ; return Promise . reject ( error ) ; } return response . response . data ; } ) ; export default ( store ) => ( next ) => ( action ) => { const callAPI = action [ CALL_API ] ; if ( typeof callAPI === 'undefined' ) { return next ( action ) ; } let { endpoint } = callAPI ; const { types , method , data , extras } = callAPI ; if ( ! Array . isArray ( types ) || types . length !== 3 ) { throw new Error ( 'Expected an array of three action types.' ) ; } if ( ! types . every ( ( type ) => typeof type === 'string' ) ) { throw new Error ( 'Expected action types to be strings.' ) ; } if ( typeof method !== 'string' ) { throw new Error ( 'Expected method to be a string.' ) ; } if ( typeof endpoint === 'function' ) { endpoint = endpoint ( store . getState ( ) ) ; } if ( typeof endpoint !== 'string' ) { throw new Error ( 'Specify a string endpoint URL.' ) ; } function actionWith ( body ) { const finalAction = { ... action , ... body } ; delete finalAction [ CALL_API ] ; return finalAction ; } const [ requestType , successType , failureType ] = types ; next ( actionWith ( { type : requestType , endpoint , extras } ) ) ; return callApi ( method , endpoint , data ) . then ( ( response ) => next ( actionWith ( { response , endpoint , type : successType , extras , } ) ) ) . catch ( ( err ) => { const { message , status } = err ; let error = null ; if ( message instanceof Error ) { error = message ; } else { error = new Error ( 'Something bad happened' ) ; } error . status = status || 500 ; if ( status === 500 ) { return next ( ) ; } next ( actionWith ( { endpoint , type : failureType , error , extras , } ) ) ; throw err ; } ) ; } ;