All files / src/domain/createApiActionCreator index.js

68.97% Statements 20/29
76.47% Branches 13/17
50% Functions 5/10
68.97% Lines 20/29
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82                            1x   1x       5x 3x 3x     3x       3x   3x         3x 3x       3x 2x   3x                                   1x 6x 4x   2x 1x 1x               1x          
import is from 'is_js';
import { fetch } from 'domain/Api';
import ApiCall from 'containers/ApiCalls';
 
/*
 * Supports currying so that args can be recycled more conveniently.
 * A contrived example:
 * ```
 * const createCreatorForX = createApiActionCreator('NOTIFICATION', 'http://...');
 * const getXActionCreator = createCreatorForX('GET');
 * const postXActionCreator = createCreatorForX('POST');
 * ```
 */
 
const REQUIRED_ARGS_COUNT = 3;
 
const createApiActionCreator = (actionObjectName,
    url, method = 'GET',
    requestExtras = {}, successExtras = {}, failureExtras = {}) =>  // these are optional!
 
  (dispatch) => {
    const prefix = (() => {
      switch (method.toUpperCase()) {
        case 'DELETE': return 'DELETE_';
        case 'POST': case 'PUT': return 'SUBMIT_';
        case 'GET': default: return 'FETCH_';
      }
    })();
 
    const upperActionObjectName = actionObjectName.toUpperCase();
 
    return dispatch(createFetchRequestAction()).payload
      .then((response) => dispatch(createFetchSuccessAction(response)))
      .catch((error) => dispatch(createFetchFailureAction(error)));
 
    function createFetchRequestAction() {
      const type = `${prefix}${upperActionObjectName}_REQUEST`;
      const action = {
        type, url, method, ...requestExtras,
      };
      // do a bog standard GET if `payload` was not supplied in the extras
      if (! requestExtras.payload) {
        action.payload = fetch(url);
      }
      return ApiCall.createAction(action);
    }
 
    function createFetchSuccessAction(response) {
      const type = `${prefix}${upperActionObjectName}_SUCCESS`;
      return ApiCall.createAction({
        type, url, method, payload: response, ...successExtras,
      });
    }
 
    function createFetchFailureAction(error) {
      const type = `${prefix}${upperActionObjectName}_FAILURE`;
      return ApiCall.createAction({
        type, url, method, error, ...failureExtras,
      });
    }
  };
 
const curried = (...args) => {
  if (args.length >= REQUIRED_ARGS_COUNT) {
    return createApiActionCreator.apply(this, args);
  }
  if (args.length === 1 && is.object(args[0])) {  // allow first arg to be an options hash
    const options = args[0];
    return createApiActionCreator.call(this,
        options.actionObjectName,
        options.url,
        options.method,
        options.requestExtras,
        options.successExtras,
        options.failureExtras);
  }
  return (...rest) =>
    curried.apply(this, args.concat(rest));
};
 
export default curried;