first commit

This commit is contained in:
2026-05-29 08:20:56 +01:00
commit 949299f58d
6368 changed files with 527176 additions and 0 deletions

View File

@@ -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).