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.
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 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.
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.
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
Create a fresh group inside the application factory and register it with one SocketRoute.
- 2
Bind typed handlers and use their classes in TSX controls; connect the page to that route.
- 3
After successful commands and membership changes, Redweb projects each player’s permitted state and discards obsolete results.
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
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.