Skip to content

Commit

Permalink
Merge pull request #52 from jtribble/topic-issue-22
Browse files Browse the repository at this point in the history
[MODIFIED] Fix for issue #22, updated Babel and ESLint to latest (test script was failing after cloning fresh repo)
  • Loading branch information
barrystaes committed Mar 8, 2016
2 parents b31e9af + 47d1d32 commit 9512ba0
Show file tree
Hide file tree
Showing 11 changed files with 224 additions and 222 deletions.
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
104 changes: 52 additions & 52 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,17 +31,17 @@ Aught to be stable but still in development while we iron out bugs.

This middleware receives [*Redux Standard API-calling Actions*](#redux-standard-api-calling-actions) (RSAAs) and dispatches [*Flux Standard Actions*](#flux-standard-actions) (FSAs) to the next middleware.

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.

### A simple example

The following is a minimal RSAA action:

```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',
method: 'GET',
types: ['REQUEST', 'SUCCESS', 'FAILURE']
Expand Down Expand Up @@ -122,35 +122,35 @@ const store = configureStore(initialState);

### Defining the API call

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`

The URL endpoint for the API call.

It is usually a string, be it a plain old one or an ES2015 template string. It may also be a function taking the state of your Redux store as its argument, and returning such a string.

#### `[CALL_API].method`
#### `[RSAA].method`

The HTTP method for the API call.

It 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 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`

The HTTP headers for the API call.

It is usually an object, with the keys specifying the header names and the values containing their content. For example, you can let the server know your call contains a JSON-encoded string body in the following way.

```js
{
[CALL_API]: {
[RSAA]: {
...
headers: { 'Content-Type': 'application/json' }
...
Expand All @@ -160,7 +160,7 @@ It is usually an object, with the keys specifying the header names and the value

It may also be a function taking the state of your Redux store as its argument, and returning an object of headers as above.

#### `[CALL_API].credentials`
#### `[RSAA].credentials`

Whether or not to send cookies with the API call.

Expand All @@ -174,48 +174,48 @@ It must be one of the following strings:

In some cases, the data you would like to fetch from the server may already be cached in you Redux store. Or you may decide that the current user does not have the necessary permissions to make some request.

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;
- `error: true`.

`redux-api-middleware` will perform no further operations. In particular, no API call will be made, and the incoming RSAA will die here.

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;
- `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}` ``;
- `error: true`.
### Customizing the dispatched FSAs
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.
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.
Expand All @@ -234,7 +234,7 @@ For example, if you want your *request* FSA to have the URL endpoint of the API
```js
// Input RSAA
{
[CALL_API]: {
[RSAA]: {
endpoint: 'http://www.example.com/api/users',
method: 'GET',
types: [
Expand All @@ -260,7 +260,7 @@ If you do not need access to the action itself or the state of your Redux store,
```js
// Input RSAA
{
[CALL_API]: {
[RSAA]: {
endpoint: 'http://www.example.com/api/users',
method: 'GET',
types: [
Expand Down Expand Up @@ -299,7 +299,7 @@ const userSchema = new Schema('users');

// Input RSAA
{
[CALL_API]: {
[RSAA]: {
endpoint: 'http://www.example.com/api/users',
method: 'GET',
types: [
Expand Down Expand Up @@ -360,7 +360,7 @@ For example, if you want the status code and status message of a unsuccessful AP
```js
{
[CALL_API]: {
[RSAA]: {
endpoint: 'http://www.example.com/api/users/1',
method: 'GET',
types: [
Expand Down Expand Up @@ -399,17 +399,17 @@ By default, *failure* FSAs will not contain a `meta` property, while their `payl
The following objects are exported by `redux-api-middleware`.
#### `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.
#### `apiMiddleware`
The Redux middleware itself.
#### `isRSAA(action)`
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.
#### `validateRSAA(action)`
Expand Down Expand Up @@ -511,65 +511,65 @@ The optional `meta` property MAY be any type of value. It is intended for any ex
### Redux Standard API-calling Actions
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.
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
- be a plain JavaScript Object,
- have an `endpoint` property,
- have a `method` property,
- have a `types` property.
The `[CALL_API]` property MAY
The `[RSAA]` property MAY
- have a `body` property,
- have a `headers` property,
- have a `credentials` property,
- have a `bailout` 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.
#### Type descriptors
Expand Down
16 changes: 10 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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
Loading

0 comments on commit 9512ba0

Please sign in to comment.