DEV Community

joehua87
joehua87

Posted on

Simple way to use Abinsthe Subscription in urql

Benefits

  • Without install @absinthe/socket which contains some legacy package; also save 16kb gzip
import { subscriptionExchange } from '@urql/core'
import { Channel, Socket } from 'phoenix'
import { make, pipe, toObservable } from 'wonka'

import { getWsEndpoint } from '~/env'

const wsEndpoint = getWsEndpoint()
const socket = new Socket(`${wsEndpoint}/socket`, {})

socket.connect()
const absintheChannel = socket.channel('__absinthe__:control')
absintheChannel.join()

export const absintheExchange = subscriptionExchange({
  forwardSubscription({ query, variables }) {
    let subscriptionChannel: Channel

    const source = make((observer) => {
      const { next } = observer

      absintheChannel.push('doc', { query, variables }).receive('ok', (v) => {
        const subscriptionId = v.subscriptionId

        if (subscriptionId) {
          subscriptionChannel = socket.channel(subscriptionId)
          subscriptionChannel.on('subscription:data', (value) => {
            next(value.result)
          })
        }
      })

      return () => {
        subscriptionChannel?.leave()
      }
    })

    return pipe(source, toObservable)
  },
})
Enter fullscreen mode Exit fullscreen mode

Then

const endpoint = getEndpoint()

export const client = createClient({
  url: `${endpoint}/graphql`,
  exchanges: [
    dedupExchange,
    fetchExchange,
    absintheExchange,
  ],
})

Enter fullscreen mode Exit fullscreen mode

Discussion (0)