Skip to content

Commit 827ea30

Browse files
jamesonenodkz
authored andcommitted
feat: Add noThrow option to NetworkLayer advanced options (thanks @jamesone)
* Add noThrow option * Fix tests + commit fixes * Make noThrow option optional in Flow * Rm it.only
1 parent 3c130b1 commit 827ea30

File tree

8 files changed

+50
-18
lines changed

8 files changed

+50
-18
lines changed

README.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,21 @@ Middlewares
8888
- `prefix` - prefix message (default: `[RELAY-NETWORK] GRAPHQL SERVER ERROR:`)
8989
- **deferMiddleware** - _experimental_ Right now `deferMiddleware()` just set `defer` as supported option for Relay. So this middleware allow to community play with `defer()` in cases, which was [described by @wincent](https://github.com/facebook/relay/issues/288#issuecomment-199510058).
9090

91+
Advanced options (2nd argument after middlewares)
92+
===========
93+
94+
RelayNetworkLayer may accept additional options:
95+
96+
```js
97+
const middlewares = []; // array of middlewares
98+
const options = {}; // optional advanced options
99+
const network = new RelayNetworkLayer(middlewares, options);
100+
```
101+
102+
Available options:
103+
104+
- **noThrow** - EXPERIMENTAL (May be deprecated in the future) set true to not throw when an error response is given by the server, and to instead handle errors in your app code.
105+
91106
### Example of injecting NetworkLayer with middlewares on the **client side**.
92107
```js
93108
import Relay from 'react-relay';

src/__tests__/fetchWithMiddleware.test.js

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ describe('fetchWithMiddleware', () => {
3535
it('should make a successfull request without middlewares', async () => {
3636
fetchMock.post('/graphql', { id: 1, data: { user: 123 } });
3737

38-
const data = await fetchWithMiddleware(createMockReq(1), []);
38+
const { data } = await fetchWithMiddleware(createMockReq(1), [], {});
3939
expect(data).toEqual({ user: 123 });
4040
});
4141

@@ -53,10 +53,14 @@ describe('fetchWithMiddleware', () => {
5353

5454
fetchMock.post('/graphql', { id: 1, data: { num: 1 } });
5555

56-
const data = await fetchWithMiddleware(createMockReq(1), [
57-
numPlus5,
58-
numMultiply10, // should be first, when changing response
59-
]);
56+
const { data } = await fetchWithMiddleware(
57+
createMockReq(1),
58+
[
59+
numPlus5,
60+
numMultiply10, // should be first, when changing response
61+
],
62+
{}
63+
);
6064
expect(data).toEqual({ num: 15 });
6165
});
6266
});

src/definition.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ export type RRNLResponseObject = {
5959
statusText: string,
6060
headers: { [name: string]: string },
6161
url: string,
62-
payload: ?GraphQLResponse,
62+
payload?: GraphQLResponse,
6363
};
6464

6565
export type RelayClassicRequest = {
@@ -71,3 +71,7 @@ export type RelayClassicRequest = {
7171
getVariables: () => Object,
7272
getDebugName: () => string,
7373
};
74+
75+
export type RRNLOptions = {
76+
noThrow?: boolean,
77+
};

src/fetchWithMiddleware.js

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import type {
77
RRNLRequestObject,
88
RRNLResponseObject,
99
MiddlewareNextFn,
10+
RRNLOptions,
1011
} from './definition';
1112

1213
function runFetch(req: RRNLRequestObject): Promise<RRNLResponseObject> {
@@ -40,16 +41,27 @@ function runFetch(req: RRNLRequestObject): Promise<RRNLResponseObject> {
4041

4142
export default function fetchWithMiddleware(
4243
req: RRNLRequestObject,
43-
middlewares: Middleware[]
44+
middlewares: Middleware[],
45+
options: RRNLOptions
4446
): Promise<any> {
4547
const wrappedFetch: MiddlewareNextFn = compose(...middlewares)(runFetch);
4648

4749
return wrappedFetch(req).then(res => {
4850
const { payload } = res;
49-
if (!payload || payload.hasOwnProperty('errors') || !payload.hasOwnProperty('data')) {
51+
const { noThrow = false } = options;
52+
const hasErrors =
53+
!payload || payload.hasOwnProperty('errors') || !payload.hasOwnProperty('data');
54+
55+
/** Only throw the Error if noThrow === false */
56+
if (!noThrow && hasErrors) {
5057
throw createRequestError(req, res);
5158
}
52-
return payload.data;
59+
60+
/** Return payload.data as well as the errors (if they exist) */
61+
return {
62+
data: (payload && payload.data) || null,
63+
errors: hasErrors ? createRequestError(req, res) : null,
64+
};
5365
});
5466
}
5567

src/middleware/__tests__/auth.test.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ describe('Middleware / auth', () => {
4141
it('should work with mutation', async () => {
4242
const req1 = mockReq();
4343
await rnl.sendMutation(req1);
44-
4544
expect(req1.payload).toEqual({ response: 'PAYLOAD' });
4645
const reqs = fetchMock.calls('/graphql');
4746
expect(reqs).toHaveLength(1);

src/relayMutation.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ export default function mutation(
2626
}
2727

2828
return fetchWithMiddleware(req)
29-
.then(data => relayRequest.resolve({ response: data }))
29+
.then(({ data }) => relayRequest.resolve({ response: data }))
3030
.catch(err => {
3131
relayRequest.reject(err);
3232
throw err;

src/relayNetworkLayer.js

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,7 @@
33
import queries from './relayQueries';
44
import mutation from './relayMutation';
55
import fetchWithMiddleware from './fetchWithMiddleware';
6-
import type { Middleware, RelayClassicRequest } from './definition';
7-
8-
export type RRNLOptions = {};
6+
import type { Middleware, RelayClassicRequest, RRNLOptions } from './definition';
97

108
export default class RelayNetworkLayer {
119
_options: RRNLOptions;
@@ -16,7 +14,7 @@ export default class RelayNetworkLayer {
1614
sendMutation: Function;
1715

1816
constructor(middlewares: Middleware[] | Middleware, options?: RRNLOptions) {
19-
this._options = options || {};
17+
this._options = typeof options === 'object' ? options : {};
2018
this._middlewares = Array.isArray(middlewares) ? middlewares : [middlewares];
2119
this._supportedOptions = [];
2220

@@ -40,10 +38,10 @@ export default class RelayNetworkLayer {
4038
}
4139

4240
sendQueries(requests: RelayClassicRequest[]): Promise<any> {
43-
return queries(requests, req => fetchWithMiddleware(req, this._middlewares));
41+
return queries(requests, req => fetchWithMiddleware(req, this._middlewares, this._options));
4442
}
4543

4644
sendMutation(request: RelayClassicRequest): Promise<any> {
47-
return mutation(request, req => fetchWithMiddleware(req, this._middlewares));
45+
return mutation(request, req => fetchWithMiddleware(req, this._middlewares, this._options));
4846
}
4947
}

src/relayQueries.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ export default function queries(
2626
};
2727

2828
return fetchWithMiddleware(req)
29-
.then(data => relayRequest.resolve({ response: data }))
29+
.then(({ data }) => relayRequest.resolve({ response: data }))
3030
.catch(err => {
3131
relayRequest.reject(err);
3232
throw err;

0 commit comments

Comments
 (0)