import * as ActionTypes from './constants';
import { createAction, apiClient } from './utils';
/**
* @module active-redux/api
*/
const wrappedApiRequest = ({
resource,
options,
endpoint,
dispatch,
success,
failure,
}) => apiClient(endpoint, options).then((json) => {
dispatch(success(json));
return Promise.resolve(json);
}).catch((error) => {
const err = error;
err.resource = resource;
dispatch(failure(err));
return Promise.reject(err);
});
/**
* Configure the API -
* see https://github.com/mzabriskie/axios#request-config
* @function
* @param {Object} config - Axios configuration
*/
export const apiConfigure = createAction(ActionTypes.API_CONFIGURE);
/**
* Clear an entity from the store
* @function
* @private
* @example
* import { apiClear } from 'active-redux';
*
* state.api.people
* // => Object<String: Person>
*
* dispatch(apiClear('people'))
*
* state.api.people
* // => {}
* @param {Object} data - JSON-API data
*/
export const apiClear = createAction(ActionTypes.API_CLEAR);
/**
* Hydrate the store from JSON-API
* @function
* @example
* import { apiHydrate } from 'active-redux';
*
* state.api.people
* // => {}
*
* const data = [{
* type: 'people',
* id: '5',
* attributes: {
* name: 'Joe',
* age: 35,
* }
* }];
*
* dispatch(apiHydrate(data))
*
* state.api.people
* // => Object<String: Person>
* @param {Object} data - JSON-API data
*/
export const apiHydrate = createAction(ActionTypes.API_HYDRATE);
const apiWillCreate = createAction(ActionTypes.API_WILL_CREATE);
const apiCreateDone = createAction(ActionTypes.API_CREATE_DONE);
const apiCreateFailed = createAction(ActionTypes.API_CREATE_FAILED);
/**
* Create a resource via API
* @function
* @example
* import { apiCreate } from 'active-redux';
* import Person from '../models/person';
*
* Person.find({ id: '5' });
* // => Promise<null>
*
* const person = new Person({ attributes: { name: 'Joe' } });
*
* dispatch(apiCreate({ resource: person })).then((json) => {
* // do something with the response json
* }).catch((error) => {
* // handle error
* });
*
* Person.find({ id: '5' });
* // => Promise<Person>
* @param {Object} args
* @param {define~Model} args.resource
* @param {string} [args.endpoint]
*/
export const apiCreate = ({ resource, endpoint = resource.endpoint('create') }) => (dispatch, getState) => {
dispatch(apiWillCreate(resource));
return wrappedApiRequest({
resource,
options: {
...getState().api.apiConfig,
method: 'POST',
data: { data: resource }
},
endpoint,
dispatch,
success: apiCreateDone,
failure: apiCreateFailed,
});
};
const apiWillRead = createAction(ActionTypes.API_WILL_READ);
const apiReadDone = createAction(ActionTypes.API_READ_DONE);
const apiReadFailed = createAction(ActionTypes.API_READ_FAILED);
/**
* Read a resource via API
* @function
* @example
* import { apiRead } from 'active-redux';
* import Person from '../models/person';
*
* Person.all();
* // => Promise<[]>
*
* dispatch(apiRead({ resource: Person })).then((json) => {
* // do something with the response json
* }).catch((error) => {
* // handle error
* });
*
* Person.all();
* // => Promise<Array<Person>>
* @param {Object} args
* @param {Model} args.resource
* @param {string} [args.endpoint]
*/
export const apiRead = ({ resource, endpoint = resource.endpoint('read') }) => (dispatch, getState) => {
dispatch(apiWillRead(resource));
return wrappedApiRequest({
resource,
options: {
...getState().api.apiConfig,
method: 'GET',
data: { data: resource }
},
endpoint,
dispatch,
success: apiReadDone,
failure: apiReadFailed,
});
};
const apiWillUpdate = createAction(ActionTypes.API_WILL_UPDATE);
const apiUpdateDone = createAction(ActionTypes.API_UPDATE_DONE);
const apiUpdateFailed = createAction(ActionTypes.API_UPDATE_FAILED);
/**
* Update a resource via API
* @function
* @example
* import { apiUpdate } from 'active-redux';
* import Person from '../models/person';
*
* Person.find({ id: '5' });
* // => Promise<Person(id='5' name='Joe')>
*
* const person = new Person({ id: '5', attributes: { name: 'Jimmy' } });
*
* dispatch(apiUpdate({ resource: person })).then((json) => {
* // do something with the response json
* }).catch((error) => {
* // handle error
* });
*
* Person.find({ id: '5' });
* // => Promise<Person(id='5' name='Jimmy')>
* @param {Object} args
* @param {Model} args.resource
* @param {string} [args.endpoint]
*/
export const apiUpdate = ({ resource, endpoint = resource.endpoint('update') }) => (
(dispatch, getState) => {
dispatch(apiWillUpdate(resource));
return wrappedApiRequest({
resource,
options: {
...getState().api.apiConfig,
method: 'PATCH',
data: { data: resource }
},
endpoint,
dispatch,
success: apiUpdateDone,
failure: apiUpdateFailed,
});
}
);
const apiWillDelete = createAction(ActionTypes.API_WILL_DELETE);
const apiDeleteDone = createAction(ActionTypes.API_DELETE_DONE);
const apiDeleteFailed = createAction(ActionTypes.API_DELETE_FAILED);
/**
* Delete a resource via API
* @function
* @example
* import { apiDelete } from 'active-redux';
* import Person from '../models/person';
*
* Person.find({ id: '5' });
* // => Promise<Person(id='5')>
*
* const person = new Person({ id: '5' });
*
* dispatch(apiDelete({ resource: person })).then((json) => {
* // do something with the response json
* }).catch((error) => {
* // handle error
* });
*
* Person.find({ id: '5' });
* // => Promise<null>
* @param {Object} args
* @param {Model} args.resource
* @param {string} [args.endpoint]
*/
export const apiDelete = ({ resource, endpoint = resource.endpoint('delete') }) => (
(dispatch, getState) => {
const options = {
...getState().api.apiConfig,
method: 'DELETE',
};
dispatch(apiWillDelete(resource));
return apiClient(endpoint, options).then((json) => {
dispatch(apiDeleteDone(resource));
return Promise.resolve(json);
}).catch((error) => {
const err = error;
err.resource = resource;
dispatch(apiDeleteFailed(err));
return Promise.reject(err);
});
}
);