redux-api-middleware
Advanced tools
Comparing version 1.0.2 to 2.0.0-beta.1
@@ -0,1 +1,26 @@ | ||
'use strict'; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
exports.ApiError = exports.RequestError = exports.InternalError = exports.InvalidRSAA = undefined; | ||
var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of'); | ||
var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); | ||
var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); | ||
var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); | ||
var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn'); | ||
var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); | ||
var _inherits2 = require('babel-runtime/helpers/inherits'); | ||
var _inherits3 = _interopRequireDefault(_inherits2); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
/** | ||
@@ -8,93 +33,100 @@ * Error class for an RSAA that does not conform to the RSAA definition | ||
*/ | ||
'use strict'; | ||
var _inherits = require('babel-runtime/helpers/inherits')['default']; | ||
var InvalidRSAA = function (_Error) { | ||
(0, _inherits3.default)(InvalidRSAA, _Error); | ||
var _classCallCheck = require('babel-runtime/helpers/class-call-check')['default']; | ||
function InvalidRSAA(validationErrors) { | ||
(0, _classCallCheck3.default)(this, InvalidRSAA); | ||
exports.__esModule = true; | ||
var _this = (0, _possibleConstructorReturn3.default)(this, (0, _getPrototypeOf2.default)(InvalidRSAA).call(this)); | ||
var InvalidRSAA = (function (_Error) { | ||
_inherits(InvalidRSAA, _Error); | ||
function InvalidRSAA(validationErrors) { | ||
_classCallCheck(this, InvalidRSAA); | ||
_Error.call(this); | ||
this.name = 'InvalidRSAA'; | ||
this.message = 'Invalid RSAA'; | ||
this.validationErrors = validationErrors; | ||
_this.name = 'InvalidRSAA'; | ||
_this.message = 'Invalid RSAA'; | ||
_this.validationErrors = validationErrors; | ||
return _this; | ||
} | ||
/** | ||
* Error class for a custom `payload` or `meta` function throwing | ||
* | ||
* @class InternalError | ||
* @access public | ||
* @param {string} message - the error message | ||
*/ | ||
return InvalidRSAA; | ||
})(Error); | ||
}(Error); | ||
var InternalError = (function (_Error2) { | ||
_inherits(InternalError, _Error2); | ||
/** | ||
* Error class for a custom `payload` or `meta` function throwing | ||
* | ||
* @class InternalError | ||
* @access public | ||
* @param {string} message - the error message | ||
*/ | ||
var InternalError = function (_Error2) { | ||
(0, _inherits3.default)(InternalError, _Error2); | ||
function InternalError(message) { | ||
_classCallCheck(this, InternalError); | ||
(0, _classCallCheck3.default)(this, InternalError); | ||
_Error2.call(this); | ||
this.name = 'InternalError'; | ||
this.message = message; | ||
var _this2 = (0, _possibleConstructorReturn3.default)(this, (0, _getPrototypeOf2.default)(InternalError).call(this)); | ||
_this2.name = 'InternalError'; | ||
_this2.message = message; | ||
return _this2; | ||
} | ||
/** | ||
* Error class for an error raised trying to make an API call | ||
* | ||
* @class RequestError | ||
* @access public | ||
* @param {string} message - the error message | ||
*/ | ||
return InternalError; | ||
})(Error); | ||
}(Error); | ||
var RequestError = (function (_Error3) { | ||
_inherits(RequestError, _Error3); | ||
/** | ||
* Error class for an error raised trying to make an API call | ||
* | ||
* @class RequestError | ||
* @access public | ||
* @param {string} message - the error message | ||
*/ | ||
var RequestError = function (_Error3) { | ||
(0, _inherits3.default)(RequestError, _Error3); | ||
function RequestError(message) { | ||
_classCallCheck(this, RequestError); | ||
(0, _classCallCheck3.default)(this, RequestError); | ||
_Error3.call(this); | ||
this.name = 'RequestError'; | ||
this.message = message; | ||
var _this3 = (0, _possibleConstructorReturn3.default)(this, (0, _getPrototypeOf2.default)(RequestError).call(this)); | ||
_this3.name = 'RequestError'; | ||
_this3.message = message; | ||
return _this3; | ||
} | ||
/** | ||
* Error class for an API response outside the 200 range | ||
* | ||
* @class ApiError | ||
* @access public | ||
* @param {number} status - the status code of the API response | ||
* @param {string} statusText - the status text of the API response | ||
* @param {object} response - the parsed JSON response of the API server if the | ||
* 'Content-Type' header signals a JSON response | ||
*/ | ||
return RequestError; | ||
})(Error); | ||
}(Error); | ||
var ApiError = (function (_Error4) { | ||
_inherits(ApiError, _Error4); | ||
/** | ||
* Error class for an API response outside the 200 range | ||
* | ||
* @class ApiError | ||
* @access public | ||
* @param {number} status - the status code of the API response | ||
* @param {string} statusText - the status text of the API response | ||
* @param {object} response - the parsed JSON response of the API server if the | ||
* 'Content-Type' header signals a JSON response | ||
*/ | ||
var ApiError = function (_Error4) { | ||
(0, _inherits3.default)(ApiError, _Error4); | ||
function ApiError(status, statusText, response) { | ||
_classCallCheck(this, ApiError); | ||
(0, _classCallCheck3.default)(this, ApiError); | ||
_Error4.call(this); | ||
this.name = 'ApiError'; | ||
this.status = status; | ||
this.statusText = statusText; | ||
this.response = response; | ||
this.message = status + ' - ' + statusText; | ||
var _this4 = (0, _possibleConstructorReturn3.default)(this, (0, _getPrototypeOf2.default)(ApiError).call(this)); | ||
_this4.name = 'ApiError'; | ||
_this4.status = status; | ||
_this4.statusText = statusText; | ||
_this4.response = response; | ||
_this4.message = status + ' - ' + statusText; | ||
return _this4; | ||
} | ||
return ApiError; | ||
})(Error); | ||
}(Error); | ||
@@ -101,0 +133,0 @@ exports.InvalidRSAA = InvalidRSAA; |
@@ -1,42 +0,12 @@ | ||
/** | ||
* Redux middleware for calling an API | ||
* @module redux-api-middleware | ||
* @requires isomorphic-fetch | ||
* @requires lodash.isplainobject | ||
* @exports {symbol} CALL_API | ||
* @exports {function} isRSAA | ||
* @exports {function} validateRSAA | ||
* @exports {function} isValidRSAA | ||
* @exports {error} InvalidRSAA | ||
* @exports {error} InternalError | ||
* @exports {error} RequestError | ||
* @exports {error} ApiError | ||
* @exports {function} getJSON | ||
* @exports {ReduxMiddleWare} apiMiddleware | ||
*/ | ||
/** | ||
* @typedef {function} ReduxMiddleware | ||
* @param {object} store | ||
* @returns {ReduxNextHandler} | ||
* | ||
* @typedef {function} ReduxNextHandler | ||
* @param {function} next | ||
* @returns {ReduxActionHandler} | ||
* | ||
* @typedef {function} ReduxActionHandler | ||
* @param {object} action | ||
* @returns undefined | ||
*/ | ||
'use strict'; | ||
var _interopRequireDefault = require('babel-runtime/helpers/interop-require-default')['default']; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
exports.apiMiddleware = exports.getJSON = exports.ApiError = exports.RequestError = exports.InternalError = exports.InvalidRSAA = exports.isValidRSAA = exports.validateRSAA = exports.isRSAA = exports.RSAA = undefined; | ||
exports.__esModule = true; | ||
var _RSAA = require('./RSAA'); | ||
var _CALL_API = require('./CALL_API'); | ||
var _RSAA2 = _interopRequireDefault(_RSAA); | ||
var _CALL_API2 = _interopRequireDefault(_CALL_API); | ||
var _validation = require('./validation'); | ||
@@ -50,3 +20,5 @@ | ||
exports.CALL_API = _CALL_API2['default']; | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
exports.RSAA = _RSAA2.default; | ||
exports.isRSAA = _validation.isRSAA; | ||
@@ -60,2 +32,31 @@ exports.validateRSAA = _validation.validateRSAA; | ||
exports.getJSON = _util.getJSON; | ||
exports.apiMiddleware = _middleware.apiMiddleware; | ||
exports.apiMiddleware = _middleware.apiMiddleware; /** | ||
* Redux middleware for calling an API | ||
* @module redux-api-middleware | ||
* @requires isomorphic-fetch | ||
* @requires lodash.isplainobject | ||
* @exports {string} RSAA | ||
* @exports {function} isRSAA | ||
* @exports {function} validateRSAA | ||
* @exports {function} isValidRSAA | ||
* @exports {error} InvalidRSAA | ||
* @exports {error} InternalError | ||
* @exports {error} RequestError | ||
* @exports {error} ApiError | ||
* @exports {function} getJSON | ||
* @exports {ReduxMiddleWare} apiMiddleware | ||
*/ | ||
/** | ||
* @typedef {function} ReduxMiddleware | ||
* @param {object} store | ||
* @returns {ReduxNextHandler} | ||
* | ||
* @typedef {function} ReduxNextHandler | ||
* @param {function} next | ||
* @returns {ReduxActionHandler} | ||
* | ||
* @typedef {function} ReduxActionHandler | ||
* @param {object} action | ||
* @returns undefined | ||
*/ |
'use strict'; | ||
var _extends = require('babel-runtime/helpers/extends')['default']; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
exports.apiMiddleware = undefined; | ||
var _regeneratorRuntime = require('babel-runtime/regenerator')['default']; | ||
var _regenerator = require('babel-runtime/regenerator'); | ||
var _interopRequireDefault = require('babel-runtime/helpers/interop-require-default')['default']; | ||
var _regenerator2 = _interopRequireDefault(_regenerator); | ||
exports.__esModule = true; | ||
var _extends2 = require('babel-runtime/helpers/extends'); | ||
var _extends3 = _interopRequireDefault(_extends2); | ||
var _slicedToArray2 = require('babel-runtime/helpers/slicedToArray'); | ||
var _slicedToArray3 = _interopRequireDefault(_slicedToArray2); | ||
var _asyncToGenerator2 = require('babel-runtime/helpers/asyncToGenerator'); | ||
var _asyncToGenerator3 = _interopRequireDefault(_asyncToGenerator2); | ||
var _isomorphicFetch = require('isomorphic-fetch'); | ||
@@ -15,9 +28,9 @@ | ||
var _lodashIsplainobject = require('lodash.isplainobject'); | ||
var _lodash = require('lodash.isplainobject'); | ||
var _lodashIsplainobject2 = _interopRequireDefault(_lodashIsplainobject); | ||
var _lodash2 = _interopRequireDefault(_lodash); | ||
var _CALL_API = require('./CALL_API'); | ||
var _RSAA = require('./RSAA'); | ||
var _CALL_API2 = _interopRequireDefault(_CALL_API); | ||
var _RSAA2 = _interopRequireDefault(_RSAA); | ||
@@ -30,2 +43,4 @@ var _validation = require('./validation'); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
/** | ||
@@ -43,209 +58,204 @@ * A Redux middleware that processes RSAA actions. | ||
return function (next) { | ||
return function callee$2$0(action) { | ||
var validationErrors, _callAPI, _requestType, callAPI, endpoint, headers, method, body, credentials, bailout, types, _normalizeTypeDescriptors, requestType, successType, failureType, res; | ||
return function () { | ||
var ref = (0, _asyncToGenerator3.default)(_regenerator2.default.mark(function _callee(action) { | ||
var validationErrors, _callAPI, _requestType, callAPI, endpoint, headers, method, body, credentials, bailout, types, _normalizeTypeDescrip, _normalizeTypeDescrip2, requestType, successType, failureType, res; | ||
return _regeneratorRuntime.async(function callee$2$0$(context$3$0) { | ||
while (1) switch (context$3$0.prev = context$3$0.next) { | ||
case 0: | ||
if (_validation.isRSAA(action)) { | ||
context$3$0.next = 2; | ||
break; | ||
} | ||
return _regenerator2.default.wrap(function _callee$(_context) { | ||
while (1) { | ||
switch (_context.prev = _context.next) { | ||
case 0: | ||
if ((0, _validation.isRSAA)(action)) { | ||
_context.next = 2; | ||
break; | ||
} | ||
return context$3$0.abrupt('return', next(action)); | ||
return _context.abrupt('return', next(action)); | ||
case 2: | ||
validationErrors = _validation.validateRSAA(action); | ||
case 2: | ||
if (!validationErrors.length) { | ||
context$3$0.next = 7; | ||
break; | ||
} | ||
// Try to dispatch an error request FSA for invalid RSAAs | ||
validationErrors = (0, _validation.validateRSAA)(action); | ||
_callAPI = action[_CALL_API2['default']]; | ||
if (!validationErrors.length) { | ||
_context.next = 7; | ||
break; | ||
} | ||
if (_callAPI.types && Array.isArray(_callAPI.types)) { | ||
_requestType = _callAPI.types[0]; | ||
_callAPI = action[_RSAA2.default]; | ||
if (_requestType && _requestType.type) { | ||
_requestType = _requestType.type; | ||
} | ||
next({ | ||
type: _requestType, | ||
payload: new _errors.InvalidRSAA(validationErrors), | ||
error: true | ||
}); | ||
} | ||
return context$3$0.abrupt('return'); | ||
if (_callAPI.types && Array.isArray(_callAPI.types)) { | ||
_requestType = _callAPI.types[0]; | ||
case 7: | ||
callAPI = action[_CALL_API2['default']]; | ||
endpoint = callAPI.endpoint; | ||
headers = callAPI.headers; | ||
method = callAPI.method; | ||
body = callAPI.body; | ||
credentials = callAPI.credentials; | ||
bailout = callAPI.bailout; | ||
types = callAPI.types; | ||
_normalizeTypeDescriptors = _util.normalizeTypeDescriptors(types); | ||
requestType = _normalizeTypeDescriptors[0]; | ||
successType = _normalizeTypeDescriptors[1]; | ||
failureType = _normalizeTypeDescriptors[2]; | ||
context$3$0.prev = 19; | ||
if (_requestType && _requestType.type) { | ||
_requestType = _requestType.type; | ||
} | ||
next({ | ||
type: _requestType, | ||
payload: new _errors.InvalidRSAA(validationErrors), | ||
error: true | ||
}); | ||
} | ||
return _context.abrupt('return'); | ||
if (!(typeof bailout === 'boolean' && bailout || typeof bailout === 'function' && bailout(getState()))) { | ||
context$3$0.next = 22; | ||
break; | ||
} | ||
case 7: | ||
return context$3$0.abrupt('return'); | ||
// Parse the validated RSAA action | ||
callAPI = action[_RSAA2.default]; | ||
endpoint = callAPI.endpoint; | ||
headers = callAPI.headers; | ||
method = callAPI.method; | ||
body = callAPI.body; | ||
credentials = callAPI.credentials; | ||
bailout = callAPI.bailout; | ||
types = callAPI.types; | ||
_normalizeTypeDescrip = (0, _util.normalizeTypeDescriptors)(types); | ||
_normalizeTypeDescrip2 = (0, _slicedToArray3.default)(_normalizeTypeDescrip, 3); | ||
requestType = _normalizeTypeDescrip2[0]; | ||
successType = _normalizeTypeDescrip2[1]; | ||
failureType = _normalizeTypeDescrip2[2]; | ||
case 22: | ||
context$3$0.next = 30; | ||
break; | ||
// Should we bail out? | ||
case 24: | ||
context$3$0.prev = 24; | ||
context$3$0.t0 = context$3$0['catch'](19); | ||
context$3$0.next = 28; | ||
return _regeneratorRuntime.awrap(_util.actionWith(_extends({}, requestType, { | ||
payload: new _errors.RequestError('[CALL_API].bailout function failed'), | ||
error: true | ||
}), [action, getState()])); | ||
_context.prev = 20; | ||
case 28: | ||
context$3$0.t1 = context$3$0.sent; | ||
return context$3$0.abrupt('return', next(context$3$0.t1)); | ||
if (!(typeof bailout === 'boolean' && bailout || typeof bailout === 'function' && bailout(getState()))) { | ||
_context.next = 23; | ||
break; | ||
} | ||
case 30: | ||
if (!(typeof endpoint === 'function')) { | ||
context$3$0.next = 41; | ||
break; | ||
} | ||
return _context.abrupt('return'); | ||
context$3$0.prev = 31; | ||
case 23: | ||
_context.next = 31; | ||
break; | ||
endpoint = endpoint(getState()); | ||
context$3$0.next = 41; | ||
break; | ||
case 25: | ||
_context.prev = 25; | ||
_context.t0 = _context['catch'](20); | ||
_context.next = 29; | ||
return (0, _util.actionWith)((0, _extends3.default)({}, requestType, { | ||
payload: new _errors.RequestError('[RSAA].bailout function failed'), | ||
error: true | ||
}), [action, getState()]); | ||
case 35: | ||
context$3$0.prev = 35; | ||
context$3$0.t2 = context$3$0['catch'](31); | ||
context$3$0.next = 39; | ||
return _regeneratorRuntime.awrap(_util.actionWith(_extends({}, requestType, { | ||
payload: new _errors.RequestError('[CALL_API].endpoint function failed'), | ||
error: true | ||
}), [action, getState()])); | ||
case 29: | ||
_context.t1 = _context.sent; | ||
return _context.abrupt('return', next(_context.t1)); | ||
case 39: | ||
context$3$0.t3 = context$3$0.sent; | ||
return context$3$0.abrupt('return', next(context$3$0.t3)); | ||
case 31: | ||
if (!(typeof endpoint === 'function')) { | ||
_context.next = 42; | ||
break; | ||
} | ||
case 41: | ||
if (!(typeof headers === 'function')) { | ||
context$3$0.next = 52; | ||
break; | ||
} | ||
_context.prev = 32; | ||
context$3$0.prev = 42; | ||
endpoint = endpoint(getState()); | ||
_context.next = 42; | ||
break; | ||
headers = headers(getState()); | ||
context$3$0.next = 52; | ||
break; | ||
case 36: | ||
_context.prev = 36; | ||
_context.t2 = _context['catch'](32); | ||
_context.next = 40; | ||
return (0, _util.actionWith)((0, _extends3.default)({}, requestType, { | ||
payload: new _errors.RequestError('[RSAA].endpoint function failed'), | ||
error: true | ||
}), [action, getState()]); | ||
case 46: | ||
context$3$0.prev = 46; | ||
context$3$0.t4 = context$3$0['catch'](42); | ||
context$3$0.next = 50; | ||
return _regeneratorRuntime.awrap(_util.actionWith(_extends({}, requestType, { | ||
payload: new _errors.RequestError('[CALL_API].headers function failed'), | ||
error: true | ||
}), [action, getState()])); | ||
case 40: | ||
_context.t3 = _context.sent; | ||
return _context.abrupt('return', next(_context.t3)); | ||
case 50: | ||
context$3$0.t5 = context$3$0.sent; | ||
return context$3$0.abrupt('return', next(context$3$0.t5)); | ||
case 42: | ||
if (!(typeof headers === 'function')) { | ||
_context.next = 53; | ||
break; | ||
} | ||
case 52: | ||
context$3$0.next = 54; | ||
return _regeneratorRuntime.awrap(_util.actionWith(requestType, [action, getState()])); | ||
_context.prev = 43; | ||
case 54: | ||
context$3$0.t6 = context$3$0.sent; | ||
next(context$3$0.t6); | ||
context$3$0.prev = 56; | ||
context$3$0.next = 59; | ||
return _regeneratorRuntime.awrap(_isomorphicFetch2['default'](endpoint, { method: method, body: body, credentials: credentials, headers: headers })); | ||
headers = headers(getState()); | ||
_context.next = 53; | ||
break; | ||
case 59: | ||
res = context$3$0.sent; | ||
context$3$0.next = 68; | ||
break; | ||
case 47: | ||
_context.prev = 47; | ||
_context.t4 = _context['catch'](43); | ||
_context.next = 51; | ||
return (0, _util.actionWith)((0, _extends3.default)({}, requestType, { | ||
payload: new _errors.RequestError('[RSAA].headers function failed'), | ||
error: true | ||
}), [action, getState()]); | ||
case 62: | ||
context$3$0.prev = 62; | ||
context$3$0.t7 = context$3$0['catch'](56); | ||
context$3$0.next = 66; | ||
return _regeneratorRuntime.awrap(_util.actionWith(_extends({}, requestType, { | ||
payload: new _errors.RequestError(context$3$0.t7.message), | ||
error: true | ||
}), [action, getState()])); | ||
case 51: | ||
_context.t5 = _context.sent; | ||
return _context.abrupt('return', next(_context.t5)); | ||
case 66: | ||
context$3$0.t8 = context$3$0.sent; | ||
return context$3$0.abrupt('return', next(context$3$0.t8)); | ||
case 53: | ||
_context.next = 55; | ||
return (0, _util.actionWith)(requestType, [action, getState()]); | ||
case 68: | ||
if (!res.ok) { | ||
context$3$0.next = 75; | ||
break; | ||
} | ||
case 55: | ||
_context.t6 = _context.sent; | ||
next(_context.t6); | ||
_context.prev = 57; | ||
_context.next = 60; | ||
return (0, _isomorphicFetch2.default)(endpoint, { method: method, body: body, credentials: credentials, headers: headers }); | ||
context$3$0.next = 71; | ||
return _regeneratorRuntime.awrap(_util.actionWith(successType, [action, getState(), res])); | ||
case 60: | ||
res = _context.sent; | ||
_context.next = 69; | ||
break; | ||
case 71: | ||
context$3$0.t9 = context$3$0.sent; | ||
return context$3$0.abrupt('return', next(context$3$0.t9)); | ||
case 63: | ||
_context.prev = 63; | ||
_context.t7 = _context['catch'](57); | ||
_context.next = 67; | ||
return (0, _util.actionWith)((0, _extends3.default)({}, requestType, { | ||
payload: new _errors.RequestError(_context.t7.message), | ||
error: true | ||
}), [action, getState()]); | ||
case 75: | ||
context$3$0.next = 77; | ||
return _regeneratorRuntime.awrap(_util.actionWith(_extends({}, failureType, { | ||
error: true | ||
}), [action, getState(), res])); | ||
case 67: | ||
_context.t8 = _context.sent; | ||
return _context.abrupt('return', next(_context.t8)); | ||
case 77: | ||
context$3$0.t10 = context$3$0.sent; | ||
return context$3$0.abrupt('return', next(context$3$0.t10)); | ||
case 69: | ||
if (!res.ok) { | ||
_context.next = 76; | ||
break; | ||
} | ||
case 79: | ||
case 'end': | ||
return context$3$0.stop(); | ||
} | ||
}, null, _this, [[19, 24], [31, 35], [42, 46], [56, 62]]); | ||
}; | ||
}; | ||
} | ||
_context.next = 72; | ||
return (0, _util.actionWith)(successType, [action, getState(), res]); | ||
exports.apiMiddleware = apiMiddleware; | ||
case 72: | ||
_context.t9 = _context.sent; | ||
return _context.abrupt('return', next(_context.t9)); | ||
// Do not process actions without a [CALL_API] property | ||
case 76: | ||
_context.next = 78; | ||
return (0, _util.actionWith)((0, _extends3.default)({}, failureType, { | ||
error: true | ||
}), [action, getState(), res]); | ||
// Try to dispatch an error request FSA for invalid RSAAs | ||
case 78: | ||
_context.t10 = _context.sent; | ||
return _context.abrupt('return', next(_context.t10)); | ||
// Parse the validated RSAA action | ||
case 80: | ||
case 'end': | ||
return _context.stop(); | ||
} | ||
} | ||
}, _callee, _this, [[20, 25], [32, 36], [43, 47], [57, 63]]); | ||
})); | ||
return function (_x) { | ||
return ref.apply(this, arguments); | ||
}; | ||
}(); | ||
}; | ||
} | ||
// Should we bail out? | ||
// Process [CALL_API].endpoint function | ||
// Process [CALL_API].headers function | ||
// We can now dispatch the request FSA | ||
// Make the API call | ||
// The request was malformed, or there was a network error | ||
// Process the server response | ||
exports.apiMiddleware = apiMiddleware; |
246
lib/util.js
'use strict'; | ||
var _extends = require('babel-runtime/helpers/extends')['default']; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
exports.actionWith = exports.normalizeTypeDescriptors = exports.getJSON = undefined; | ||
var _regeneratorRuntime = require('babel-runtime/regenerator')['default']; | ||
var _toConsumableArray2 = require('babel-runtime/helpers/toConsumableArray'); | ||
var _Promise = require('babel-runtime/core-js/promise')['default']; | ||
var _toConsumableArray3 = _interopRequireDefault(_toConsumableArray2); | ||
exports.__esModule = true; | ||
var _extends2 = require('babel-runtime/helpers/extends'); | ||
var _errors = require('./errors'); | ||
var _extends3 = _interopRequireDefault(_extends2); | ||
var _typeof2 = require('babel-runtime/helpers/typeof'); | ||
var _typeof3 = _interopRequireDefault(_typeof2); | ||
var _slicedToArray2 = require('babel-runtime/helpers/slicedToArray'); | ||
var _slicedToArray3 = _interopRequireDefault(_slicedToArray2); | ||
var _regenerator = require('babel-runtime/regenerator'); | ||
var _regenerator2 = _interopRequireDefault(_regenerator); | ||
var _promise = require('babel-runtime/core-js/promise'); | ||
var _promise2 = _interopRequireDefault(_promise); | ||
var _asyncToGenerator2 = require('babel-runtime/helpers/asyncToGenerator'); | ||
var _asyncToGenerator3 = _interopRequireDefault(_asyncToGenerator2); | ||
/** | ||
@@ -21,35 +44,43 @@ * Extract JSON body from a server response | ||
*/ | ||
function getJSON(res) { | ||
var contentType, emptyCodes; | ||
return _regeneratorRuntime.async(function getJSON$(context$1$0) { | ||
while (1) switch (context$1$0.prev = context$1$0.next) { | ||
case 0: | ||
contentType = res.headers.get('Content-Type'); | ||
emptyCodes = [204, 205]; | ||
if (!(! ~emptyCodes.indexOf(res.status) && contentType && ~contentType.indexOf('json'))) { | ||
context$1$0.next = 8; | ||
break; | ||
} | ||
var getJSON = function () { | ||
var ref = (0, _asyncToGenerator3.default)(_regenerator2.default.mark(function _callee(res) { | ||
var contentType, emptyCodes; | ||
return _regenerator2.default.wrap(function _callee$(_context) { | ||
while (1) { | ||
switch (_context.prev = _context.next) { | ||
case 0: | ||
contentType = res.headers.get('Content-Type'); | ||
emptyCodes = [204, 205]; | ||
context$1$0.next = 5; | ||
return _regeneratorRuntime.awrap(res.json()); | ||
if (!(! ~emptyCodes.indexOf(res.status) && contentType && ~contentType.indexOf('json'))) { | ||
_context.next = 8; | ||
break; | ||
} | ||
case 5: | ||
return context$1$0.abrupt('return', context$1$0.sent); | ||
_context.next = 5; | ||
return res.json(); | ||
case 8: | ||
context$1$0.next = 10; | ||
return _regeneratorRuntime.awrap(_Promise.resolve()); | ||
case 5: | ||
return _context.abrupt('return', _context.sent); | ||
case 10: | ||
return context$1$0.abrupt('return', context$1$0.sent); | ||
case 8: | ||
_context.next = 10; | ||
return _promise2.default.resolve(); | ||
case 11: | ||
case 'end': | ||
return context$1$0.stop(); | ||
} | ||
}, null, this); | ||
} | ||
case 10: | ||
return _context.abrupt('return', _context.sent); | ||
case 11: | ||
case 'end': | ||
return _context.stop(); | ||
} | ||
} | ||
}, _callee, this); | ||
})); | ||
return function getJSON(_x) { | ||
return ref.apply(this, arguments); | ||
}; | ||
}(); | ||
/** | ||
@@ -61,18 +92,92 @@ * Blow up string or symbol types into full-fledged type descriptors, | ||
* @access private | ||
* @param {array} types - The [CALL_API].types from a validated RSAA | ||
* @param {array} types - The [RSAA].types from a validated RSAA | ||
* @returns {array} | ||
*/ | ||
/** | ||
* Evaluate a type descriptor to an FSA | ||
* | ||
* @function actionWith | ||
* @access private | ||
* @param {object} descriptor - A type descriptor | ||
* @param {array} args - The array of arguments for `payload` and `meta` function properties | ||
* @returns {object} | ||
*/ | ||
var actionWith = function () { | ||
var ref = (0, _asyncToGenerator3.default)(_regenerator2.default.mark(function _callee2(descriptor, args) { | ||
return _regenerator2.default.wrap(function _callee2$(_context2) { | ||
while (1) { | ||
switch (_context2.prev = _context2.next) { | ||
case 0: | ||
_context2.prev = 0; | ||
_context2.next = 3; | ||
return typeof descriptor.payload === 'function' ? descriptor.payload.apply(descriptor, (0, _toConsumableArray3.default)(args)) : descriptor.payload; | ||
case 3: | ||
descriptor.payload = _context2.sent; | ||
_context2.next = 10; | ||
break; | ||
case 6: | ||
_context2.prev = 6; | ||
_context2.t0 = _context2['catch'](0); | ||
descriptor.payload = new _errors.InternalError(_context2.t0.message); | ||
descriptor.error = true; | ||
case 10: | ||
_context2.prev = 10; | ||
_context2.next = 13; | ||
return typeof descriptor.meta === 'function' ? descriptor.meta.apply(descriptor, (0, _toConsumableArray3.default)(args)) : descriptor.meta; | ||
case 13: | ||
descriptor.meta = _context2.sent; | ||
_context2.next = 21; | ||
break; | ||
case 16: | ||
_context2.prev = 16; | ||
_context2.t1 = _context2['catch'](10); | ||
delete descriptor.meta; | ||
descriptor.payload = new _errors.InternalError(_context2.t1.message); | ||
descriptor.error = true; | ||
case 21: | ||
return _context2.abrupt('return', descriptor); | ||
case 22: | ||
case 'end': | ||
return _context2.stop(); | ||
} | ||
} | ||
}, _callee2, this, [[0, 6], [10, 16]]); | ||
})); | ||
return function actionWith(_x2, _x3) { | ||
return ref.apply(this, arguments); | ||
}; | ||
}(); | ||
var _errors = require('./errors'); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
function normalizeTypeDescriptors(types) { | ||
var requestType = types[0]; | ||
var successType = types[1]; | ||
var failureType = types[2]; | ||
var _types = (0, _slicedToArray3.default)(types, 3); | ||
if (typeof requestType === 'string' || typeof requestType === 'symbol') { | ||
var requestType = _types[0]; | ||
var successType = _types[1]; | ||
var failureType = _types[2]; | ||
if (typeof requestType === 'string' || (typeof requestType === 'undefined' ? 'undefined' : (0, _typeof3.default)(requestType)) === 'symbol') { | ||
requestType = { type: requestType }; | ||
} | ||
if (typeof successType === 'string' || typeof successType === 'symbol') { | ||
if (typeof successType === 'string' || (typeof successType === 'undefined' ? 'undefined' : (0, _typeof3.default)(successType)) === 'symbol') { | ||
successType = { type: successType }; | ||
} | ||
successType = _extends({ | ||
successType = (0, _extends3.default)({ | ||
payload: function payload(action, state, res) { | ||
@@ -83,6 +188,6 @@ return getJSON(res); | ||
if (typeof failureType === 'string' || typeof failureType === 'symbol') { | ||
if (typeof failureType === 'string' || (typeof failureType === 'undefined' ? 'undefined' : (0, _typeof3.default)(failureType)) === 'symbol') { | ||
failureType = { type: failureType }; | ||
} | ||
failureType = _extends({ | ||
failureType = (0, _extends3.default)({ | ||
payload: function payload(action, state, res) { | ||
@@ -96,63 +201,4 @@ return getJSON(res).then(function (json) { | ||
return [requestType, successType, failureType]; | ||
} | ||
/** | ||
* Evaluate a type descriptor to an FSA | ||
* | ||
* @function actionWith | ||
* @access private | ||
* @param {object} descriptor - A type descriptor | ||
* @param {array} args - The array of arguments for `payload` and `meta` function properties | ||
* @returns {object} | ||
*/ | ||
function actionWith(descriptor, args) { | ||
return _regeneratorRuntime.async(function actionWith$(context$1$0) { | ||
while (1) switch (context$1$0.prev = context$1$0.next) { | ||
case 0: | ||
context$1$0.prev = 0; | ||
context$1$0.next = 3; | ||
return _regeneratorRuntime.awrap(typeof descriptor.payload === 'function' ? descriptor.payload.apply(descriptor, args) : descriptor.payload); | ||
case 3: | ||
descriptor.payload = context$1$0.sent; | ||
context$1$0.next = 10; | ||
break; | ||
case 6: | ||
context$1$0.prev = 6; | ||
context$1$0.t0 = context$1$0['catch'](0); | ||
descriptor.payload = new _errors.InternalError(context$1$0.t0.message); | ||
descriptor.error = true; | ||
case 10: | ||
context$1$0.prev = 10; | ||
context$1$0.next = 13; | ||
return _regeneratorRuntime.awrap(typeof descriptor.meta === 'function' ? descriptor.meta.apply(descriptor, args) : descriptor.meta); | ||
case 13: | ||
descriptor.meta = context$1$0.sent; | ||
context$1$0.next = 21; | ||
break; | ||
case 16: | ||
context$1$0.prev = 16; | ||
context$1$0.t1 = context$1$0['catch'](10); | ||
delete descriptor.meta; | ||
descriptor.payload = new _errors.InternalError(context$1$0.t1.message); | ||
descriptor.error = true; | ||
case 21: | ||
return context$1$0.abrupt('return', descriptor); | ||
case 22: | ||
case 'end': | ||
return context$1$0.stop(); | ||
} | ||
}, null, this, [[0, 6], [10, 16]]); | ||
} | ||
exports.getJSON = getJSON; | ||
}exports.getJSON = getJSON; | ||
exports.normalizeTypeDescriptors = normalizeTypeDescriptors; | ||
exports.actionWith = actionWith; |
'use strict'; | ||
var _interopRequireDefault = require('babel-runtime/helpers/interop-require-default')['default']; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
exports.isValidRSAA = exports.validateRSAA = exports.isValidTypeDescriptor = exports.isRSAA = undefined; | ||
exports.__esModule = true; | ||
var _slicedToArray2 = require('babel-runtime/helpers/slicedToArray'); | ||
var _CALL_API = require('./CALL_API'); | ||
var _slicedToArray3 = _interopRequireDefault(_slicedToArray2); | ||
var _CALL_API2 = _interopRequireDefault(_CALL_API); | ||
var _typeof2 = require('babel-runtime/helpers/typeof'); | ||
var _lodashIsplainobject = require('lodash.isplainobject'); | ||
var _typeof3 = _interopRequireDefault(_typeof2); | ||
var _lodashIsplainobject2 = _interopRequireDefault(_lodashIsplainobject); | ||
var _RSAA = require('./RSAA'); | ||
var _RSAA2 = _interopRequireDefault(_RSAA); | ||
var _lodash = require('lodash.isplainobject'); | ||
var _lodash2 = _interopRequireDefault(_lodash); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
/** | ||
* Is the given action a plain JavaScript object with a [CALL_API] property? | ||
* Is the given action a plain JavaScript object with an [RSAA] property? | ||
* | ||
@@ -24,3 +35,3 @@ * @function isRSAA | ||
function isRSAA(action) { | ||
return _lodashIsplainobject2['default'](action) && action.hasOwnProperty(_CALL_API2['default']); | ||
return (0, _lodash2.default)(action) && action.hasOwnProperty(_RSAA2.default); | ||
} | ||
@@ -39,3 +50,3 @@ | ||
if (!_lodashIsplainobject2['default'](obj)) { | ||
if (!(0, _lodash2.default)(obj)) { | ||
return false; | ||
@@ -50,3 +61,3 @@ } | ||
return false; | ||
} else if (typeof obj.type !== 'string' && typeof obj.type !== 'symbol') { | ||
} else if (typeof obj.type !== 'string' && (0, _typeof3.default)(obj.type) !== 'symbol') { | ||
return false; | ||
@@ -74,3 +85,3 @@ } | ||
if (!isRSAA(action)) { | ||
validationErrors.push('RSAAs must be plain JavaScript objects with a [CALL_API] property'); | ||
validationErrors.push('RSAAs must be plain JavaScript objects with an [RSAA] property'); | ||
return validationErrors; | ||
@@ -80,3 +91,3 @@ } | ||
for (var key in action) { | ||
if (key !== [_CALL_API2['default']]) { | ||
if (key !== _RSAA2.default) { | ||
validationErrors.push('Invalid root key: ' + key); | ||
@@ -86,9 +97,9 @@ } | ||
var callAPI = action[_CALL_API2['default']]; | ||
if (!_lodashIsplainobject2['default'](callAPI)) { | ||
validationErrors.push('[CALL_API] property must be a plain JavaScript object'); | ||
var callAPI = action[_RSAA2.default]; | ||
if (!(0, _lodash2.default)(callAPI)) { | ||
validationErrors.push('[RSAA] property must be a plain JavaScript object'); | ||
} | ||
for (var key in callAPI) { | ||
if (! ~validCallAPIKeys.indexOf(key)) { | ||
validationErrors.push('Invalid [CALL_API] key: ' + key); | ||
for (var _key in callAPI) { | ||
if (! ~validCallAPIKeys.indexOf(_key)) { | ||
validationErrors.push('Invalid [RSAA] key: ' + _key); | ||
} | ||
@@ -105,44 +116,46 @@ } | ||
if (typeof endpoint === 'undefined') { | ||
validationErrors.push('[CALL_API] must have an endpoint property'); | ||
validationErrors.push('[RSAA] must have an endpoint property'); | ||
} else if (typeof endpoint !== 'string' && typeof endpoint !== 'function') { | ||
validationErrors.push('[CALL_API].endpoint property must be a string or a function'); | ||
validationErrors.push('[RSAA].endpoint property must be a string or a function'); | ||
} | ||
if (typeof method === 'undefined') { | ||
validationErrors.push('[CALL_API] must have a method property'); | ||
validationErrors.push('[RSAA] must have a method property'); | ||
} else if (typeof method !== 'string') { | ||
validationErrors.push('[CALL_API].method property must be a string'); | ||
validationErrors.push('[RSAA].method property must be a string'); | ||
} else if (! ~validMethods.indexOf(method.toUpperCase())) { | ||
validationErrors.push('Invalid [CALL_API].method: ' + method.toUpperCase()); | ||
validationErrors.push('Invalid [RSAA].method: ' + method.toUpperCase()); | ||
} | ||
if (typeof headers !== 'undefined' && !_lodashIsplainobject2['default'](headers) && typeof headers !== 'function') { | ||
validationErrors.push('[CALL_API].headers property must be undefined, a plain JavaScript object, or a function'); | ||
if (typeof headers !== 'undefined' && !(0, _lodash2.default)(headers) && typeof headers !== 'function') { | ||
validationErrors.push('[RSAA].headers property must be undefined, a plain JavaScript object, or a function'); | ||
} | ||
if (typeof credentials !== 'undefined') { | ||
if (typeof credentials !== 'string') { | ||
validationErrors.push('[CALL_API].credentials property must be undefined, or a string'); | ||
validationErrors.push('[RSAA].credentials property must be undefined, or a string'); | ||
} else if (! ~validCredentials.indexOf(credentials)) { | ||
validationErrors.push('Invalid [CALL_API].credentials: ' + credentials); | ||
validationErrors.push('Invalid [RSAA].credentials: ' + credentials); | ||
} | ||
} | ||
if (typeof bailout !== 'undefined' && typeof bailout !== 'boolean' && typeof bailout !== 'function') { | ||
validationErrors.push('[CALL_API].bailout property must be undefined, a boolean, or a function'); | ||
validationErrors.push('[RSAA].bailout property must be undefined, a boolean, or a function'); | ||
} | ||
if (typeof types === 'undefined') { | ||
validationErrors.push('[CALL_API] must have a types property'); | ||
validationErrors.push('[RSAA] must have a types property'); | ||
} else if (!Array.isArray(types) || types.length !== 3) { | ||
validationErrors.push('[CALL_API].types property must be an array of length 3'); | ||
validationErrors.push('[RSAA].types property must be an array of length 3'); | ||
} else { | ||
var requestType = types[0]; | ||
var successType = types[1]; | ||
var failureType = types[2]; | ||
var _types = (0, _slicedToArray3.default)(types, 3); | ||
if (typeof requestType !== 'string' && typeof requestType !== 'symbol' && !isValidTypeDescriptor(requestType)) { | ||
var requestType = _types[0]; | ||
var successType = _types[1]; | ||
var failureType = _types[2]; | ||
if (typeof requestType !== 'string' && (typeof requestType === 'undefined' ? 'undefined' : (0, _typeof3.default)(requestType)) !== 'symbol' && !isValidTypeDescriptor(requestType)) { | ||
validationErrors.push('Invalid request type'); | ||
} | ||
if (typeof successType !== 'string' && typeof successType !== 'symbol' && !isValidTypeDescriptor(successType)) { | ||
if (typeof successType !== 'string' && (typeof successType === 'undefined' ? 'undefined' : (0, _typeof3.default)(successType)) !== 'symbol' && !isValidTypeDescriptor(successType)) { | ||
validationErrors.push('Invalid success type'); | ||
} | ||
if (typeof failureType !== 'string' && typeof failureType !== 'symbol' && !isValidTypeDescriptor(failureType)) { | ||
if (typeof failureType !== 'string' && (typeof failureType === 'undefined' ? 'undefined' : (0, _typeof3.default)(failureType)) !== 'symbol' && !isValidTypeDescriptor(failureType)) { | ||
validationErrors.push('Invalid failure type'); | ||
@@ -149,0 +162,0 @@ } |
{ | ||
"name": "redux-api-middleware", | ||
"version": "1.0.2", | ||
"version": "2.0.0-beta.1", | ||
"description": "Redux middleware for calling an API.", | ||
@@ -29,3 +29,4 @@ "main": "lib/index.js", | ||
"dependencies": { | ||
"babel-runtime": "^5.8.25", | ||
"babel-plugin-transform-runtime": "^6.5.2", | ||
"babel-runtime": "^6.5.0", | ||
"isomorphic-fetch": "^2.1.1", | ||
@@ -35,8 +36,11 @@ "lodash.isplainobject": "^3.2.0" | ||
"devDependencies": { | ||
"babel": "^5.8.23", | ||
"babel-eslint": "^4.1.3", | ||
"babel-istanbul": "^0.3.20", | ||
"babel-cli": "^6.5.1", | ||
"babel-eslint": "^4.1.8", | ||
"babel-istanbul": "^0.6.0", | ||
"babel-preset-es2015": "^6.5.0", | ||
"babel-preset-stage-0": "^6.5.0", | ||
"coveralls": "^2.11.4", | ||
"eslint": "^1.6.0", | ||
"eslint-plugin-babel": "^2.1.1", | ||
"eslint": "^2.0.0", | ||
"eslint-plugin-babel": "^3.1.0", | ||
"estraverse-fb": "^1.3.1", | ||
"nock": "^2.15.0", | ||
@@ -43,0 +47,0 @@ "normalizr": "^1.1.0", |
113
README.md
redux-api-middleware | ||
==================== | ||
[![Build Status](https://travis-ci.org/agraboso/redux-api-middleware.svg?branch=master)](https://travis-ci.org/agraboso/redux-api-middleware) [![Coverage Status](https://coveralls.io/repos/agraboso/redux-api-middleware/badge.svg?branch=master&service=github)](https://coveralls.io/github/agraboso/redux-api-middleware?branch=master) | ||
## This `next` branch is 2.0.0-beta in development! | ||
Aught to be stable but still in development while we iron out bugs. | ||
[![Build Status](https://travis-ci.org/agraboso/redux-api-middleware.svg?branch=next)](https://travis-ci.org/agraboso/redux-api-middleware) [![Coverage Status](https://coveralls.io/repos/agraboso/redux-api-middleware/badge.svg?branch=next&service=github)](https://coveralls.io/github/agraboso/redux-api-middleware?branch=next) | ||
[Redux middleware](http://rackt.github.io/redux/docs/advanced/Middleware.html) for calling an API. | ||
@@ -31,3 +34,3 @@ | ||
RSAAs are identified by the presence of a `[CALL_API]` property, where [`CALL_API`](#call_api) is a `Symbol` defined in, and exported by `redux-api-middleware`. They contain information describing an API call and three different types of FSAs, known as the *request*, *success* and *failure* FSAs. | ||
RSAAs are identified by the presence of an `[RSAA]` property, where [`RSAA`](#rsaa) is a `String` constant defined in, and exported by `redux-api-middleware`. They contain information describing an API call and three different types of FSAs, known as the *request*, *success* and *failure* FSAs. | ||
@@ -39,6 +42,6 @@ ### A simple example | ||
```js | ||
import { CALL_API } from `redux-api-middleware`; | ||
import { RSAA } from `redux-api-middleware`; // RSAA = '@@redux-api-middleware/RSAA' | ||
{ | ||
[CALL_API]: { | ||
[RSAA]: { | ||
endpoint: 'http://www.example.com/api/users', | ||
@@ -124,5 +127,5 @@ method: 'GET', | ||
The parameters of the API call are specified by root properties of the `[CALL_API]` property of an RSAA. | ||
The parameters of the API call are specified by root properties of the `[RSAA]` property of an RSAA. | ||
#### `[CALL_API].endpoint` | ||
#### `[RSAA].endpoint` | ||
@@ -133,3 +136,3 @@ The URL endpoint for the API call. | ||
#### `[CALL_API].method` | ||
#### `[RSAA].method` | ||
@@ -140,9 +143,9 @@ The HTTP method for the API call. | ||
#### `[CALL_API].body` | ||
#### `[RSAA].body` | ||
The body of the API call. | ||
`redux-api-middleware` uses [`isomorphic-fetch`](https://github.com/matthew-andrews/isomorphic-fetch) to make the API call. `[CALL_API].body` should hence be a valid body according to the the [fetch specification](https://fetch.spec.whatwg.org). In most cases, this will be a JSON-encoded string or a [`FormData`](https://developer.mozilla.org/en/docs/Web/API/FormData) object. | ||
`redux-api-middleware` uses [`isomorphic-fetch`](https://github.com/matthew-andrews/isomorphic-fetch) to make the API call. `[RSAA].body` should hence be a valid body according to the the [fetch specification](https://fetch.spec.whatwg.org). In most cases, this will be a JSON-encoded string or a [`FormData`](https://developer.mozilla.org/en/docs/Web/API/FormData) object. | ||
#### `[CALL_API].headers` | ||
#### `[RSAA].headers` | ||
@@ -155,3 +158,3 @@ The HTTP headers for the API call. | ||
{ | ||
[CALL_API]: { | ||
[RSAA]: { | ||
... | ||
@@ -166,3 +169,3 @@ headers: { 'Content-Type': 'application/json' } | ||
#### `[CALL_API].credentials` | ||
#### `[RSAA].credentials` | ||
@@ -181,14 +184,14 @@ Whether or not to send cookies with the API call. | ||
You can tell `redux-api-middleware` to not make the API call through `[CALL_API].bailout`. If the value is `true`, the RSAA will die here, and no FSA will be passed on to the next middleware. | ||
You can tell `redux-api-middleware` to not make the API call through `[RSAA].bailout`. If the value is `true`, the RSAA will die here, and no FSA will be passed on to the next middleware. | ||
A more useful possibility is to give `[CALL_API].bailout` a function. At runtime, it will be passed the state of your Redux store as its only argument, if the return value of the function is `true`, the API call will not be made. | ||
A more useful possibility is to give `[RSAA].bailout` a function. At runtime, it will be passed the state of your Redux store as its only argument, if the return value of the function is `true`, the API call will not be made. | ||
### Lifecycle | ||
The `[CALL_API].types` property controls the output of `redux-api-middleware`. The simplest form it can take is an array of length 3 consisting of string constants (or symbols), as in our [example](#a-simple-example) above. This results in the default behavior we now describe. | ||
The `[RSAA].types` property controls the output of `redux-api-middleware`. The simplest form it can take is an array of length 3 consisting of string constants (or symbols), as in our [example](#a-simple-example) above. This results in the default behavior we now describe. | ||
1. When `redux-api-middleware` receives an action, it first checks whether it has a `[CALL_API]` property. If it does not, it was clearly not intended for processing with `redux-api-middleware`, and so it is unceremoniously passed on to the next middleware. | ||
1. When `redux-api-middleware` receives an action, it first checks whether it has an `[RSAA]` property. If it does not, it was clearly not intended for processing with `redux-api-middleware`, and so it is unceremoniously passed on to the next middleware. | ||
2. It is now time to validate the action against the [RSAA definition](#redux-standard-api-calling-actions). If there are any validation errors, a *request* FSA will be dispatched (if at all possible) with the following properties: | ||
- `type`: the string constant in the first position of the `[CALL_API].types` array; | ||
- `type`: the string constant in the first position of the `[RSAA].types` array; | ||
- `payload`: an [`InvalidRSAA`](#invalidrsaa) object containing a list of said validation errors; | ||
@@ -200,11 +203,11 @@ - `error: true`. | ||
3. Now that `redux-api-middleware` is sure it has received a valid RSAA, it will try making the API call. If everything is alright, a *request* FSA will be dispatched with the following property: | ||
- `type`: the string constant in the first position of the `[CALL_API].types` array. | ||
- `type`: the string constant in the first position of the `[RSAA].types` array. | ||
But errors may pop up at this stage, for several reasons: | ||
- `redux-api-middleware` has to call those of `[CALL_API].bailout`, `[CALL_API].endpoint` and `[CALL_API].headers` that happen to be a function, which may throw an error; | ||
- `isomorphic-fetch` may throw an error: the RSAA definition is not strong enough to preclude that from happening (you may, for example, send in a `[CALL_API].body` that is not valid according to the fetch specification — mind the SHOULDs in the [RSAA definition](#redux-standard-api-calling-actions)); | ||
- `redux-api-middleware` has to call those of `[RSAA].bailout`, `[RSAA].endpoint` and `[RSAA].headers` that happen to be a function, which may throw an error; | ||
- `isomorphic-fetch` may throw an error: the RSAA definition is not strong enough to preclude that from happening (you may, for example, send in a `[RSAA].body` that is not valid according to the fetch specification — mind the SHOULDs in the [RSAA definition](#redux-standard-api-calling-actions)); | ||
- a network failure occurs (the network is unreachable, the server responds with an error,...). | ||
If such an error occurs, a different *request* FSA will be dispatched (*instead* of the one described above). It will contain the following properties: | ||
- `type`: the string constant in the first position of the `[CALL_API].types` array; | ||
- `type`: the string constant in the first position of the `[RSAA].types` array; | ||
- `payload`: a [`RequestError`](#requesterror) object containing an error message; | ||
@@ -214,7 +217,7 @@ - `error: true`. | ||
4. If `redux-api-middleware` receives a response from the server with a status code in the 200 range, a *success* FSA will be dispatched with the following properties: | ||
- `type`: the string constant in the second position of the `[CALL_API].types` array; | ||
- `type`: the string constant in the second position of the `[RSAA].types` array; | ||
- `payload`: if the `Content-Type` header of the response is set to something JSONy (see [*Success* type descriptors](#success-type-descriptors) below), the parsed JSON response of the server, or undefined otherwise. | ||
If the status code of the response falls outside that 200 range, a *failure* FSA will dispatched instead, with the following properties: | ||
- `type`: the string constant in the third position of the `[CALL_API].types` array; | ||
- `type`: the string constant in the third position of the `[RSAA].types` array; | ||
- `payload`: an [`ApiError`](#apierror) object containing the message `` `${status} - ${statusText}` ``; | ||
@@ -225,3 +228,3 @@ - `error: true`. | ||
It is possible to customize the output of `redux-api-middleware` by replacing one or more of the string constants (or symbols) in `[CALL_API].types` by a type descriptor. | ||
It is possible to customize the output of `redux-api-middleware` by replacing one or more of the string constants (or symbols) in `[RSAA].types` by a type descriptor. | ||
@@ -245,3 +248,3 @@ A *type descriptor* is a plain JavaScript object that will be used as a blueprint for the dispatched FSAs. As such, type descriptors must have a `type` property, intended to house the string constant or symbol specifying the `type` of the resulting FSAs. | ||
{ | ||
[CALL_API]: { | ||
[RSAA]: { | ||
endpoint: 'http://www.example.com/api/users', | ||
@@ -272,3 +275,3 @@ method: 'GET', | ||
{ | ||
[CALL_API]: { | ||
[RSAA]: { | ||
endpoint: 'http://www.example.com/api/users', | ||
@@ -312,3 +315,3 @@ method: 'GET', | ||
{ | ||
[CALL_API]: { | ||
[RSAA]: { | ||
endpoint: 'http://www.example.com/api/users', | ||
@@ -374,3 +377,3 @@ method: 'GET', | ||
{ | ||
[CALL_API]: { | ||
[RSAA]: { | ||
endpoint: 'http://www.example.com/api/users/1', | ||
@@ -414,5 +417,5 @@ method: 'GET', | ||
#### `CALL_API` | ||
#### `RSAA` | ||
A JavaScript `Symbol` whose presence as a key in an action signals that `redux-api-middleware` should process said action. | ||
A JavaScript `String` whose presence as a key in an action signals that `redux-api-middleware` should process said action. | ||
@@ -425,3 +428,3 @@ #### `apiMiddleware` | ||
A function that returns `true` if `action` has a `[CALL_API]` property, and `false` otherwise. | ||
A function that returns `true` if `action` has an `[RSAA]` property, and `false` otherwise. | ||
@@ -528,4 +531,4 @@ #### `validateRSAA(action)` | ||
The definition of a *Redux Standard API-calling Action* below is the one used to validate RSAA actions. As explained in [Lifecycle](#lifecycle), | ||
- actions without a `[CALL_API]` will be passed to the next middleware without any modifications; | ||
- actions with a `[CALL_API]` property that fail validation will result in an error *request* FSA. | ||
- actions without an `[RSAA]` property will be passed to the next middleware without any modifications; | ||
- actions with an `[RSAA]` property that fail validation will result in an error *request* FSA. | ||
@@ -535,11 +538,11 @@ A *Redux Standard API-calling Action* MUST | ||
- be a plain JavaScript object, | ||
- have a `[CALL_API]` property. | ||
- have an `[RSAA]` property. | ||
A *Redux Standard API-calling Action* MUST NOT | ||
- include properties other than `[CALL_API]`. | ||
- include properties other than `[RSAA]`. | ||
#### `[CALL_API]` | ||
#### `[RSAA]` | ||
The `[CALL_API]` property MUST | ||
The `[RSAA]` property MUST | ||
@@ -551,3 +554,3 @@ - be a plain JavaScript Object, | ||
The `[CALL_API]` property MAY | ||
The `[RSAA]` property MAY | ||
@@ -559,33 +562,33 @@ - have a `body` property, | ||
The `[CALL_API]` property MUST NOT | ||
The `[RSAA]` property MUST NOT | ||
- include properties other than `endpoint`, `method`, `types`, `body`, `headers`, `credentials`, and `bailout`. | ||
#### `[CALL_API].endpoint` | ||
#### `[RSAA].endpoint` | ||
The `[CALL_API].endpoint` property MUST be a string or a function. In the second case, the function SHOULD return a string. | ||
The `[RSAA].endpoint` property MUST be a string or a function. In the second case, the function SHOULD return a string. | ||
#### `[CALL_API].method` | ||
#### `[RSAA].method` | ||
The `[CALL_API].method` property MUST be one of the strings `GET`, `HEAD`, `POST`, `PUT`, `PATCH`, `DELETE` or `OPTIONS`, in any mixture of lowercase and uppercase letters. | ||
The `[RSAA].method` property MUST be one of the strings `GET`, `HEAD`, `POST`, `PUT`, `PATCH`, `DELETE` or `OPTIONS`, in any mixture of lowercase and uppercase letters. | ||
#### `[CALL_API].body` | ||
#### `[RSAA].body` | ||
The optional `[CALL_API].body` property SHOULD be a valid body according to the the [fetch specification](https://fetch.spec.whatwg.org). | ||
The optional `[RSAA].body` property SHOULD be a valid body according to the the [fetch specification](https://fetch.spec.whatwg.org). | ||
#### `[CALL_API].headers` | ||
#### `[RSAA].headers` | ||
The optional `[CALL_API].headers` property MUST be a plain JavaScript object or a function. In the second case, the function SHOULD return a plain JavaScript object. | ||
The optional `[RSAA].headers` property MUST be a plain JavaScript object or a function. In the second case, the function SHOULD return a plain JavaScript object. | ||
#### `[CALL_API].credentials` | ||
#### `[RSAA].credentials` | ||
The optional `[CALL_API].credentials` property MUST be one of the strings `omit`, `same-origin` or `include`. | ||
The optional `[RSAA].credentials` property MUST be one of the strings `omit`, `same-origin` or `include`. | ||
#### `[CALL_API].bailout` | ||
#### `[RSAA].bailout` | ||
The optional `[CALL_API].bailout` property MUST be a boolean or a function. | ||
The optional `[RSAA].bailout` property MUST be a boolean or a function. | ||
#### `[CALL_API].types` | ||
#### `[RSAA].types` | ||
The `[CALL_API].types` property MUST be an array of length 3. Each element of the array MUST be a string, a `Symbol`, or a type descriptor. | ||
The `[RSAA].types` property MUST be an array of length 3. Each element of the array MUST be a string, a `Symbol`, or a type descriptor. | ||
@@ -618,2 +621,6 @@ #### Type descriptors | ||
## Upgrading from v1.0.x | ||
TODO | ||
## License | ||
@@ -620,0 +627,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
52823
655
617
4
14
1
+ Addedbabel-plugin-transform-runtime@6.23.0(transitive)
+ Addedbabel-runtime@6.26.0(transitive)
+ Addedcore-js@2.6.12(transitive)
+ Addedregenerator-runtime@0.11.1(transitive)
- Removedbabel-runtime@5.8.38(transitive)
- Removedcore-js@1.2.7(transitive)
Updatedbabel-runtime@^6.5.0