@anycable/turbo-stream
TypeScript icon, indicating that this package has built-in type declarations

0.5.0 • Public • Published

npm version

AnyCable Turbo Streams

This package provides AnyCable client integration for Turbo Streams.

The default @hotwired/turbo-rails package doesn't allow you to replace the default Action Cable client with a custom consumer implementation.

🎥 You can learn more about the motivation behind the custom Turbo Streams integration from the AnyCasts episode "Using anycable-client to auto-refresh tokens"

NOTE: Make sure you're not importing @hotwired/turbo-rails or use a custom tag name: Hotwire's package registers the custom element implicitly and it's not possible to override it.

Usage

Assuming that you have a cable instance defined somewhere, to activate Turbo Streams elements you need to add the following code:

import { start } from "@anycable/turbo-stream"
// This is your cable instance
import cable from "cable"
// Explicitly activate stream source elements
start(cable)

This approach let you control when (and how) to start streaming from the <turbo-cable-stream-source> HTML elements.

No server-side changes required. We support all standard functionality: passing a custom channel class and subscription params.

Compatibility with @hotwired/turbo-rails

Our integration aims to be API compatible with the official packages, which means, HTML elements and their attributes are recognized and interpreted the same way as with @hotwired/turbo-rails.

One subtle but important difference is that @anycable/turbo-stream does not activate stream elements added to temporary Turbo cache pages. This way we avoid unnecessary subscriptions/unsubscriptions and potential race conditions.

Advanced configuration

Attaching X-Socket-ID header to Turbo requests

You can automatically add a header to all Turbo requests with the current socket session ID. This can be used to perform broadcasts to others (see Rails integration docs):

import { start } from "@anycable/turbo-stream"
import cable from "cable"

start(cable, { requestSocketIDHeader: true })

// You can also specify a custom header name
// start(cable, { requestSocketIDHeader: 'X-My-Socket-ID' })

Custom channel classes

You define a custom JS channel class for Turbo Streams subscriptions:

import { TurboChannel } from "@anycable/turbo-stream"

class CustomTurboChannel extends TurboChannel {
  // Constructor receives the current HTML element (turbo-cable-stream-source),
  // a channel name (Turbo::StreamsChannel) by default and subscription params
  constructor(element, channelName, params) {
    // You can override the server-side channel name
    super(element, 'MyTurboChannel', params)
    // Additional state configuration goes here
    this.totalActions = 0
  }

  // You can override receive function to intercept actions
  receive(message) {
    this.totalActions++

    // Ignore every second message
    if (this.totalActions % 2 === 0) return

    // Fallback to the default behaviour,
    // which sends the action to Turbo
    super.receive(message)
  }
}

Another example is a channel which logs all the actions before executing them:

class LogChannel extends TurboChannel {
  receive(message) {
    console.log("TURBO ACTION", message)
    super.receive(message)
  }
}

start(cable, {channelClass: LogChannel})

Custom tags

You can use a custom tag name for Turbo Streams source elements. One use case is to use different JS channels for different tags:

// Assuming you have some special channel class
import { TurboPresenceChannel } from './channel.js'
import { start } from "@anycable/turbo-stream"

import cable from "cable"

// Default behaviour
start(cable)

// Custom behaviour
start(cable, { tagName: 'turbo-presence-source', channelClass: TurboPresenceChannel })

NOTE: You need to create a custom Rails helper to render custom elements. For example:

def turbo_presence_stream_from(*streamables, **attributes)
  attributes[:channel] = attributes[:channel]&.to_s || "Turbo::StreamsChannel"
  attributes[:"signed-stream-name"] = Turbo::StreamsChannel.signed_stream_name(streamables)

  tag.turbo_presence_source(**attributes)
end

Package Sidebar

Install

npm i @anycable/turbo-stream

Homepage

anycable.io/

Weekly Downloads

741

Version

0.5.0

License

MIT

Unpacked Size

11.3 kB

Total Files

10

Last publish

Collaborators

  • hellsquirrel
  • palkan