Skip to content

Commit

Permalink
feat(core): Allow fetch exchange to handle subscriptions (#3106)
Browse files Browse the repository at this point in the history
  • Loading branch information
kitten authored Mar 31, 2023
1 parent a28a58f commit 97c8be2
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 3 deletions.
5 changes: 5 additions & 0 deletions .changeset/tricky-poets-clap.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@urql/core': minor
---

Allow subscriptions to be handled by the `fetchExchange` when `fetchSubscriptions` is turned on.
10 changes: 10 additions & 0 deletions packages/core/src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,16 @@ export interface ClientOptions {
* @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
Expand Down
12 changes: 10 additions & 2 deletions packages/core/src/exchanges/fetch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,11 @@ export const fetchExchange: Exchange = ({ forward, dispatchDebug }) => {
const fetchResults$ = pipe(
ops$,
filter(operation => {
return operation.kind === 'query' || operation.kind === 'mutation';
return (
operation.kind !== 'teardown' &&
(operation.kind !== 'subscription' ||
!!operation.context.fetchSubscriptions)
);
}),
mergeMap(operation => {
const body = makeFetchBody(operation);
Expand Down Expand Up @@ -87,7 +91,11 @@ export const fetchExchange: Exchange = ({ forward, dispatchDebug }) => {
const forward$ = pipe(
ops$,
filter(operation => {
return operation.kind !== 'query' && operation.kind !== 'mutation';
return (
operation.kind === 'teardown' ||
(operation.kind === 'subscription' &&
!operation.context.fetchSubscriptions)
);
}),
forward
);
Expand Down
4 changes: 3 additions & 1 deletion packages/core/src/internal/fetchOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,9 @@ export const makeFetchOptions = (
): RequestInit => {
const headers: HeadersInit = {
accept:
'application/graphql-response+json, application/graphql+json, application/json, text/event-stream, multipart/mixed',
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'
Expand Down
10 changes: 10 additions & 0 deletions packages/core/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -473,6 +473,16 @@ export interface OperationContext {
* @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
Expand Down

0 comments on commit 97c8be2

Please sign in to comment.