import type { FastifyPluginAsync } from 'fastify'; import { z } from 'zod'; import { emitToPlayer } from '../../realtime/socket.js'; import { authGuard } from '../../shared/authGuard.js'; import { parseOrThrow } from '../../shared/validators.js'; import { claimMission, listActive, listAvailable, startMission } from './missions.service.js'; const missionParamsSchema = z.object({ missionId: z.string().uuid() }); const playerMissionParamsSchema = z.object({ playerMissionId: z.string().uuid() }); export const missionsRoutes: FastifyPluginAsync = async (app) => { app.addHook('preHandler', authGuard); app.get('/available', async (request) => { return listAvailable(request.user.playerId); }); app.get('/active', async (request) => { return listActive(request.user.playerId); }); app.post('/:missionId/start', async (request, reply) => { const { missionId } = parseOrThrow(missionParamsSchema, request.params); const playerMission = await startMission(request.user.playerId, missionId); request.log.info( { playerId: request.user.playerId, missionId, playerMissionId: playerMission.id }, 'mission:start', ); return reply.status(201).send({ playerMissionId: playerMission.id, status: playerMission.status, startedAt: playerMission.startedAt, completesAt: playerMission.completesAt, }); }); app.post('/:playerMissionId/claim', async (request) => { const { playerMissionId } = parseOrThrow(playerMissionParamsSchema, request.params); const result = await claimMission(request.user.playerId, playerMissionId); request.log.info( { playerId: request.user.playerId, playerMissionId, success: result.success, rewardMoney: result.rewardMoney, }, 'mission:claim', ); emitToPlayer(request.user.playerId, 'player:notification', { type: 'mission:result', playerMissionId, success: result.success, }); return result; }); };