redux-api-middleware
Advanced tools
Comparing version 1.0.0-beta2 to 1.0.0-beta3
@@ -29,2 +29,23 @@ /** | ||
/** | ||
* Error class for a custom `payload` or `meta` function throwing | ||
* | ||
* @class InternalError | ||
* @access public | ||
* @param {string} message - the error message | ||
*/ | ||
return InvalidRSAA; | ||
})(Error); | ||
var InternalError = (function (_Error2) { | ||
_inherits(InternalError, _Error2); | ||
function InternalError(message) { | ||
_classCallCheck(this, InternalError); | ||
_Error2.call(this); | ||
this.name = 'InternalError'; | ||
this.message = message; | ||
} | ||
/** | ||
* Error class for an error raised trying to make an API call | ||
@@ -36,7 +57,7 @@ * | ||
*/ | ||
return InvalidRSAA; | ||
return InternalError; | ||
})(Error); | ||
var RequestError = (function (_Error2) { | ||
_inherits(RequestError, _Error2); | ||
var RequestError = (function (_Error3) { | ||
_inherits(RequestError, _Error3); | ||
@@ -46,3 +67,3 @@ function RequestError(message) { | ||
_Error2.call(this); | ||
_Error3.call(this); | ||
this.name = 'RequestError'; | ||
@@ -65,4 +86,4 @@ this.message = message; | ||
var ApiError = (function (_Error3) { | ||
_inherits(ApiError, _Error3); | ||
var ApiError = (function (_Error4) { | ||
_inherits(ApiError, _Error4); | ||
@@ -72,3 +93,3 @@ function ApiError(status, statusText, response) { | ||
_Error3.call(this); | ||
_Error4.call(this); | ||
this.name = 'ApiError'; | ||
@@ -85,3 +106,4 @@ this.status = status; | ||
exports.InvalidRSAA = InvalidRSAA; | ||
exports.InternalError = InternalError; | ||
exports.RequestError = RequestError; | ||
exports.ApiError = ApiError; |
@@ -11,2 +11,3 @@ /** | ||
* @exports {error} InvalidRSAA | ||
* @exports {error} InternalError | ||
* @exports {error} RequestError | ||
@@ -55,2 +56,3 @@ * @exports {error} ApiError | ||
exports.InvalidRSAA = _errors.InvalidRSAA; | ||
exports.InternalError = _errors.InternalError; | ||
exports.RequestError = _errors.RequestError; | ||
@@ -57,0 +59,0 @@ exports.ApiError = _errors.ApiError; |
@@ -168,14 +168,14 @@ 'use strict'; | ||
case 52: | ||
context$3$0.prev = 52; | ||
context$3$0.next = 55; | ||
return _regeneratorRuntime.awrap(_isomorphicFetch2['default'](endpoint, { method: method, body: body, credentials: credentials, headers: headers })); | ||
case 55: | ||
res = context$3$0.sent; | ||
context$3$0.next = 58; | ||
context$3$0.next = 54; | ||
return _regeneratorRuntime.awrap(_util.actionWith(requestType, [action, getState()])); | ||
case 58: | ||
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 })); | ||
case 59: | ||
res = context$3$0.sent; | ||
context$3$0.next = 68; | ||
@@ -186,3 +186,3 @@ break; | ||
context$3$0.prev = 62; | ||
context$3$0.t7 = context$3$0['catch'](52); | ||
context$3$0.t7 = context$3$0['catch'](56); | ||
context$3$0.next = 66; | ||
@@ -225,3 +225,3 @@ return _regeneratorRuntime.awrap(_util.actionWith(_extends({}, requestType, { | ||
} | ||
}, null, _this, [[19, 24], [31, 35], [42, 46], [52, 62]]); | ||
}, null, _this, [[19, 24], [31, 35], [42, 46], [56, 62]]); | ||
}; | ||
@@ -245,2 +245,4 @@ }; | ||
// We can now dispatch the request FSA | ||
// Make the API call | ||
@@ -247,0 +249,0 @@ |
@@ -107,25 +107,44 @@ 'use strict'; | ||
case 0: | ||
context$1$0.t0 = {}; | ||
context$1$0.t1 = descriptor; | ||
context$1$0.next = 4; | ||
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 4: | ||
context$1$0.t2 = context$1$0.sent; | ||
context$1$0.next = 7; | ||
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 7: | ||
context$1$0.t3 = context$1$0.sent; | ||
context$1$0.t4 = { | ||
payload: context$1$0.t2, | ||
meta: context$1$0.t3 | ||
}; | ||
return context$1$0.abrupt('return', _extends(context$1$0.t0, context$1$0.t1, context$1$0.t4)); | ||
case 13: | ||
descriptor.meta = context$1$0.sent; | ||
context$1$0.next = 21; | ||
break; | ||
case 10: | ||
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); | ||
}, null, this, [[0, 6], [10, 16]]); | ||
} | ||
@@ -132,0 +151,0 @@ |
{ | ||
"name": "redux-api-middleware", | ||
"version": "1.0.0-beta2", | ||
"version": "1.0.0-beta3", | ||
"description": "Redux middleware for calling an API.", | ||
@@ -5,0 +5,0 @@ "main": "lib/index.js", |
@@ -31,3 +31,3 @@ redux-api-middleware | ||
RSAAs are identified by the presence 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 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. | ||
@@ -183,3 +183,3 @@ ### A simple example | ||
1. When `redux-api-middleware` receives an action, if 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 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. | ||
@@ -206,3 +206,3 @@ 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: | ||
4. If `redux-api-middleware` receives a response from the server with a status code in the 200 range, a *success* FSA will dispatched with the following properties: | ||
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; | ||
@@ -220,6 +220,8 @@ - `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. | ||
A *type descriptor* is a plain JavaScript object that will be used as a blueprint for the dispatched FSAs. As such, types descriptors must have a `type` property, intended to house the string constant or symbol specifying the `type` of the resulting FSAs. | ||
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. | ||
They may also have `payload` and `meta` properties, which may be of any type. Functions passed as `payload` and `meta` properties of type descriptors will be evaluated at runtime. The signature of these functions should be different depending on whether the type descriptor refers to *request*, *success* or *failure* FSAs — keep reading. | ||
If a custom `payload` and `meta` function throws an error, `redux-api-middleware` will dispatch an FSA with its `error` property set to `true`, and an `InternalError` object as its `payload`. | ||
A noteworthy feature of `redux-api-middleware` is that it accepts Promises (or function that return them) in `payload` and `meta` properties of type descriptors, and it will wait for them to resolve before dispatching the FSA — so no need to use anything like `redux-promise`. | ||
@@ -431,2 +433,11 @@ | ||
#### `InternalError` | ||
An error class extending the native `Error` object. Its constructor takes a string, intended to contain an error message. | ||
`InternalError` objects have two properties: | ||
- `name: 'InternalError'`; | ||
- `message`: the argument of the call to its constructor. | ||
#### `RequestError` | ||
@@ -433,0 +444,0 @@ |
@@ -18,2 +18,17 @@ /** | ||
/** | ||
* Error class for a custom `payload` or `meta` function throwing | ||
* | ||
* @class InternalError | ||
* @access public | ||
* @param {string} message - the error message | ||
*/ | ||
class InternalError extends Error { | ||
constructor(message) { | ||
super(); | ||
this.name = 'InternalError'; | ||
this.message = message; | ||
} | ||
} | ||
/** | ||
* Error class for an error raised trying to make an API call | ||
@@ -54,2 +69,2 @@ * | ||
export { InvalidRSAA, RequestError, ApiError }; | ||
export { InvalidRSAA, InternalError, RequestError, ApiError }; |
@@ -11,2 +11,3 @@ /** | ||
* @exports {error} InvalidRSAA | ||
* @exports {error} InternalError | ||
* @exports {error} RequestError | ||
@@ -34,3 +35,3 @@ * @exports {error} ApiError | ||
import { isRSAA, validateRSAA, isValidRSAA } from './validation'; | ||
import { InvalidRSAA, RequestError, ApiError } from './errors'; | ||
import { InvalidRSAA, InternalError, RequestError, ApiError } from './errors'; | ||
import { getJSON } from './util'; | ||
@@ -45,2 +46,3 @@ import { apiMiddleware } from './middleware'; | ||
InvalidRSAA, | ||
InternalError, | ||
RequestError, | ||
@@ -47,0 +49,0 @@ ApiError, |
@@ -95,10 +95,11 @@ import fetch from 'isomorphic-fetch'; | ||
// We can now dispatch the request FSA | ||
next(await actionWith( | ||
requestType, | ||
[action, getState()] | ||
)); | ||
try { | ||
// Make the API call | ||
var res = await fetch(endpoint, { method, body, credentials, headers }); | ||
next(await actionWith( | ||
requestType, | ||
[action, getState()] | ||
)); | ||
} catch(e) { | ||
@@ -105,0 +106,0 @@ // The request was malformed, or there was a network error |
@@ -1,2 +0,2 @@ | ||
import { ApiError } from './errors'; | ||
import { InternalError, ApiError } from './errors'; | ||
@@ -69,17 +69,28 @@ /** | ||
async function actionWith(descriptor, args) { | ||
return { | ||
...descriptor, | ||
payload: await ( | ||
try { | ||
descriptor.payload = await ( | ||
typeof descriptor.payload === 'function' ? | ||
descriptor.payload(...args) : | ||
descriptor.payload | ||
), | ||
meta: await ( | ||
); | ||
} catch (e) { | ||
descriptor.payload = new InternalError(e.message); | ||
descriptor.error = true; | ||
} | ||
try { | ||
descriptor.meta = await ( | ||
typeof descriptor.meta === 'function' ? | ||
descriptor.meta(...args) : | ||
descriptor.meta | ||
) | ||
}; | ||
); | ||
} catch (e) { | ||
delete descriptor.meta; | ||
descriptor.payload = new InternalError(e.message); | ||
descriptor.error = true; | ||
} | ||
return descriptor; | ||
} | ||
export { getJSON, normalizeTypeDescriptors, actionWith }; |
@@ -7,3 +7,3 @@ import test from 'tape'; | ||
import { isRSAA, isValidTypeDescriptor, validateRSAA, isValidRSAA } from '../src/validation'; | ||
import { InvalidRSAA, RequestError, ApiError } from '../src/errors'; | ||
import { InvalidRSAA, InternalError, RequestError, ApiError } from '../src/errors'; | ||
import { getJSON, normalizeTypeDescriptors, actionWith } from '../src/util'; | ||
@@ -504,2 +504,23 @@ import { apiMiddleware } from '../src/middleware'; | ||
test('InternalError', (t) => { | ||
const error = new InternalError('error thrown in payload function'); | ||
t.ok( | ||
error instanceof Error, | ||
'is an error object' | ||
); | ||
t.equal( | ||
error.name, | ||
'InternalError', | ||
'has correct name property' | ||
); | ||
t.equal( | ||
error.message, | ||
'error thrown in payload function', | ||
'has correct message' | ||
); | ||
t.end(); | ||
}); | ||
test('RequestError', (t) => { | ||
@@ -696,4 +717,2 @@ const error = new RequestError('Network request failed'); | ||
test('actionWith', async (t) => { | ||
t.plan(8); | ||
const descriptor1 = { | ||
@@ -745,4 +764,40 @@ type: 'REQUEST', | ||
} | ||
} | ||
}; | ||
const fsa2 = await actionWith(descriptor2, passedArgs); | ||
const descriptor3 = { | ||
type: 'REQUEST', | ||
payload: (...args) => { | ||
throw new Error('error in payload function'); | ||
} | ||
}; | ||
const fsa3 = await actionWith(descriptor3, passedArgs); | ||
t.equal( | ||
fsa3.payload.message, | ||
'error in payload function', | ||
'must set FSA payload property to an error if a custom payload function throws' | ||
); | ||
t.ok( | ||
fsa3.error, | ||
'must set FSA error property to true if a custom payload function throws' | ||
); | ||
const descriptor4 = { | ||
type: 'REQUEST', | ||
meta: (...args) => { | ||
throw new Error('error in meta function'); | ||
} | ||
}; | ||
const fsa4 = await actionWith(descriptor4, passedArgs); | ||
t.equal( | ||
fsa4.payload.message, | ||
'error in meta function', | ||
'must set FSA payload property to an error if a custom meta function throws' | ||
); | ||
t.ok( | ||
fsa4.error, | ||
'must set FSA error property to true if a custom meta function throws' | ||
); | ||
t.end(); | ||
}); | ||
@@ -1060,26 +1115,53 @@ | ||
const doNext = (action) => { | ||
t.pass('next handler called'); | ||
t.equal( | ||
action.type, | ||
'REQUEST', | ||
'dispatched FSA has correct type property' | ||
); | ||
t.equal( | ||
action.payload.name, | ||
'RequestError', | ||
'dispatched FSA has correct payload property' | ||
); | ||
t.equal( | ||
action.meta, | ||
'someMeta', | ||
'dispatched FSA has correct meta property' | ||
); | ||
t.ok( | ||
action.error, | ||
'dispatched FSA has correct error property' | ||
); | ||
switch (action.type) { | ||
case 'REQUEST': | ||
if (!action.error) { | ||
t.pass('next handler called'); | ||
t.equal( | ||
action.type, | ||
'REQUEST', | ||
'dispatched non-error FSA has correct type property' | ||
); | ||
t.equal( | ||
action.payload, | ||
'ignoredPayload', | ||
'dispatched non-error FSA has correct payload property' | ||
); | ||
t.equal( | ||
action.meta, | ||
'someMeta', | ||
'dispatched non-error FSA has correct meta property' | ||
); | ||
t.notOk( | ||
action.error, | ||
'dispatched non-error FSA has correct error property' | ||
); | ||
break; | ||
} else { | ||
t.pass('next handler called'); | ||
t.equal( | ||
action.type, | ||
'REQUEST', | ||
'dispatched error FSA has correct type property' | ||
); | ||
t.equal( | ||
action.payload.name, | ||
'RequestError', | ||
'dispatched error FSA has correct payload property' | ||
); | ||
t.equal( | ||
action.meta, | ||
'someMeta', | ||
'dispatched error FSA has correct meta property' | ||
); | ||
t.ok( | ||
action.error, | ||
'dispatched error FSA has correct error property' | ||
); | ||
} | ||
} | ||
}; | ||
const actionHandler = nextHandler(doNext); | ||
t.plan(5); | ||
t.plan(10); | ||
actionHandler(anAction); | ||
@@ -1086,0 +1168,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
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
111319
22
3057
604