Last active
May 24, 2022 15:45
-
-
Save rmosolgo/a4c098de02af63ec1cdd09a3573a216b to your computer and use it in GitHub Desktop.
urql subscription exchange from GraphQL-Ruby pusher subscriptions
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Client, defaultExchanges, subscriptionExchange } from 'urql' | |
import Pusher from "pusher" | |
const pusherClient = new Pusher("your-app-key", { cluster: "us2" }) | |
const forwardSubscriptionToPusher = (operation) => { | |
// urql will call `.subscribe` on the returned object: | |
// https://github.com/FormidableLabs/urql/blob/f89cfd06d9f14ae9cb3be10b21bd5cbd12ca275c/packages/core/src/exchanges/subscription.ts#L68-L73 | |
// https://github.com/FormidableLabs/urql/blob/f89cfd06d9f14ae9cb3be10b21bd5cbd12ca275c/packages/core/src/exchanges/subscription.ts#L82-L97 | |
return { | |
subscribe: ({next, error, complete}) => { | |
// Somehow forward the operation to be POSTed to the server, | |
// I don't see an option for passing this on to the `fetchExchange` | |
const fetchBody = JSON.stringify({ | |
query: operation.query, | |
variables: operation.variables, | |
}) | |
var pusherChannelName | |
// TODO: add whatever else you need to fetch | |
// a graphql response from the server | |
fetch("/graphql", { method: "POST", body: fetchBody }) | |
.then((result) => { | |
// Get the server-provided subscription ID | |
pusherChannelName = result.headers.get("X-Subscription-ID") | |
// Set up a subscription to Pusher, forwarding updates to | |
// the `next` function provided by urql | |
const pusherChannel = pusher.subscribe(subscriptionChannel) | |
pusherChannel.bind("update", (payload) => { | |
// Here's an update to this subscription, | |
// pass it on: | |
if (payload.result) { | |
next(payload.result) | |
} | |
// If the server signals that this is the end, | |
// then unsubscribe the client: | |
if (!payload.more) { | |
complete() | |
} | |
}) | |
// Continue processing the initial result for the subscription | |
return result.json() | |
}) | |
.then((jsonResult) => { | |
// forward the initial result to urql | |
next(jsonResult) | |
}) | |
// urql will call `.unsubscribe()` if it's returned here: | |
// https://github.com/FormidableLabs/urql/blob/f89cfd06d9f14ae9cb3be10b21bd5cbd12ca275c/packages/core/src/exchanges/subscription.ts#L102 | |
return { | |
unsubscribe: () => { | |
// When requested by urql, disconnect from this channel | |
pusherChannelName && pusherClient.unsubscribe(pusherChannelName) | |
} | |
} | |
} | |
} | |
} | |
const client = new Client({ | |
url: '/graphql', | |
exchanges: [ | |
...defaultExchanges, | |
subscriptionExchange({ | |
forwardSubscription: forwardSubscriptionToPusher | |
}), | |
], | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment