feat(P5B.T2): GamePayload + games wrappers + winner-detect helpers + tests

Adds conversation_games table type + game_make_move RPC to db-types, GamePayload variant and parseMessagePayload branch to shared/attachments, games.ts with createGame/getGame/makeGameMove wrappers plus pure tttWinningLine/c4WinningCells/c4DropRow/isBoardFull helpers, 11 tests covering all winner helpers, and re-export from chat/index.ts.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
byGalax
2026-05-16 21:47:36 +02:00
parent e1423dba32
commit 256a613134
5 changed files with 304 additions and 1 deletions
+20 -1
View File
@@ -88,12 +88,20 @@ export interface WatchTogetherPayload {
session_id: string;
}
export interface GamePayload {
v: 1;
type: 'game';
game_id: string;
game_type: 'ttt' | 'c4';
}
export type MessagePayload =
| TextMessagePayload
| CallEventPayload
| PollPayload
| WhiteboardPayload
| WatchTogetherPayload;
| WatchTogetherPayload
| GamePayload;
export type ParsedMessagePayload =
| {
@@ -120,6 +128,11 @@ export type ParsedMessagePayload =
| {
kind: 'watch_together';
sessionId: string;
}
| {
kind: 'game';
gameId: string;
gameType: 'ttt' | 'c4';
};
export function serializeMessagePayload(payload: MessagePayload): string {
@@ -190,6 +203,12 @@ export function parseMessagePayload(raw: string | null): ParsedMessagePayload {
: '';
return { kind: 'watch_together', sessionId: id };
}
if (obj.type === 'game') {
const p = obj as Partial<GamePayload>;
const id = typeof p.game_id === 'string' && p.game_id.length > 0 ? p.game_id : '';
const t = p.game_type === 'ttt' || p.game_type === 'c4' ? p.game_type : 'ttt';
return { kind: 'game', gameId: id, gameType: t };
}
const t = obj as TextMessagePayload;
return {
kind: 'text',