Created
December 14, 2015 21:06
-
-
Save mnazim/33c7739c62a5877f0aa7 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Schema, arrayOf, normalize } from 'normalizr'; | |
import { camelizeKeys } from 'humps'; | |
import axios from 'axios'; | |
const API_ROOT = 'http://localhost:5555/api/v1/'; | |
// Fetches an API response. | |
// This makes every API response have the same shape, regardless of how nested it was. | |
function callApi(endpoint, method = 'get', data = {}, schema = null) { | |
const fullUrl = (endpoint.indexOf(API_ROOT) === -1) ? API_ROOT + endpoint : endpoint; | |
if (method.toLowerCase() == 'get') { | |
return axios.get( | |
fullUrl, | |
{ params: data } | |
); | |
} | |
else { | |
return axios.post( | |
fullUrl, | |
data | |
); | |
} | |
} | |
// Action key that carries API call info interpreted by this Redux middleware. | |
export const CALL_API = Symbol('Call API'); | |
// A Redux middleware that interprets actions with CALL_API info specified. | |
// Performs the call and promises when such actions are dispatched. | |
export default store => next => action => { | |
const callAPI = action[CALL_API]; | |
if (typeof callAPI === 'undefined') { | |
return next(action); | |
} | |
let { endpoint } = callAPI; | |
const { schema, types, method, data } = callAPI; | |
if (typeof endpoint === 'function') { | |
endpoint = endpoint(store.getState()); | |
} | |
if (typeof endpoint !== 'string') { | |
throw new Error('Specify a string endpoint URL.'); | |
} | |
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.'); | |
} | |
function actionWith(data) { | |
const finalAction = Object.assign({}, action, data); | |
delete finalAction[CALL_API]; | |
return finalAction; | |
} | |
const [requestType, successType, failureType] = types; | |
next(actionWith({ type: requestType })); | |
return callApi(endpoint, method, data, schema).then( | |
response => next(actionWith({ | |
response, | |
type: successType | |
})), | |
error => next(actionWith({ | |
type: failureType, | |
error: error.message || 'Something went wrong!' | |
})) | |
); | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment