Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

redux-api-middleware

Package Overview
Dependencies
Maintainers
1
Versions
42
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

redux-api-middleware - npm Package Compare versions

Comparing version 1.0.0-beta2 to 1.0.0-beta3

coverage.json

36

lib/errors.js

@@ -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;

22

lib/middleware.js

@@ -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 @@ });

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc