{"size": 3536, "ext": "js", "max_stars_repo_path": "client/middleware/api-middleware.js", "max_stars_repo_name": "avehlies/keyteki", "max_stars_repo_stars_event_min_datetime": null, "max_stars_repo_stars_event_max_datetime": null, "max_issues_repo_path": "client/middleware/api-middleware.js", "max_issues_repo_name": "avehlies/keyteki", "max_issues_repo_issues_event_min_datetime": null, "max_issues_repo_issues_event_max_datetime": null, "max_forks_repo_path": "client/middleware/api-middleware.js", "max_forks_repo_name": "avehlies/keyteki", "max_forks_repo_forks_event_min_datetime": null, "max_forks_repo_forks_event_max_datetime": null}
{"max_stars_count": null, "max_issues_count": null, "max_forks_count": null, "avg_line_length": 28.7479674797, "max_line_length": 107, "alphanum_fraction": 0.4703054299}
import $ from 'jquery';
import { navigate, setAuthTokens, authenticateSocket } from '../actions';

export default function callAPIMiddleware({ dispatch, getState }) {
    return next => async action => {
        const {
            types,
            APIParams,
            shouldCallAPI = () => true,
            payload = {},
            skipAuth = false
        } = action;

        if(!types) {
            return next(action);
        }

        if(!Array.isArray(types) || types.length !== 2 || !types.every(type => typeof type === 'string')) {
            throw new Error('Expected an array of two string types.');
        }

        const [requestType, successType] = types;

        dispatch(Object.assign({}, payload, {
            type: requestType
        }));

        if(!shouldCallAPI(getState())) {
            return;
        }

        dispatch(Object.assign({}, payload, {
            type: 'API_LOADING',
            request: requestType
        }));

        let apiParams = APIParams || {};
        apiParams.contentType = 'application/json';
        if(!skipAuth) {
            apiParams.headers = {
                Authorization: `Bearer ${getState().auth.token}`
            };
        }

        let response;
        let errorStatus = 200;

        try {
            response = await $.ajax(apiParams.url, apiParams);
        } catch(error) {
            if(error.status === 401) {
                let state = getState();
                let authResponse = await $.ajax('/api/account/token', {
                    contentType: 'application/json',
                    type: 'POST',
                    data: JSON.stringify({ token: state.auth.refreshToken })
                });

                if(!authResponse.success) {
                    dispatch(navigate('/login'));

                    return;
                }

                dispatch(setAuthTokens(authResponse.token, state.auth.refreshToken));
                dispatch(authenticateSocket());

                apiParams.headers = {
                    Authorization: `Bearer ${authResponse.token}`
                };

                try {
                    response = await $.ajax(apiParams.url, apiParams);
                } catch(innerError) {
                    errorStatus = innerError.status;
                }
            } else {
                errorStatus = error.status;
            }
        }

        if(!response) {
            dispatch(Object.assign({}, payload, {
                status: errorStatus,
                message: 'An error occured communicating with the server.  Please try again later.',
                type: 'API_LOADED',
                request: requestType
            }));

            dispatch(Object.assign({}, payload, {
                status: errorStatus,
                message: 'An error occured communicating with the server.  Please try again later.',
                type: 'API_FAILURE',
                request: requestType
            }));

            return;
        }

        if(!response.success) {
            dispatch(Object.assign({}, payload, {
                status: 200,
                message: response.message,
                type: 'API_FAILURE',
                request: requestType
            }));

            return;
        }

        dispatch(Object.assign({}, payload, {
            response,
            type: successType
        }));

        dispatch(Object.assign({}, payload, {
            type: 'API_LOADED',
            request: requestType
        }));
    };
}

