import { Body, Controller, Delete, Get, Param, Patch, Post, Req, Sse, UnauthorizedException, UseGuards, } from '@nestjs/common'; import { Observable } from 'rxjs'; import { JwtAuthGuard } from '../auth/jwt-auth.guard'; import { AuthService } from '../auth/auth.service'; import { CreateListDto } from './dto/create-list.dto'; import { AddListItemDto, UpdateListItemDto } from './dto/list-item.dto'; import { ShareListDto } from './dto/share-list.dto'; import { UpdateListDto } from './dto/update-list.dto'; import { ListRealtimeService } from './list-realtime.service'; import { ListsService } from './lists.service'; import type { AuthenticatedRequest } from '../auth/auth.types'; import type { MessageEvent } from '@nestjs/common'; @Controller('lists') @UseGuards(JwtAuthGuard) export class ListsController { constructor( private readonly authService: AuthService, private readonly listRealtimeService: ListRealtimeService, private readonly listsService: ListsService, ) {} @Post() createList( @Req() request: AuthenticatedRequest, @Body() createDto: CreateListDto, ) { return this.listsService.createList(this.requireUserId(request), createDto); } @Post('with-item-suggestions') createListWithItemSuggestions( @Req() request: AuthenticatedRequest, @Body() createDto: CreateListDto, ) { return this.listsService.createListWithItemSuggestions( this.requireUserId(request), createDto, ); } @Get() listLists(@Req() request: AuthenticatedRequest) { return this.listsService.listLists(this.requireUserId(request)); } @Sse('events') listEvents(@Req() request: AuthenticatedRequest): Observable { return this.listRealtimeService.eventsFor(this.requireUserId(request)); } @Get(':listId') getList( @Req() request: AuthenticatedRequest, @Param('listId') listId: string, ) { return this.listsService.getList(this.requireUserId(request), listId); } @Patch(':listId') updateList( @Req() request: AuthenticatedRequest, @Param('listId') listId: string, @Body() updateDto: UpdateListDto, ) { return this.listsService.updateList( this.requireUserId(request), listId, updateDto, ); } @Delete(':listId') deleteList( @Req() request: AuthenticatedRequest, @Param('listId') listId: string, ) { return this.listsService.deleteList(this.requireUserId(request), listId); } @Post(':listId/shares') shareList( @Req() request: AuthenticatedRequest, @Param('listId') listId: string, @Body() shareDto: ShareListDto, ) { return this.listsService.shareList( this.requireUserId(request), listId, shareDto, ); } @Delete(':listId/shares/:userId') removeShare( @Req() request: AuthenticatedRequest, @Param('listId') listId: string, @Param('userId') userId: string, ) { return this.listsService.removeShare( this.requireUserId(request), listId, userId, ); } @Post(':listId/items') addItem( @Req() request: AuthenticatedRequest, @Param('listId') listId: string, @Body() addDto: AddListItemDto, ) { return this.listsService.addItem( this.requireUserId(request), listId, addDto, ); } @Post(':listId/item-suggestions') suggestItems( @Req() request: AuthenticatedRequest, @Param('listId') listId: string, ) { return this.listsService.suggestItems(this.requireUserId(request), listId); } @Post(':listId/cleanup-suggestions') suggestCleanup( @Req() request: AuthenticatedRequest, @Param('listId') listId: string, ) { return this.listsService.suggestListCleanup( this.requireUserId(request), listId, ); } @Post(':listId/apply-cleanup') applyCleanup( @Req() request: AuthenticatedRequest, @Param('listId') listId: string, ) { return this.listsService.applyListCleanup( this.requireUserId(request), listId, ); } @Post(':listId/template') createTemplateFromList( @Req() request: AuthenticatedRequest, @Param('listId') listId: string, ) { return this.listsService.createTemplateFromList( this.requireUserId(request), listId, ); } @Patch(':listId/items/:itemId') async updateItem( @Req() request: AuthenticatedRequest, @Param('listId') listId: string, @Param('itemId') itemId: string, @Body() updateDto: UpdateListItemDto, ) { const userId = this.requireUserId(request); return this.listsService.updateItem( userId, listId, itemId, updateDto, await this.authService.getUserDisplayName(userId), ); } @Delete(':listId/items/:itemId') deleteItem( @Req() request: AuthenticatedRequest, @Param('listId') listId: string, @Param('itemId') itemId: string, ) { return this.listsService.deleteItem( this.requireUserId(request), listId, itemId, ); } private requireUserId(request: AuthenticatedRequest): string { if (!request.user?.sub) { throw new UnauthorizedException('Authenticated user is required.'); } return request.user.sub; } }