Skip to content

WebSocket transport ​

The default wire: a full-duplex WebSocket. Lowest latency, broadest support, and the closest match to a classic realtime connection. Provided by @super-line/transport-websocket.

bash
pnpm add @super-line/core @super-line/transport-websocket

Server ​

webSocketServerTransport attaches to an http.Server — compose it with Express/Fastify/Hono, or a bare http.createServer().

ts
import http from 'node:http'
import { createSuperLineServer } from '@super-line/server'
import { webSocketServerTransport } from '@super-line/transport-websocket'

const server = http.createServer()
const srv = createSuperLineServer(contract, {
  transports: [webSocketServerTransport({ server })],
  authenticate: (h) => ({ role: h.query.role, ctx: verify(h.query.token) }),
})
server.listen(3000)

Options:

OptionDefaultNotes
server—the http.Server to attach to (required)
pathanyonly handle upgrades for this pathname; others pass through
backpressureoff{ maxBufferedBytes, onExceed: 'close' | 'drop' } — guard against slow consumers (the byte-buffer threshold is WS-specific)
inspectoroffaccept Control Center inspector clients on the superline.inspector.v1 subprotocol — see Control Center

path, backpressure, and inspector are WebSocket-transport concerns, so they live on the transport, not on the server.

Client ​

ts
import { createSuperLineClient } from '@super-line/client'
import { webSocketClientTransport } from '@super-line/transport-websocket'

const client = createSuperLineClient(contract, {
  transport: webSocketClientTransport({ url: 'ws://localhost:3000' }),
  role: 'user',
  params: { token }, // carried on the URL query → readable as h.query.token in authenticate
})

In a browser (and Node 22+), WebSocket is a global — nothing to configure. On older Node, pass an implementation:

ts
import WebSocket from 'ws'
webSocketClientTransport({ url, WebSocket })

Behavior notes ​

  • An authenticate that throws SuperLineError('UNAUTHORIZED') gets the upgrade completed and closed 4401, so the client can tell a refused credential from a dead host and stops retrying it. Any other throw becomes a 401 at the HTTP upgrade with no socket opened, which the client sees as a drop and retries. See Reconnection & delivery.
  • Heartbeat is app-level ping/pong frames the core manages — not the WebSocket protocol ping — so it's identical across every transport.
  • params (and role) ride the URL query string and surface in authenticate as h.query.

Next: HTTP — SSE & long-poll · back to Choose a transport.

Released under the MIT License.