WS message router: dispatch by type #35

Open
opened 2026-04-19 07:23:37 +00:00 by forgejo-lila · 0 comments
Owner

Context

WebSocket messages are JSON with a type field. The router parses, validates, and dispatches to handlers.

What to do

Build a message router with Zod validation.

Files to create

  • apps/api/src/ws/router.ts — parse JSON, validate with Zod discriminated union, dispatch.
  • apps/api/src/ws/handlers/ — directory for handler functions.

Implementation outline

import { wsMessageSchema } from '@lila/shared';

export function handleMessage(ws: WebSocket, data: string, user: User) {
  const parsed = wsMessageSchema.safeParse(JSON.parse(data));
  if (!parsed.success) {
    ws.send(JSON.stringify({ type: 'error', message: 'Invalid message' }));
    return;
  }
  switch (parsed.data.type) {
    case 'lobby:join': handleLobbyJoin(ws, parsed.data, user); break;
    case 'lobby:leave': handleLobbyLeave(ws, parsed.data, user); break;
    // ...
  }
}

Acceptance criteria

  • Invalid JSON or unknown types return error to client
  • Each message type validated against its Zod schema
  • Handlers receive typed, validated data
  • Easily extensible (new type = new schema + handler)
  • Malformed messages never crash the server

Notes

Zod schemas for WS messages belong in packages/shared (see separate issue). Pattern: z.discriminatedUnion('type', [...]). Reference: packages/shared/src/schemas/game.ts.

## Context WebSocket messages are JSON with a `type` field. The router parses, validates, and dispatches to handlers. ## What to do Build a message router with Zod validation. ## Files to create - `apps/api/src/ws/router.ts` — parse JSON, validate with Zod discriminated union, dispatch. - `apps/api/src/ws/handlers/` — directory for handler functions. ## Implementation outline ```typescript import { wsMessageSchema } from '@lila/shared'; export function handleMessage(ws: WebSocket, data: string, user: User) { const parsed = wsMessageSchema.safeParse(JSON.parse(data)); if (!parsed.success) { ws.send(JSON.stringify({ type: 'error', message: 'Invalid message' })); return; } switch (parsed.data.type) { case 'lobby:join': handleLobbyJoin(ws, parsed.data, user); break; case 'lobby:leave': handleLobbyLeave(ws, parsed.data, user); break; // ... } } ``` ## Acceptance criteria - Invalid JSON or unknown types return error to client - Each message type validated against its Zod schema - Handlers receive typed, validated data - Easily extensible (new type = new schema + handler) - Malformed messages never crash the server ## Notes Zod schemas for WS messages belong in `packages/shared` (see separate issue). Pattern: `z.discriminatedUnion('type', [...])`. Reference: `packages/shared/src/schemas/game.ts`.
forgejo-lila added the
multiplayer
label 2026-04-19 07:23:37 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: forgejo-lila/lila#35
No description provided.