first commit
This commit is contained in:
@@ -0,0 +1,52 @@
|
||||
# Gateway room operations
|
||||
|
||||
## Purpose
|
||||
|
||||
Free-function module containing every room-level mutation the gateway exposes — create / delete / join / leave / broadcast / unicast — extracted from `gateway.ts` so the daemon file stays under the 300-line cap. The functions consume a structurally-typed `RoomOpsDeps` and have no class dependency, which makes them straightforward to unit-test with hand-rolled fakes.
|
||||
|
||||
## Features
|
||||
|
||||
- `createRoom(deps, config)` — capacity check + idempotent registration; throws `ROOM_FULL` once the daemon hits `maxRooms`.
|
||||
- `deleteRoom(rooms, id)` — clears members, drops the entry, decrements the OTel rooms-active gauge.
|
||||
- `joinRoom(deps, roomId, clientId, idempotencyKey?)` — gates through rate-limit + authz, wraps the join in `IdempotencyGuard.execute`, fires the `presence:update`.
|
||||
- `leaveRoom(deps, roomId, clientId)` — symmetric leave + presence fire.
|
||||
- `broadcastToRoom(deps, roomId, senderId, payload, idempotencyKey?)` — gated + idempotent message dispatch returning `{message, recipients}`.
|
||||
- `unicast(deps, senderId, targetId, payload)` — gated unicast.
|
||||
|
||||
## Usage: Basic Example
|
||||
|
||||
```ts
|
||||
import { createRoom, joinRoom } from "@suaveplan/websocket-gateway";
|
||||
|
||||
createRoom(deps, { id: "general" });
|
||||
await joinRoom(deps, "general", "alice");
|
||||
```
|
||||
|
||||
## Usage: Advanced Example
|
||||
|
||||
```ts
|
||||
import { broadcastToRoom } from "@suaveplan/websocket-gateway";
|
||||
|
||||
const result = await broadcastToRoom(
|
||||
deps,
|
||||
"general",
|
||||
"alice",
|
||||
{ text: "hi" },
|
||||
"client-supplied-idempotency-key"
|
||||
);
|
||||
// result.recipients excludes alice; result.message is the dispatched envelope.
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
- `createRoom(deps, config): Room`
|
||||
- `deleteRoom(rooms, roomId): boolean`
|
||||
- `joinRoom(deps, roomId, clientId, idempotencyKey?): Promise<boolean>`
|
||||
- `leaveRoom(deps, roomId, clientId): Promise<boolean>`
|
||||
- `broadcastToRoom(deps, roomId, senderId, payload, idempotencyKey?): Promise<{message, recipients} | null>`
|
||||
- `unicast(deps, senderId, targetId, payload): Promise<Message | null>`
|
||||
- `RoomOpsDeps` — structurally-typed dependency bundle.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
The dependency bundle uses `Pick<>` / `Omit<>` per function so tests can construct minimal fakes — `createRoom` and `deleteRoom` deliberately avoid pulling in the gate/idempotency/presence-fire dependencies that aren't relevant to their pure path. Idempotency keys default to a deterministic `<verb>:<roomId>:<clientId>` shape; per-broadcast they incorporate the daemon's clock so two `broadcastToRoom` calls in the same logical operation are NOT deduplicated unless the caller passes an explicit key (the upstream behaviour).
|
||||
Reference in New Issue
Block a user