"use server"; /** * Canonical server-action surface for the poker minigame. * The signatures below are the pinned contract shared with the UI layer. * All table logic lives in the registry (src/lib/minigames/poker/tables.ts). */ import config from "@payload-config"; import { getPayload } from "payload"; import type { Card, PokerActionKind, PrivatePlayerView } from "@/lib/minigames/poker/types"; import { isSuperuser } from "@/utils/access-control/hasPermission"; import { adjustStack, applyPlayerAction, createTable, forceExpireTable, getSnapshotFor, joinTableWithBuyIn, leaveTableWithBuyIn, spectateTable, listSummaries, renameTable, setBoardQueue, setHoleQueue, startGameWithBuyIn, type PokerSnapshot, type PokerTableSummary, } from "@/lib/minigames/poker/tables"; export type { PokerSnapshot, PokerTableSummary }; export type PokerCardInput = Card; interface ActionResult { success: boolean; error?: string; data?: T; } async function authenticate() { const payloadConfig = await config; const payload = await getPayload({ config: payloadConfig }); const { headers } = await import("next/headers"); const hdrs = await headers(); const { user } = await payload.auth({ headers: hdrs, canSetHeaders: false, }); if (!user) { throw new Error("Unauthorized"); } return { payload, user }; } function toError(error: unknown): { success: false; error: string } { const message = error instanceof Error ? error.message : "Unknown error"; if (message === "Unauthorized") { return { success: false, error: "You must be logged in." }; } return { success: false, error: message }; } interface UserLike { id: number; displayName?: string | null; username?: string | null; } function userName(user: UserLike): string { if (typeof user.displayName === "string" && user.displayName) return user.displayName; if (typeof user.username === "string" && user.username) return user.username; return `Player ${user.id}`; } export async function createPokerTable(): Promise> { try { const { user } = await authenticate(); const tableId = createTable(Number(user.id), userName(user)); return { success: true, data: { tableId } }; } catch (error) { return toError(error); } } export async function listPokerTables(): Promise> { try { await authenticate(); return { success: true, data: listSummaries() }; } catch (error) { return toError(error); } } export async function forceExpirePokerTable(tableId: string): Promise> { try { const { payload, user } = await authenticate(); const allowed = await isSuperuser(payload, user); if (!allowed) { return { success: false, error: "Only administrators can force-end tables." }; } forceExpireTable(tableId, payload); return { success: true }; } catch (error) { return toError(error); } } export async function joinPokerTable(tableId: string): Promise> { try { const { user } = await authenticate(); const snapshot = await joinTableWithBuyIn(tableId, Number(user.id), userName(user)); return { success: true, data: snapshot }; } catch (error) { return toError(error); } } export async function spectatePokerTable(tableId: string): Promise> { try { const { user } = await authenticate(); const snapshot = spectateTable(tableId, Number(user.id)); return { success: true, data: snapshot }; } catch (error) { return toError(error); } } export async function setPokerBoardQueue( tableId: string, cards: PokerCardInput[], ): Promise> { try { const { payload, user } = await authenticate(); const allowed = await isSuperuser(payload, user); if (!allowed) { return { success: false, error: "Only administrators can use dev controls." }; } const snapshot = setBoardQueue(tableId, Number(user.id), cards); return { success: true, data: snapshot }; } catch (error) { return toError(error); } } export async function setPokerHoleQueue( tableId: string, seatId: number, cards: PokerCardInput[], ): Promise> { try { const { payload, user } = await authenticate(); const allowed = await isSuperuser(payload, user); if (!allowed) { return { success: false, error: "Only administrators can use dev controls." }; } const snapshot = setHoleQueue(tableId, Number(user.id), seatId, cards); return { success: true, data: snapshot }; } catch (error) { return toError(error); } } export async function adjustPokerStack( tableId: string, seatId: number, delta: number, ): Promise> { try { const { payload, user } = await authenticate(); const allowed = await isSuperuser(payload, user); if (!allowed) { return { success: false, error: "Only administrators can use dev controls." }; } const snapshot = adjustStack(tableId, Number(user.id), seatId, delta); return { success: true, data: snapshot }; } catch (error) { return toError(error); } } export async function leavePokerTable(tableId: string): Promise> { try { const { user } = await authenticate(); await leaveTableWithBuyIn(tableId, Number(user.id)); return { success: true }; } catch (error) { return toError(error); } } export async function startPokerGame(tableId: string): Promise> { try { const { user } = await authenticate(); const snapshot = await startGameWithBuyIn(tableId, Number(user.id)); return { success: true, data: snapshot }; } catch (error) { return toError(error); } } export async function renamePokerTable( tableId: string, rawName: string, ): Promise> { try { const { user } = await authenticate(); const snapshot = renameTable(tableId, Number(user.id), rawName); return { success: true, data: snapshot }; } catch (error) { return toError(error); } } export async function fetchPokerTable(tableId: string): Promise> { try { const { user } = await authenticate(); const snapshot = getSnapshotFor(tableId, Number(user.id)); return { success: true, data: snapshot }; } catch (error) { return toError(error); } } export async function pokerAction( tableId: string, kind: PokerActionKind, amount?: number, ): Promise> { try { const { user } = await authenticate(); const snapshot = applyPlayerAction(tableId, Number(user.id), kind, amount); return { success: true, data: snapshot }; } catch (error) { return toError(error); } }