Mirror: The highly customizable and versatile GraphQL client with which you add on features like normalized caching as you grow.

feat(core): Allow fetch exchange to handle subscriptions (#3106)

Changed files
+38 -3
.changeset
packages
core
src
+5
.changeset/tricky-poets-clap.md
···
···
+
---
+
'@urql/core': minor
+
---
+
+
Allow subscriptions to be handled by the `fetchExchange` when `fetchSubscriptions` is turned on.
+10
packages/core/src/client.ts
···
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API} for the Fetch API spec.
*/
fetch?: typeof fetch;
/** A list of `Exchange`s that will be used to create the `Client`'s execution pipeline.
*
* @remarks
···
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API} for the Fetch API spec.
*/
fetch?: typeof fetch;
+
/** Allows a subscription to be executed using a `fetch` API request.
+
*
+
* @remarks
+
* If your API supports the `text/event-stream` and/or `multipart/mixed` response protocol, and you use
+
* this protocol to handle subscriptions, then you may switch this flag to `true`.
+
*
+
* This means you won’t have to create a {@link subscriptionExchange} to handle subscriptions with an
+
* external transport, and will instead be able to use GraphQL over HTTP transports.
+
*/
+
fetchSubscriptions?: boolean;
/** A list of `Exchange`s that will be used to create the `Client`'s execution pipeline.
*
* @remarks
+10 -2
packages/core/src/exchanges/fetch.ts
···
const fetchResults$ = pipe(
ops$,
filter(operation => {
-
return operation.kind === 'query' || operation.kind === 'mutation';
}),
mergeMap(operation => {
const body = makeFetchBody(operation);
···
const forward$ = pipe(
ops$,
filter(operation => {
-
return operation.kind !== 'query' && operation.kind !== 'mutation';
}),
forward
);
···
const fetchResults$ = pipe(
ops$,
filter(operation => {
+
return (
+
operation.kind !== 'teardown' &&
+
(operation.kind !== 'subscription' ||
+
!!operation.context.fetchSubscriptions)
+
);
}),
mergeMap(operation => {
const body = makeFetchBody(operation);
···
const forward$ = pipe(
ops$,
filter(operation => {
+
return (
+
operation.kind === 'teardown' ||
+
(operation.kind === 'subscription' &&
+
!operation.context.fetchSubscriptions)
+
);
}),
forward
);
+3 -1
packages/core/src/internal/fetchOptions.ts
···
): RequestInit => {
const headers: HeadersInit = {
accept:
-
'application/graphql-response+json, application/graphql+json, application/json, text/event-stream, multipart/mixed',
};
const extraOptions =
(typeof operation.context.fetchOptions === 'function'
···
): RequestInit => {
const headers: HeadersInit = {
accept:
+
operation.kind === 'subscription'
+
? 'text/event-stream, multipart/mixed'
+
: 'application/graphql-response+json, application/graphql+json, application/json, text/event-stream, multipart/mixed',
};
const extraOptions =
(typeof operation.context.fetchOptions === 'function'
+10
packages/core/src/types.ts
···
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/fetch} for a description of this object.
*/
fetchOptions?: RequestInit | (() => RequestInit);
/** The request and caching strategy instructing cache exchanges how to treat cached results.
*
* @remarks
···
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/fetch} for a description of this object.
*/
fetchOptions?: RequestInit | (() => RequestInit);
+
/** Allows the `fetchExchange` to handle subscriptions.
+
*
+
* @remarks
+
* When set to `true`, subscriptions are allowed to be handled by the {@link fetchExchange} and will
+
* be sent using a `fetch` call as GraphQL over HTTP requests.
+
* This may be enabled on {@link ClientOptions.fetchSubscriptions} when your API supports the
+
* `text/event-stream` and `multipart/mixed` response protocols and is able to use them to
+
* respond with subscription results.
+
*/
+
fetchSubscriptions?: boolean;
/** The request and caching strategy instructing cache exchanges how to treat cached results.
*
* @remarks