import { Body, Controller, Delete, Get, HttpCode, HttpStatus, Param, ParseUUIDPipe, Patch, Post, Query, UseGuards, } from '@nestjs/common'; import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger'; import { createServerRequestSchema, updateServerRequestSchema } from '@hexahost/contracts'; import { CurrentUser } from '../auth/decorators/current-user.decorator'; import { SessionGuard } from '../auth/guards/session.guard'; import { ZodValidationPipe } from '../common/pipes/zod-validation.pipe'; import { ServersService } from './servers.service'; import { IdleService } from './idle/idle.service'; @ApiTags('servers') @Controller('servers') @UseGuards(SessionGuard) export class ServersController { constructor( private readonly serversService: ServersService, private readonly idleService: IdleService, ) {} @Post() @HttpCode(HttpStatus.CREATED) @ApiOperation({ summary: 'Create a game server' }) @ApiResponse({ status: 201, description: 'Server created' }) create( @CurrentUser() user: { id: string }, @Body(new ZodValidationPipe(createServerRequestSchema)) body: unknown, ) { return this.serversService.createServer( user.id, body as Parameters[1], ); } @Get() @ApiOperation({ summary: 'List owned game servers' }) list(@CurrentUser() user: { id: string }) { return this.serversService.listServers(user.id); } @Get(':id') @ApiOperation({ summary: 'Get a game server by id' }) get( @CurrentUser() user: { id: string }, @Param('id', ParseUUIDPipe) id: string, ) { return this.serversService.getServer(user.id, id); } @Post(':id/start') @HttpCode(HttpStatus.ACCEPTED) @ApiOperation({ summary: 'Start a game server' }) start( @CurrentUser() user: { id: string }, @Param('id', ParseUUIDPipe) id: string, ) { return this.serversService.startServer(user.id, id); } @Post(':id/stop') @HttpCode(HttpStatus.ACCEPTED) @ApiOperation({ summary: 'Stop a game server' }) stop( @CurrentUser() user: { id: string }, @Param('id', ParseUUIDPipe) id: string, ) { return this.serversService.stopServer(user.id, id); } @Post(':id/restart') @HttpCode(HttpStatus.ACCEPTED) @ApiOperation({ summary: 'Restart a game server' }) restart( @CurrentUser() user: { id: string }, @Param('id', ParseUUIDPipe) id: string, @Query('skip') skip?: string, ) { return this.serversService.restartServer(user.id, id, skip === 'true'); } @Post(':id/kill') @HttpCode(HttpStatus.ACCEPTED) @ApiOperation({ summary: 'Force-kill a running game server' }) kill( @CurrentUser() user: { id: string }, @Param('id', ParseUUIDPipe) id: string, ) { return this.serversService.killServer(user.id, id); } @Delete(':id') @HttpCode(HttpStatus.ACCEPTED) @ApiOperation({ summary: 'Delete a game server' }) delete( @CurrentUser() user: { id: string }, @Param('id', ParseUUIDPipe) id: string, ) { return this.serversService.deleteServer(user.id, id); } @Patch(':id') @ApiOperation({ summary: 'Update server metadata' }) patch( @CurrentUser() user: { id: string }, @Param('id', ParseUUIDPipe) id: string, @Body(new ZodValidationPipe(updateServerRequestSchema)) body: unknown, ) { return this.serversService.updateServer( user.id, id, body as Parameters[2], ); } @Get(':id/start-queue') @ApiOperation({ summary: 'Get start queue status for a server' }) startQueue( @CurrentUser() user: { id: string }, @Param('id', ParseUUIDPipe) id: string, ) { return this.serversService.getStartQueue(user.id, id); } @Post(':id/cancel-queue') @HttpCode(HttpStatus.OK) @ApiOperation({ summary: 'Cancel a queued server start' }) cancelQueue( @CurrentUser() user: { id: string }, @Param('id', ParseUUIDPipe) id: string, ) { return this.serversService.cancelQueuedStart(user.id, id); } @Get(':id/idle') @ApiOperation({ summary: 'Get idle shutdown status' }) idleStatus( @CurrentUser() user: { id: string }, @Param('id', ParseUUIDPipe) id: string, ) { return this.idleService.getIdleStatus(user.id, id); } @Post(':id/idle/extend') @HttpCode(HttpStatus.OK) @ApiOperation({ summary: 'Extend idle shutdown countdown by 5 minutes' }) extendIdle( @CurrentUser() user: { id: string }, @Param('id', ParseUUIDPipe) id: string, ) { return this.idleService.extendIdleCountdown(user.id, id); } }