apollo-link-http
Advanced tools
Comparing version 0.7.0 to 0.8.0
# Change log | ||
### vNEXT | ||
- throw error on empty ExectionResult (missing) | ||
- support setting credentials, headers, and fetcherOptions in the setup of the link | ||
- removed sending of context to the server and allowed opt-in of sending extensions |
@@ -25,3 +25,12 @@ (function (global, factory) { | ||
}; | ||
var parseAndCheckResponse = function (response) { | ||
var __rest = (undefined && undefined.__rest) || function (s, e) { | ||
var t = {}; | ||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) | ||
t[p] = s[p]; | ||
if (s != null && typeof Object.getOwnPropertySymbols === "function") | ||
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) if (e.indexOf(p[i]) < 0) | ||
t[p[i]] = s[p[i]]; | ||
return t; | ||
}; | ||
var parseAndCheckResponse = function (request) { return function (response) { | ||
return response | ||
@@ -32,2 +41,5 @@ .json() | ||
throw new Error("Response not successful: Received status code " + response.status); | ||
if (!result.hasOwnProperty('data') && !result.hasOwnProperty('errors')) { | ||
throw new Error("Server response was missing for query '" + request.operationName + "'."); | ||
} | ||
return result; | ||
@@ -42,3 +54,3 @@ }) | ||
}); | ||
}; | ||
}; }; | ||
var checkFetcher = function (fetcher) { | ||
@@ -68,3 +80,4 @@ if (fetcher.use && | ||
var createHttpLink = function (_a) { | ||
var _b = _a === void 0 ? {} : _a, uri = _b.uri, fetcher = _b.fetch, includeExtensions = _b.includeExtensions; | ||
if (_a === void 0) { _a = {}; } | ||
var uri = _a.uri, fetcher = _a.fetch, includeExtensions = _a.includeExtensions, requestOptions = __rest(_a, ["uri", "fetch", "includeExtensions"]); | ||
warnIfNoFetch(fetcher); | ||
@@ -97,8 +110,15 @@ if (fetcher) | ||
} | ||
var fetchOptions = __assign({ method: 'POST' }, fetcherOptions, { headers: { | ||
var options = fetcherOptions; | ||
if (requestOptions.fetcherOptions) | ||
options = __assign({}, requestOptions.fetcherOptions, options); | ||
var fetchOptions = __assign({ method: 'POST' }, options, { headers: { | ||
accept: '*/*', | ||
'content-type': 'application/json', | ||
}, body: serializedBody }); | ||
if (requestOptions.credentials) | ||
fetchOptions.credentials = requestOptions.credentials; | ||
if (credentials) | ||
fetchOptions.credentials = credentials; | ||
if (requestOptions.headers) | ||
fetchOptions.headers = __assign({}, fetchOptions.headers, requestOptions.headers); | ||
if (headers) | ||
@@ -110,3 +130,3 @@ fetchOptions.headers = __assign({}, fetchOptions.headers, headers); | ||
fetcher(uri, fetchOptions) | ||
.then(parseAndCheckResponse) | ||
.then(parseAndCheckResponse(operation)) | ||
.then(function (result) { | ||
@@ -113,0 +133,0 @@ observer.next(result); |
@@ -0,1 +1,2 @@ | ||
/// <reference types="zen-observable" /> | ||
import { ApolloLink, Observable, RequestHandler } from 'apollo-link'; | ||
@@ -7,4 +8,7 @@ import { ExecutionResult } from 'graphql'; | ||
includeExtensions?: boolean; | ||
credentials?: string; | ||
headers?: any; | ||
fetcherOptions?: any; | ||
} | ||
export declare const createHttpLink: ({uri, fetch: fetcher, includeExtensions}?: FetchOptions) => ApolloLink; | ||
export declare const createHttpLink: ({uri, fetch: fetcher, includeExtensions, ...requestOptions}?: FetchOptions) => ApolloLink; | ||
export declare class HttpLink extends ApolloLink { | ||
@@ -11,0 +15,0 @@ requester: RequestHandler; |
@@ -19,5 +19,14 @@ var __extends = (this && this.__extends) || (function () { | ||
}; | ||
var __rest = (this && this.__rest) || function (s, e) { | ||
var t = {}; | ||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) | ||
t[p] = s[p]; | ||
if (s != null && typeof Object.getOwnPropertySymbols === "function") | ||
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) if (e.indexOf(p[i]) < 0) | ||
t[p[i]] = s[p[i]]; | ||
return t; | ||
}; | ||
import { ApolloLink, Observable } from 'apollo-link'; | ||
import { print } from 'graphql/language/printer'; | ||
var parseAndCheckResponse = function (response) { | ||
var parseAndCheckResponse = function (request) { return function (response) { | ||
return response | ||
@@ -28,2 +37,5 @@ .json() | ||
throw new Error("Response not successful: Received status code " + response.status); | ||
if (!result.hasOwnProperty('data') && !result.hasOwnProperty('errors')) { | ||
throw new Error("Server response was missing for query '" + request.operationName + "'."); | ||
} | ||
return result; | ||
@@ -38,3 +50,3 @@ }) | ||
}); | ||
}; | ||
}; }; | ||
var checkFetcher = function (fetcher) { | ||
@@ -64,3 +76,4 @@ if (fetcher.use && | ||
export var createHttpLink = function (_a) { | ||
var _b = _a === void 0 ? {} : _a, uri = _b.uri, fetcher = _b.fetch, includeExtensions = _b.includeExtensions; | ||
if (_a === void 0) { _a = {}; } | ||
var uri = _a.uri, fetcher = _a.fetch, includeExtensions = _a.includeExtensions, requestOptions = __rest(_a, ["uri", "fetch", "includeExtensions"]); | ||
warnIfNoFetch(fetcher); | ||
@@ -93,8 +106,15 @@ if (fetcher) | ||
} | ||
var fetchOptions = __assign({ method: 'POST' }, fetcherOptions, { headers: { | ||
var options = fetcherOptions; | ||
if (requestOptions.fetcherOptions) | ||
options = __assign({}, requestOptions.fetcherOptions, options); | ||
var fetchOptions = __assign({ method: 'POST' }, options, { headers: { | ||
accept: '*/*', | ||
'content-type': 'application/json', | ||
}, body: serializedBody }); | ||
if (requestOptions.credentials) | ||
fetchOptions.credentials = requestOptions.credentials; | ||
if (credentials) | ||
fetchOptions.credentials = credentials; | ||
if (requestOptions.headers) | ||
fetchOptions.headers = __assign({}, fetchOptions.headers, requestOptions.headers); | ||
if (headers) | ||
@@ -106,3 +126,3 @@ fetchOptions.headers = __assign({}, fetchOptions.headers, headers); | ||
fetcher(uri, fetchOptions) | ||
.then(parseAndCheckResponse) | ||
.then(parseAndCheckResponse(operation)) | ||
.then(function (result) { | ||
@@ -109,0 +129,0 @@ observer.next(result); |
{ | ||
"name": "apollo-link-http", | ||
"version": "0.7.0", | ||
"version": "0.8.0", | ||
"description": "HTTP transport layer for GraphQL", | ||
@@ -42,16 +42,14 @@ "author": "Evans Hauser <evanshauser@gmail.com>", | ||
}, | ||
"dependencies": { | ||
"apollo-fetch": "^0.6.0", | ||
"peerDependencies": { | ||
"apollo-link": "^0.8.0", | ||
"graphql": "^0.11.0" | ||
}, | ||
"peerDependencies": { | ||
"apollo-link": "^0.7.0" | ||
}, | ||
"devDependencies": { | ||
"@types/graphql": "0.11.4", | ||
"@types/jest": "21.1.1", | ||
"apollo-link": "^0.7.0", | ||
"@types/graphql": "0.11.5", | ||
"@types/jest": "21.1.2", | ||
"apollo-fetch": "^0.6.0", | ||
"apollo-link": "^0.8.0", | ||
"browserify": "14.4.0", | ||
"fetch-mock": "5.12.2", | ||
"graphql": "0.11.6", | ||
"fetch-mock": "5.13.1", | ||
"graphql": "0.11.7", | ||
"graphql-tag": "2.4.2", | ||
@@ -61,3 +59,3 @@ "jest": "21.2.1", | ||
"rollup": "0.45.2", | ||
"ts-jest": "21.0.1", | ||
"ts-jest": "21.1.2", | ||
"tslint": "5.7.0", | ||
@@ -64,0 +62,0 @@ "typescript": "2.5.1", |
@@ -26,3 +26,3 @@ # HTTP Link | ||
## Options | ||
HTTP Link takes an object with three options on it to customize the behavior of the link. If your server supports it, the HTTP link can also send over metadata about the request in the extensions field. To enable this, pass `includeExtensions` as true. | ||
HTTP Link takes an object with some options on it to customize the behavior of the link. If your server supports it, the HTTP link can also send over metadata about the request in the extensions field. To enable this, pass `includeExtensions` as true. | ||
@@ -34,6 +34,9 @@ |name|value|default|required| | ||
|fetch|fetch|global fetch|false| | ||
|headers|Headers (or object)|{}|false| | ||
|credentials|string|none|false| | ||
|fetchOptions|Fetch Options (object)|none|false| | ||
## Context | ||
The HTTP Link uses the `headers` field on the context to allow passing headers to the HTTP request. It also supports the `credentials` field for defining credentials policy for fetch and `fetchOptions` to allow generic fetch overrides (i.e. method: "GET"). | ||
The HTTP Link uses the `headers` field on the context to allow passing headers to the HTTP request. It also supports the `credentials` field for defining credentials policy for fetch and `fetchOptions` to allow generic fetch overrides (i.e. method: "GET"). These options will override the same key if passed when creating the the link. | ||
@@ -69,3 +72,3 @@ |name|value|default|required| | ||
### Upgrading from `apollo-fetch` / `apollo-client` | ||
If you previously used either `apollo-fetch` or `apollo-client`, you will need to change the way `use` and `useAfter` are implemented in your app. They can both be implemented in a link like so: | ||
If you previously used either `apollo-fetch` or `apollo-client`, you will need to change the way `use` and `useAfter` are implemented in your app. Both can be implemented by writing a custom link. It's important to note that regardless of whether you're adding middleware or afterware, your HTTP link will always be last in the chain since it's a terminating link. | ||
@@ -123,3 +126,3 @@ #### Middleware | ||
applyAfterware({ response }, next) { | ||
if (response.status === 401) { | ||
if (response.statusCode === 401) { | ||
logout(); | ||
@@ -126,0 +129,0 @@ } |
@@ -25,3 +25,3 @@ import { Observable, ApolloLink, execute } from 'apollo-link'; | ||
describe('HttpLink', () => { | ||
const data = { hello: 'world', method: 'POST' }; | ||
const data = { data: { hello: 'world' } }; | ||
const mockError = { throws: new TypeError('mock me') }; | ||
@@ -235,2 +235,37 @@ | ||
}); | ||
it('adds headers to the request from the setup', done => { | ||
const variables = { params: 'stub' }; | ||
const link = createHttpLink({ | ||
uri: 'data', | ||
headers: { authorization: '1234' }, | ||
}); | ||
execute(link, { query: sampleQuery, variables }).subscribe(result => { | ||
const headers = fetchMock.lastCall()[1].headers; | ||
expect(headers.authorization).toBe('1234'); | ||
expect(headers['content-type']).toBe('application/json'); | ||
expect(headers.accept).toBe('*/*'); | ||
done(); | ||
}); | ||
}); | ||
it('prioritizes context headers over setup headers', done => { | ||
const variables = { params: 'stub' }; | ||
const middleware = new ApolloLink((operation, forward) => { | ||
operation.setContext({ | ||
headers: { authorization: '1234' }, | ||
}); | ||
return forward(operation); | ||
}); | ||
const link = middleware.concat( | ||
createHttpLink({ uri: 'data', headers: { authorization: 'no user' } }), | ||
); | ||
execute(link, { query: sampleQuery, variables }).subscribe(result => { | ||
const headers = fetchMock.lastCall()[1].headers; | ||
expect(headers.authorization).toBe('1234'); | ||
expect(headers['content-type']).toBe('application/json'); | ||
expect(headers.accept).toBe('*/*'); | ||
done(); | ||
}); | ||
}); | ||
it('adds headers to the request from the context on an operation', done => { | ||
@@ -271,2 +306,43 @@ const variables = { params: 'stub' }; | ||
}); | ||
it('adds creds to the request from the setup', done => { | ||
const variables = { params: 'stub' }; | ||
const link = createHttpLink({ uri: 'data', credentials: 'same-team-yo' }); | ||
execute(link, { query: sampleQuery, variables }).subscribe(result => { | ||
const creds = fetchMock.lastCall()[1].credentials; | ||
expect(creds).toBe('same-team-yo'); | ||
done(); | ||
}); | ||
}); | ||
it('prioritizes creds from the context over the setup', done => { | ||
const variables = { params: 'stub' }; | ||
const middleware = new ApolloLink((operation, forward) => { | ||
operation.setContext({ | ||
credentials: 'same-team-yo', | ||
}); | ||
return forward(operation); | ||
}); | ||
const link = middleware.concat( | ||
createHttpLink({ uri: 'data', credentials: 'error' }), | ||
); | ||
execute(link, { query: sampleQuery, variables }).subscribe(result => { | ||
const creds = fetchMock.lastCall()[1].credentials; | ||
expect(creds).toBe('same-team-yo'); | ||
done(); | ||
}); | ||
}); | ||
it('adds fetcherOptions to the request from the setup', done => { | ||
const variables = { params: 'stub' }; | ||
const link = createHttpLink({ | ||
uri: 'data', | ||
fetcherOptions: { signal: 'foo' }, | ||
}); | ||
execute(link, { query: sampleQuery, variables }).subscribe(result => { | ||
const signal = fetchMock.lastCall()[1].signal; | ||
expect(signal).toBe('foo'); | ||
done(); | ||
}); | ||
}); | ||
it('adds fetcherOptions to the request from the context', done => { | ||
@@ -290,2 +366,22 @@ const variables = { params: 'stub' }; | ||
}); | ||
it('prioritizes context over setup', done => { | ||
const variables = { params: 'stub' }; | ||
const middleware = new ApolloLink((operation, forward) => { | ||
operation.setContext({ | ||
fetcherOptions: { | ||
signal: 'foo', | ||
}, | ||
}); | ||
return forward(operation); | ||
}); | ||
const link = middleware.concat( | ||
createHttpLink({ uri: 'data', fetcherOptions: { signal: 'bar' } }), | ||
); | ||
execute(link, { query: sampleQuery, variables }).subscribe(result => { | ||
const signal = fetchMock.lastCall()[1].signal; | ||
expect(signal).toBe('foo'); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
@@ -346,2 +442,19 @@ | ||
}); | ||
it('throws an error if empty response from the server ', done => { | ||
fetch.mockReturnValueOnce(Promise.resolve({ json })); | ||
json.mockReturnValueOnce(Promise.resolve({ body: 'boo' })); | ||
const link = createHttpLink({ uri: 'data', fetch }); | ||
execute(link, { query: sampleQuery }).subscribe( | ||
result => { | ||
done.fail('error should have been thrown from the network'); | ||
}, | ||
e => { | ||
expect(e.parseError.message).toMatch( | ||
/Server response was missing for query 'SampleQuery'/, | ||
); | ||
done(); | ||
}, | ||
); | ||
}); | ||
it('makes it easy to do stuff on a 401', done => { | ||
@@ -416,2 +529,4 @@ fetch.mockReturnValueOnce(Promise.resolve({ status: 401, json })); | ||
fetch.mockReturnValueOnce(Promise.resolve({ json })); | ||
json.mockReturnValueOnce(Promise.resolve({ data: { hello: 'world' } })); | ||
const link = createHttpLink({ uri: 'data', fetch }); | ||
@@ -418,0 +533,0 @@ |
@@ -17,3 +17,3 @@ import { ApolloLink, Observable, RequestHandler } from 'apollo-link'; | ||
const parseAndCheckResponse = (response: Response) => { | ||
const parseAndCheckResponse = request => (response: Response) => { | ||
return response | ||
@@ -26,2 +26,7 @@ .json() | ||
); | ||
if (!result.hasOwnProperty('data') && !result.hasOwnProperty('errors')) { | ||
throw new Error( | ||
`Server response was missing for query '${request.operationName}'.`, | ||
); | ||
} | ||
return result; | ||
@@ -88,5 +93,13 @@ }) | ||
includeExtensions?: boolean; | ||
credentials?: string; | ||
headers?: any; | ||
fetcherOptions?: any; | ||
} | ||
export const createHttpLink = ( | ||
{ uri, fetch: fetcher, includeExtensions }: FetchOptions = {}, | ||
{ | ||
uri, | ||
fetch: fetcher, | ||
includeExtensions, | ||
...requestOptions, | ||
}: FetchOptions = {}, | ||
) => { | ||
@@ -125,5 +138,8 @@ // dev warnings to ensure fetch is present | ||
let options = fetcherOptions; | ||
if (requestOptions.fetcherOptions) | ||
options = { ...requestOptions.fetcherOptions, ...options }; | ||
const fetchOptions = { | ||
method: 'POST', | ||
...fetcherOptions, | ||
...options, | ||
headers: { | ||
@@ -137,3 +153,11 @@ // headers are case insensitive (https://stackoverflow.com/a/5259004) | ||
if (requestOptions.credentials) | ||
fetchOptions.credentials = requestOptions.credentials; | ||
if (credentials) fetchOptions.credentials = credentials; | ||
if (requestOptions.headers) | ||
fetchOptions.headers = { | ||
...fetchOptions.headers, | ||
...requestOptions.headers, | ||
}; | ||
if (headers) | ||
@@ -146,3 +170,3 @@ fetchOptions.headers = { ...fetchOptions.headers, ...headers }; | ||
fetcher(uri, fetchOptions) | ||
.then(parseAndCheckResponse) | ||
.then(parseAndCheckResponse(operation)) | ||
.then(result => { | ||
@@ -149,0 +173,0 @@ // we have data and can send it to back up the link chain |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
63109
2
1024
186
4
15
+ Addedapollo-link@0.8.0(transitive)
+ Addedzen-observable@0.6.1(transitive)
- Removedapollo-fetch@^0.6.0
- Removedgraphql@^0.11.0
- Removedapollo-fetch@0.6.0(transitive)
- Removedapollo-link@0.7.0(transitive)
- Removedencoding@0.1.13(transitive)
- Removediconv-lite@0.6.3(transitive)
- Removedis-stream@1.1.0(transitive)
- Removedisomorphic-fetch@2.2.1(transitive)
- Removednode-fetch@1.7.3(transitive)
- Removedsafer-buffer@2.1.2(transitive)
- Removedwhatwg-fetch@3.6.20(transitive)
- Removedzen-observable-ts@0.5.0(transitive)