Subscriptions

Listen for real-time updates from your server using GraphQL Subscriptions.

SubscriptionExample.svelte
<script lang="ts">
    import { graphql } from '$houdini'

    // this information should usually come from a fragment
    export let itemID: string

    // will start listening onMount (browser only)
    const updates = graphql(`
        subscription ItemUpdate($id: ID!) {
            itemUpdate(id: $id) {
                item {
                    id
                    completed
                    text
                }
            }
        }
    `)


    $: updates.listen({ id: itemID })
</script>

latest value: {$updates.itemUpdate.item.text}
SubscriptionExample.svelte
<script>
    import { graphql } from '$houdini'
    
    // this information should usually come from a fragment
    /* @type { string } */
    export let itemID
    
    // will start listening onMount (browser only)
    const updates = graphql(`
        subscription ItemUpdate($id: ID!) {
            itemUpdate(id: $id) {
                item {
                    id
                    completed
                    text
                }
            }
        }
    `)
    
    $: updates.listen({ id: itemID })
</script>

latest value: {$updates.itemUpdate.item.text}

Subscriptions can be defined like any other document and are triggered using the subscription store’s listen method:

List Operations

Subscription bodies can contain all of the list operations described in this document.

Configuring the client

Houdini can work with any websocket client as long as you can provide an object that satisfies the SubscriptionHandler interface as the second argument to the HoudiniClient’s constructor. Keep in mind that WebSocket connections only exist between the browser and your API, therefor you must remember to pass null when configuring your environment on the rendering server.

Using graphql-ws

If your API supports the graphql-ws protocol, you can create a client and pass it directly:

src/client.ts
import { createClient } from 'graphql-ws'
import { browser } from '$app/environment'

let socketClient = browser
    ? new createClient({
            url: 'ws://api.url'
      })
    : null

export default new HoudiniClient(requestHandler, socketClient)
src/client.js
import { createClient } from 'graphql-ws'
import { browser } from '$app/environment'

let socketClient = browser
    ? new createClient({
          url: 'ws://api.url',
      })
    : null

export default new HoudiniClient(requestHandler, socketClient)

Using subscriptions-transport-ws

If you are using the deprecated subscriptions-transport-ws library and associated protocol, you will have to slightly modify the above block:

src/client.ts
import { SubscriptionClient } from 'subscriptions-transport-ws'
import { browser } from '$app/environment'

let socketClient = null
if (browser) {
    // instantiate the transport client
    const client = new SubscriptionClient('ws://api.url', {
        reconnect: true,
    })

    // wrap the client in something houdini can use
    socketClient = {
        subscribe(payload, handlers) {
            // send the request
            const { unsubscribe } = client.request(payload).subscribe(handlers)

            // return the function to unsubscribe
            return unsubscribe
        },
    }
}

export default new HoudiniClient(requestHandler, socketClient)
src/client.js
import { SubscriptionClient } from 'subscriptions-transport-ws'
import { browser } from '$app/environment'

let socketClient = null
if (browser) {
    // instantiate the transport client
    const client = new SubscriptionClient('ws://api.url', {
        reconnect: true,
    })

    // wrap the client in something houdini can use
    socketClient = {
        subscribe(payload, handlers) {
            // send the request
            const { unsubscribe } = client.request(payload).subscribe(handlers)

            // return the function to unsubscribe
            return unsubscribe
        },
    }
}

export default new HoudiniClient(requestHandler, socketClient)

Server-Side Events

If your server supports the latest Server-Side events, you can use them to power your subscriptions:

src/client.ts
import { SubscriptionClient } from 'subscriptions-transport-ws'
import { browser } from '$app/environment'

let socketClient = null
if (browser) {
    socketClient = {
        subscribe(payload, handlers) {
            const url = new URL('/api/graplhql', location.href)
            url.searchParams.append('query', payload.query)
            url.searchParams.append('variables', JSON.stringify(payload.variables))

            const eventSource = new EventSource(url)

            eventSource.addEventListener('message', (ev) => handlers.next(JSON.parse(ev.data)))

            return () => eventSource.close()
        },
    }
}

export default new HoudiniClient(requestHandler, socketClient)
src/client.js
import { SubscriptionClient } from 'subscriptions-transport-ws'
import { browser } from '$app/environment'

let socketClient = null
if (browser) {
    socketClient = {
        subscribe(payload, handlers) {
            const url = new URL('/api/graplhql', location.href)
            url.searchParams.append('query', payload.query)
            url.searchParams.append('variables', JSON.stringify(payload.variables))

            const eventSource = new EventSource(url)

            eventSource.addEventListener('message', (ev) => handlers.next(JSON.parse(ev.data)))

            return () => eventSource.close()
        },
    }
}

export default new HoudiniClient(requestHandler, socketClient)