import type { FastifyInstance, FastifyRequest } from 'fastify'; import { gameAuth, gameRoute } from './game-api.js'; import { ApiError, type GameSessionStore } from './game-session-store.js'; import type { RankedService } from './ranked-service.js'; import type { FighterAppearance } from '../shared/cosmetics.js'; import type { ActionId } from '../shared/types.js'; export function registerRankedApi(app: FastifyInstance, sessions: GameSessionStore, service: RankedService) { const identity = async (request: FastifyRequest) => { const session = await sessions.get(gameAuth(request)); if (!session.playerId) throw new ApiError(401, 'INVALID_SESSION'); return { playerId: session.playerId, gameSessionId: session.gameSessionId }; }; gameRoute(app, 'GET', '/api/profile', async request => service.profile((await identity(request)).playerId)); gameRoute(app, 'POST', '/api/profile', async request => { const { playerId } = await identity(request); return service.updateProfile(playerId, request.body as { appearance?: FighterAppearance }); }); gameRoute(app, 'GET', '/api/ranked/leaderboard', async request => service.leaderboard((await identity(request)).playerId)); for (const [url, method] of [['status', 'GET'], ['queue', 'POST'], ['cancel', 'POST']] as const) { gameRoute(app, method, `/api/ranked/${url}`, async request => { const { playerId, gameSessionId } = await identity(request); return service[url === 'queue' ? 'join' : url](playerId, gameSessionId); }); } gameRoute(app, 'POST', '/api/ranked/action', async request => { const { playerId, gameSessionId } = await identity(request); const body = request.body as { matchId: string; turnId: number; action: ActionId } | undefined; if (!body) throw new ApiError(400, 'INVALID_REQUEST'); return service.action(playerId, gameSessionId, body.matchId, body.turnId, body.action); }); gameRoute(app, 'POST', '/api/ranked/leave', async request => { const { playerId, gameSessionId } = await identity(request); const body = request.body as { matchId: string } | undefined; if (!body) throw new ApiError(400, 'INVALID_REQUEST'); return service.leave(playerId, gameSessionId, body.matchId); }); }