diff --git a/.changeset/tricky-poets-clap.md b/.changeset/tricky-poets-clap.md new file mode 100644 index 0000000000..0b7a33fcf0 --- /dev/null +++ b/.changeset/tricky-poets-clap.md @@ -0,0 +1,5 @@ +--- +'@urql/core': minor +--- + +Allow subscriptions to be handled by the `fetchExchange` when `fetchSubscriptions` is turned on. diff --git a/packages/core/src/client.ts b/packages/core/src/client.ts index 9790e5fc3b..98a47444df 100755 --- a/packages/core/src/client.ts +++ b/packages/core/src/client.ts @@ -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 diff --git a/packages/core/src/exchanges/fetch.ts b/packages/core/src/exchanges/fetch.ts index 39edbdeb04..07c914bb05 100755 --- a/packages/core/src/exchanges/fetch.ts +++ b/packages/core/src/exchanges/fetch.ts @@ -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); @@ -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 ); diff --git a/packages/core/src/internal/fetchOptions.ts b/packages/core/src/internal/fetchOptions.ts index cc698e81d2..7aa6513fef 100644 --- a/packages/core/src/internal/fetchOptions.ts +++ b/packages/core/src/internal/fetchOptions.ts @@ -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' diff --git a/packages/core/src/types.ts b/packages/core/src/types.ts index b41c7e9bf6..1614a9226e 100644 --- a/packages/core/src/types.ts +++ b/packages/core/src/types.ts @@ -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