Skip to content

Fix for issue #22, updated Babel and ESLint to latest (test script was failing after cloning fresh repo) #43

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 8 commits into from
7 changes: 2 additions & 5 deletions .babelrc
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
{
"stage": 0,
"loose": "all",
"optional": [
"runtime"
]
"plugins": ["transform-runtime"],
"presets": ["es2015", "stage-0"]
}
1 change: 1 addition & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"experimentalObjectRestSpread": true,
"modules": true
},
"root": true,
"rules": {
"babel/arrow-parens": [2, "always"],
"no-underscore-dangle": 0,
Expand Down
113 changes: 60 additions & 53 deletions README.md

Large diffs are not rendered by default.

18 changes: 11 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "redux-api-middleware",
"version": "1.0.1",
"version": "2.0.0-beta.1",
"description": "Redux middleware for calling an API.",
"main": "lib/index.js",
"scripts": {
Expand All @@ -26,17 +26,21 @@
},
"license": "MIT",
"dependencies": {
"babel-runtime": "^5.8.25",
"babel-plugin-transform-runtime": "^6.5.2",
"babel-runtime": "^6.5.0",
"isomorphic-fetch": "^2.1.1",
"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",
"normalizr": "^1.1.0",
"rimraf": "^2.4.3",
Expand Down
10 changes: 0 additions & 10 deletions src/CALL_API.js

This file was deleted.

10 changes: 10 additions & 0 deletions src/RSAA.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/**
* String key that carries API call info interpreted by this Redux middleware.
*
* @constant {string}
* @access public
* @default
*/
const RSAA = '@@redux-api-middleware/RSAA';

export default RSAA;
6 changes: 3 additions & 3 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* @module redux-api-middleware
* @requires isomorphic-fetch
* @requires lodash.isplainobject
* @exports {symbol} CALL_API
* @exports {string} RSAA
* @exports {function} isRSAA
* @exports {function} validateRSAA
* @exports {function} isValidRSAA
Expand All @@ -29,14 +29,14 @@
* @returns undefined
*/

import CALL_API from './CALL_API';
import RSAA from './RSAA';
import { isRSAA, validateRSAA, isValidRSAA } from './validation';
import { InvalidRSAA, InternalError, RequestError, ApiError } from './errors';
import { getJSON } from './util';
import { apiMiddleware } from './middleware';

export {
CALL_API,
RSAA,
isRSAA,
validateRSAA,
isValidRSAA,
Expand Down
18 changes: 9 additions & 9 deletions src/middleware.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import fetch from 'isomorphic-fetch';
import isPlainObject from 'lodash.isplainobject';

import CALL_API from './CALL_API';
import RSAA from './RSAA';
import { isRSAA, validateRSAA } from './validation';
import { InvalidRSAA, RequestError, ApiError } from './errors' ;
import { getJSON, normalizeTypeDescriptors, actionWith } from './util';
Expand All @@ -14,15 +14,15 @@ import { getJSON, normalizeTypeDescriptors, actionWith } from './util';
*/
function apiMiddleware({ getState }) {
return (next) => async (action) => {
// Do not process actions without a [CALL_API] property
// Do not process actions without an [RSAA] property
if (!isRSAA(action)) {
return next(action);
}

// Try to dispatch an error request FSA for invalid RSAAs
const validationErrors = validateRSAA(action);
if (validationErrors.length) {
const callAPI = action[CALL_API];
const callAPI = action[RSAA];
if (callAPI.types && Array.isArray(callAPI.types)) {
let requestType = callAPI.types[0];
if (requestType && requestType.type) {
Expand All @@ -38,7 +38,7 @@ function apiMiddleware({ getState }) {
}

// Parse the validated RSAA action
const callAPI = action[CALL_API];
const callAPI = action[RSAA];
var { endpoint, headers } = callAPI;
const { method, body, credentials, bailout, types } = callAPI;
const [requestType, successType, failureType] = normalizeTypeDescriptors(types);
Expand All @@ -53,38 +53,38 @@ function apiMiddleware({ getState }) {
return next(await actionWith(
{
...requestType,
payload: new RequestError('[CALL_API].bailout function failed'),
payload: new RequestError('[RSAA].bailout function failed'),
error: true
},
[action, getState()]
));
}

// Process [CALL_API].endpoint function
// Process [RSAA].endpoint function
if (typeof endpoint === 'function') {
try {
endpoint = endpoint(getState());
} catch (e) {
return next(await actionWith(
{
...requestType,
payload: new RequestError('[CALL_API].endpoint function failed'),
payload: new RequestError('[RSAA].endpoint function failed'),
error: true
},
[action, getState()]
));
}
}

// Process [CALL_API].headers function
// Process [RSAA].headers function
if (typeof headers === 'function') {
try {
headers = headers(getState());
} catch (e) {
return next(await actionWith(
{
...requestType,
payload: new RequestError('[CALL_API].headers function failed'),
payload: new RequestError('[RSAA].headers function failed'),
error: true
},
[action, getState()]
Expand Down
2 changes: 1 addition & 1 deletion src/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ async function getJSON(res) {
*
* @function normalizeTypeDescriptors
* @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}
*/
function normalizeTypeDescriptors(types) {
Expand Down
38 changes: 19 additions & 19 deletions src/validation.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import CALL_API from './CALL_API';
import RSAA from './RSAA';
import isPlainObject from 'lodash.isplainobject';

/**
* 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?
*
* @function isRSAA
* @access public
* @param {object} action - The action to check
* @returns {boolean}
*/
function isRSAA(action) {
return isPlainObject(action) && action.hasOwnProperty(CALL_API);
return isPlainObject(action) && action.hasOwnProperty(RSAA);
}

/**
Expand Down Expand Up @@ -81,58 +81,58 @@ function validateRSAA(action) {
]

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

for (let key in action) {
if (key !== [CALL_API]) {
if (key !== RSAA) {
validationErrors.push(`Invalid root key: ${key}`);
}
}

const callAPI = action[CALL_API];
const callAPI = action[RSAA];
if (!isPlainObject(callAPI)) {
validationErrors.push('[CALL_API] property must be a plain JavaScript object');
validationErrors.push('[RSAA] property must be a plain JavaScript object');
}
for (let key in callAPI) {
if (!~validCallAPIKeys.indexOf(key)) {
validationErrors.push(`Invalid [CALL_API] key: ${key}`);
validationErrors.push(`Invalid [RSAA] key: ${key}`);
}
}

const { endpoint, method, headers, credentials, types, bailout } = callAPI;
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' && !isPlainObject(headers) && typeof headers !== 'function') {
validationErrors.push('[CALL_API].headers property must be undefined, a plain JavaScript object, or a 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 {
const [requestType, successType, failureType] = types;
if (typeof requestType !== 'string' && typeof requestType !== 'symbol' && !isValidTypeDescriptor(requestType)) {
Expand Down
Loading