Usage

defineWSHandler

The all-in-one utility to manage reactive WebSocket connections from server-side.

The defineWSHandler will be the main utility to manage WebSocket connections server-side. It handles automatically the subscription of topics defined in the runtime configuration while also proving a hooking system to trigger messages globally from other part of the application server-side.

Please first read the upstream Nitro documentation on defineWebSocketHandler to understand the basic usage.

Example

/server/routes/_ws.ts
import * as v from 'valibot'

export default defineWSHandler({
  async open(peer) {
    // Update peer with 'chat' data from storage
    const chat = await useStorage('ws').getItem('chat')
    if (chat)
      peer.send(JSON.stringify({
        topic: 'chat',
        payload: chat,
      }), { compress: true })

    // Update everyone's session metadata
    const payload = JSON.stringify({ topic: 'session', payload: { users: peer.peers.size } })
    peer.send(payload, { compress: true })
    peer.publish('session', payload, { compress: true })
  },

  async message(peer, message) {
    // Validate the incoming chat message
    const parsedMessage = await wsValidateMessage( // built-in validation util
      v.object({
        type: v.literal('publish'),
        topic: v.literal('chat'),
        payload: v.object({ text: v.string() }),
      }),
      message,
    )

    // Update chat data in storage
    const mem = useStorage('ws')
    const { topic, payload } = parsedMessage
    const _chat = await mem.getItem<Array<{ user: string, text: string }>>('chat') || []
    const newChat = [..._chat, { ...payload, user: peer.id }]
    await mem.setItem(topic, newChat)

    // Broadcast the updated chat to everyone
    peer.send(JSON.stringify({ topic, payload: newChat }), { compress: true })
    peer.publish(topic, JSON.stringify({ topic, payload: newChat }), { compress: true })
  },

  close(peer) {
    // Update everyone's session metadata
    peer.publish(
      'session',
      JSON.stringify({
        topic: 'session',
        payload: {
          users: peer.peers.size,
        },
      }),
      { compress: true },
    )
  },
})

Parsing messages

A small wsParseMessage utility is provided to parse JSON content from incoming messages. This uses destr under the hood to parse the message and not throw an error if the message is not a valid JSON string.

This is also used under the hood by validation utilities.

Authentication

You can easily validate user's sessions with modules like nuxt-auth-utils as described in the documentation.

Please refer to the reactive-ws demo for a complete example.