Liveflux

Adapters

The transport adapters Liveflux ships — WebSocket, Phoenix Channels, Server-Sent Events, and Socket.IO — plus how to write your own.

An adapter is the only protocol-specific piece of Liveflux. The core, the fold strategies, and the React binding never change — you pick the adapter that matches how your backend pushes, hand it to a LivefluxClient, and everything else is identical. Every adapter implements the same StreamAdapter contract, so swapping transports is a one-line change.

PackageTransportConstruct with
@liveflux/wsAny plain WebSocket (any backend, any language)ws(url)
@liveflux/phoenixPhoenix Channels (v2 wire protocol)phoenix(url)
@liveflux/sseServer-Sent Events (EventSource)sse(url)
@liveflux/socketioSocket.IO (your own client socket)socketio(socket)
@liveflux/graphql-wsGraphQL subscriptions (graphql-transport-ws)graphqlWs(url)

All are zero-dependency and reconnect-safe: the core owns the reconnect policy, and each adapter replays its active subscription set on every reopen.

WebSocket — @liveflux/ws

The generic adapter for any backend that exposes a plain WebSocket. It speaks a small JSON control protocol (subscribe / unsubscribe / heartbeat outbound; { channel, event, payload } inbound), both sides overridable via encode / decode.

import { LivefluxClient } from '@liveflux/core';
import { ws } from '@liveflux/ws';

const client = new LivefluxClient({ adapter: ws('wss://example.com/socket') });
client.connect();

Phoenix Channels — @liveflux/phoenix

For Elixir Phoenix backends. Hand-rolled v2 framing (zero-dep), joins a topic per channel, and re-joins on reconnect.

import { LivefluxClient } from '@liveflux/core';
import { phoenix } from '@liveflux/phoenix';

const client = new LivefluxClient({ adapter: phoenix('wss://example.com/socket/websocket') });
client.connect();

Server-Sent Events — @liveflux/sse

For backends that stream over SSE. The downstream stream is a standard EventSource; because SSE is one-way, subscribe / unsubscribe / resume go upstream over a separate control channel — by default an HTTP POST alongside the stream (override with control, or supply your own transport function).

import { LivefluxClient } from '@liveflux/core';
import { sse } from '@liveflux/sse';

const client = new LivefluxClient({
  adapter: sse('https://example.com/events', { control: 'https://example.com/events/control' }),
});
client.connect();

Cursor resume is supported: resume(subId, cursor) sends a gap-recovery frame, and the default decoder threads the SSE lastEventId through as the cursor. See the package README for the full options (withCredentials, injectable EventSource / fetch, encode / decode, maxMessageBytes).

Socket.IO — @liveflux/socketio

Wraps a Socket.IO client socket you already created — your transport upgrade, rooms, and auth stay yours. socket.io-client is an optional peer you provide; the adapter never imports it, so nothing extra ships. Let the core own reconnect by disabling Socket.IO's own retry.

import { io } from 'socket.io-client';
import { LivefluxClient } from '@liveflux/core';
import { socketio } from '@liveflux/socketio';

const socket = io('https://example.com', { reconnection: false });

const client = new LivefluxClient({ adapter: socketio(socket) });
client.connect();

By default it listens for a message event ({ channel, event, payload }) and emits subscribe / unsubscribe / resume; each event name and the decoder are overridable.

GraphQL subscriptions — @liveflux/graphql-ws

For GraphQL backends over the graphql-transport-ws protocol. It speaks the protocol directly over a WebSocket — no GraphQL client to bundle, zero dependencies. A liveflux channel maps to a subscription document (override with query), and each next result is routed back to its channel.

import { LivefluxClient } from '@liveflux/core';
import { graphqlWs } from '@liveflux/graphql-ws';

const client = new LivefluxClient({
  adapter: graphqlWs('wss://example.com/graphql', {
    query: (channel, params) => ({ query: channel, variables: params }),
    connectionParams: () => ({ authToken: getToken() }),
  }),
});
client.connect();

It handles the connection_initconnection_ack handshake, replays active subscriptions after each ack, answers ping with pong, and surfaces subscription errors. See the package README for query / decode / connectionParams details.

Write your own

Anything push-capable can be an adapter — implement StreamAdapter (connect / disconnect / subscribe / unsubscribe, optionally resume / heartbeat) and prove it with the shared conformance suite from @liveflux/adapter-tests. See Concepts for the contract.

On this page