WebSocket · In depth

connectedClients / ConnectedClient

Route-owned connected players with checked identity, bounded room membership, deduplicated presence and private server-page updates. Reuses RoomRegistry; no second socket map or browser dispatcher is required.

Explain it like I’m five

The simple mental model

Each player gets a checked name badge and a private screen. Redweb tracks who is connected and updates their screens; your game still decides what each person may do and see.

When it fits

When should I use it?

Use it with socket-bound TSX pages to remove manual membership maps, identity rechecks, presence loops and fan-out code. Ordinary raw socket routes need not adopt it.

A practical API pattern

Follow the example

This pattern explains the named API. Application classes, credentials, and assets may need to be supplied; use a complete recipe for a runnable starting point.

Read this article as Markdown

ts
import { connectedClients } from 'redweb'

// Supply your authenticated account lookup, game service, page and contract.
const players = connectedClients({
  identity: context => account(context.request),
  page: () => GamePage,
  project: (player, room, online) => ({
    game: games.resume(room, player.identity).snapshot(player.identity),
    online,
  }),
})
const match = players.bind(contract)
const Join = match.handler('join', (player, { room }) =>
  player.join(room, () => games.join(room, player.identity)))

// Register connections: players and protocol: match.protocol on MatchRoute.
// Attach GamePage with @page('/', { socket: MatchRoute }).
// Its TSX form uses rw-submit={Join}.
  1. 1

    Create a fresh group inside the application factory and register it with one SocketRoute.

  2. 2

    Bind typed handlers and use their classes in TSX controls; connect the page to that route.

  3. 3

    After successful commands and membership changes, Redweb projects each player’s permitted state and discards obsolete results.

Configuration

Choices you can make

  • identity: rechecks the admitted principal against current credentials
  • page: lazy reference to the attached page class
  • project: side-effect-free per-player page state; online identities are deduplicated
  • reject / errorState: classify deliberately public errors and map them to page fields
  • raw: optional update/reject adapters for non-HTML clients
  • authorizationTimeoutMs / projectionTimeoutMs: bounded asynchronous work
Surface area

Methods and members

players.bind(contract)

Creates typed handlers whose callback receives a ConnectedClient; successful commands refresh its rooms.

players.get(socket)

Returns the checked route-owned facade for page connection lifecycle hooks.

players.refresh(room)

Projects external domain changes to that room’s currently authorized connections.

player.identity / page / rooms / room

Admitted identity, private page, membership snapshot, and exactly-one-room convenience accessor.

player.join(room, commit?) / leave(room)

Checks capacity and authorization before a synchronous domain commit; failure removes newly added membership, not arbitrary domain side effects.