/** * REST API Types * * TypeScript definitions for HTTP API requests and responses. * These complement the WebSocket events for non-real-time operations. */ import type { GameListItem, CreateGameRequest, CreateGameResponse } from './game' /** * API error response */ export interface ApiError { message: string code?: string field?: string errors?: Array<{ loc: string[] msg: string type: string }> } /** * Paginated response wrapper */ export interface PaginatedResponse { items: T[] total: number page: number per_page: number has_next: boolean has_prev: boolean } /** * Game filters for list queries */ export interface GameFilters { status?: 'pending' | 'active' | 'completed' league_id?: 'sba' | 'pd' team_id?: number date_from?: string date_to?: string page?: number per_page?: number } /** * Discord OAuth callback response */ export interface DiscordAuthResponse { access_token: string refresh_token: string expires_in: number user: DiscordUser } /** * Discord user data */ export interface DiscordUser { id: string // Discord snowflake ID (gmid) username: string discriminator: string avatar: string | null email?: string } /** * JWT token payload */ export interface JwtPayload { user_id: string exp: number iat: number } /** * Team data (from league API) */ export interface Team { id: number name: string owner_id: string league_id: 'sba' | 'pd' } /** * SBA Team data (from /api/teams endpoint) */ export interface SbaTeam { id: number abbrev: string sname: string // Short name (e.g., "Geese") lname: string // Long name (e.g., "Everett Geese") color: string // Hex color code thumbnail: string | null // Team logo URL manager_legacy: string gmid: string | null gmid2: string | null division: { id: number division_name: string division_abbrev: string league_name: string league_abbrev: string season: number } } /** * User's teams response */ export interface UserTeamsResponse { teams: Team[] } // ============================================================================ // API Endpoint Types // ============================================================================ /** * POST /api/games */ export type CreateGameRequestData = CreateGameRequest export type CreateGameResponseData = CreateGameResponse /** * GET /api/games/:id */ export interface GetGameResponse { game: GameListItem } /** * GET /api/games/active */ export type GetActiveGamesResponse = PaginatedResponse /** * GET /api/games/completed */ export type GetCompletedGamesResponse = PaginatedResponse /** * GET /api/games/:id/history */ export interface PlayHistoryItem { play_number: number inning: number half: 'top' | 'bottom' outs_before: number batter_id: number pitcher_id: number result_description: string runs_scored: number outs_recorded: number created_at: string } export interface GetPlayHistoryResponse { plays: PlayHistoryItem[] total: number } /** * DELETE /api/games/:id */ export interface DeleteGameResponse { message: string game_id: string } /** * POST /api/auth/discord/callback */ export type DiscordCallbackRequest = { code: string state: string } export type DiscordCallbackResponse = DiscordAuthResponse /** * GET /api/auth/me */ export interface GetCurrentUserResponse { user: DiscordUser teams: Team[] } /** * POST /api/auth/refresh */ export interface RefreshTokenRequest { refresh_token: string } export interface RefreshTokenResponse { access_token: string expires_in: number } /** * POST /api/games/:id/lineups */ export interface LineupPlayerRequest { player_id: number position: string batting_order: number | null // null for pitcher in DH lineup } export interface SubmitLineupsRequest { home_lineup: LineupPlayerRequest[] // 9-10 players away_lineup: LineupPlayerRequest[] // 9-10 players } export interface SubmitLineupsResponse { game_id: string message: string home_lineup_count: number away_lineup_count: number }