adonisjs / transmit

A Server-Sent-Event module for AdonisJS
MIT License
72 stars 6 forks source link

AdonisJS Transmit

A native Server-Sent-Event (SSE) module for AdonisJS.


[![typescript-image]][typescript-url] [![gh-workflow-image]][gh-workflow-url] [![npm-image]][npm-url] [![npm-download-image]][npm-download-url] [![license-image]][license-url]

Usage | Checkout AdonisJS



AdonisJS Transmit is a native Server-Sent-Event (SSE) module for AdonisJS. It provides a simple API to send events to the client. It also supports Redis as a Transport Layer for broadcasting events to multiple servers or instances.

Here are a few things you should know before using this module.

👉 Unidirectional Communication: The data transmission occurs only from server to client, not the other way around.
👉 Textual Data Only: SSE only supports the transmission of textual data, binary data cannot be sent.
👉 HTTP Protocol: The underlying protocol used is the regular HTTP, not any special or proprietary protocol.

Table of Contents

Installation

Install the package from the npm registry as follows:

node ace add @adonisjs/transmit

Usage

The module exposes a transmit instance, which can be used to send events to the client.

import transmit from '@adonisjs/transmit/services/main'

// Anywhere in your code
transmit.broadcast('channelName', { username: 'lanz' })

Channels

Channels are a way to group events. For example, you can have a channel for users and another for posts. The client can subscribe to one or more channels to receive events.

Channel Names

Channels names must be a string and must not contain any special characters except /. The following are valid channel names.

transmit.broadcast('users', { username: 'lanz' })
transmit.broadcast('users/1', { username: 'lanz' })
transmit.broadcast('users/1/posts', { username: 'lanz' })

Channel Authorization

You can mark a channel as private and then authorize the client to subscribe to it. The authorization is done using a callback function.

// start/transmit.ts

import type { HttpContext } from '@adonisjs/core/http'

transmit.authorize<{ id: string }>('users/:id', (ctx: HttpContext, { id }) => {
  return ctx.auth.user?.id === +id
})

[!NOTE] Do not forget to add your start/transmit.ts file inside the preloads array of the adonisrc.ts file.

When a client tries to subscribe to a private channel, the callback function is invoked with the channel params and the HTTP context. The callback function must return a boolean value to allow or disallow the subscription.

Syncing

Transmit supports syncing events across multiple servers or instances using a transport layer. You can enable syncing by changing the configuration and referencing your driver (only Redis is available as of now).

// config/transmit.ts
import env from '#start/env'
import { defineConfig } from '@adonisjs/transmit'
import { redis } from '@adonisjs/transmit/transports'

export default defineConfig({
  transport: {
    driver: redis({
      host: env.get('REDIS_HOST'),
      port: env.get('REDIS_PORT'),
      password: env.get('REDIS_PASSWORD'),
    })
  }
})

[!NOTE] Ensure to have ioredis installed when using the redis driver.

Ping

Transmit supports pinging the client to keep the connection alive. You can enable pinging by changing the configuration.

// config/transmit.ts
import { defineConfig } from '@adonisjs/transmit'
import { redis } from '@adonisjs/transmit/transports'

export default defineConfig({
  pingInterval: '1m',
})

Events

Transmit uses Emittery to emit any lifecycle events. You can listen for events using the on method.

transmit.on('connect', ({ uid }) => {
  console.log(`Connected: ${uid}`)
})

transmit.on('disconnect', ({ uid }) => {
  console.log(`Disconnected: ${uid}`)
})

transmit.on('broadcast', ({ channel }) => {
  console.log(`Broadcasted to channel ${channel}`)
})

transmit.on('subscribe', ({ uid, channel }) => {
  console.log(`Subscribed ${uid} to ${channel}`)
})

transmit.on('unsubscribe', ({ uid, channel }) => {
  console.log(`Unsubscribed ${uid} from ${channel}`)
})