Skip to content

Instantly share code, notes, and snippets.

@rmosolgo
Last active May 24, 2022 15:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rmosolgo/a4c098de02af63ec1cdd09a3573a216b to your computer and use it in GitHub Desktop.
Save rmosolgo/a4c098de02af63ec1cdd09a3573a216b to your computer and use it in GitHub Desktop.
urql subscription exchange from GraphQL-Ruby pusher subscriptions
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