a6de43edc1
- pnpm workspace: shared/server/client packages - Server: Fastify+ws, chess.js, FSM (touch-move + hierarchy), per-player view filter, zod validation, rate limiting, grace-window disconnect handling - Client: Svelte 5 + Vite, click-to-move board, moderator panel, promotion/draw dialogs - Shared: protocol types, ModeratorText enum, geometricMoves helper (provably zero opponent-info leak) - 43 tests pass (21 shared, 22 server incl. 4 real-WS integration) - Deploy: CT 690 on node-241 (192.168.0.245), systemd-managed, Caddy block for chess.sethpc.xyz - Live at https://chess.sethpc.xyz Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
63 lines
1.6 KiB
TypeScript
63 lines
1.6 KiB
TypeScript
import type {
|
|
BoardView, Color, GameId, GameStatus, Mode, PlayerToken,
|
|
PromotionType, Square, EndReason,
|
|
} from './types.js';
|
|
import type { Announcement } from './moderator.js';
|
|
|
|
export type ClientMessage =
|
|
| { type: 'hello'; gameId: GameId; token?: PlayerToken; joinAs?: Color | 'auto' }
|
|
| { type: 'commit'; from: Square; to?: Square; promotion?: PromotionType }
|
|
| { type: 'resign' }
|
|
| { type: 'offer-draw' }
|
|
| { type: 'respond-draw'; accept: boolean }
|
|
| { type: 'pong' };
|
|
|
|
export type ErrorCode =
|
|
| 'game_not_found'
|
|
| 'slot_taken'
|
|
| 'spectators_disabled'
|
|
| 'not_your_turn'
|
|
| 'malformed'
|
|
| 'promotion_required'
|
|
| 'must_move_touched_piece'
|
|
| 'rate_limited'
|
|
| 'invalid_token';
|
|
|
|
export type ServerMessage =
|
|
| {
|
|
type: 'joined';
|
|
you: Color | 'spectator-rejected';
|
|
token: PlayerToken;
|
|
view: BoardView;
|
|
announcements: Announcement[];
|
|
gameStatus: GameStatus;
|
|
mode: Mode;
|
|
highlightingEnabled: boolean;
|
|
opponentConnected: boolean;
|
|
}
|
|
| {
|
|
type: 'update';
|
|
view: BoardView;
|
|
newAnnouncements: Announcement[];
|
|
gameStatus: GameStatus;
|
|
touchedPiece?: Square;
|
|
drawOffer?: { from: Color } | null;
|
|
endReason?: EndReason;
|
|
winner?: Color | null;
|
|
}
|
|
| { type: 'peer-status'; color: Color; connected: boolean; graceUntil?: number }
|
|
| { type: 'error'; code: ErrorCode; message: string }
|
|
| { type: 'ping' };
|
|
|
|
export interface CreateGameRequest {
|
|
mode: Mode;
|
|
side: Color | 'random';
|
|
highlightingEnabled: boolean;
|
|
}
|
|
|
|
export interface CreateGameResponse {
|
|
gameId: GameId;
|
|
creatorToken: PlayerToken;
|
|
joinUrl: string;
|
|
}
|