from typing import TYPE_CHECKING, Optional from uuid import UUID from litestar import Controller, get, post, put from litestar.contrib.repository.filters import LimitOffset, SearchFilter from litestar.di import Provide from sqlalchemy.ext.asyncio import AsyncSession from app.domain.user import Repository, Service, User, UserReadDTO, UserWriteDTO from app.lib.responses import ObjectListResponse, ObjectResponse if TYPE_CHECKING: from sqlalchemy.ext.asyncio import AsyncSession DETAIL_ROUTE = "/{user_id:uuid}" def provides_service(db_session: AsyncSession) -> Service: """Constructs repository and service objects for the request.""" return Service(Repository(session=db_session)) class UserController(Controller): dto = UserWriteDTO return_dto = UserReadDTO path = "/users" dependencies = { "service": Provide(provides_service, sync_to_thread=False), } tags = ["Users"] @get() async def get_users( self, service: Service, search: Optional[str] = None ) -> ObjectListResponse[User]: filters = [ LimitOffset(limit=20, offset=0), ] if search is not None: filters.append( SearchFilter( field_name="caption", value=search, ), ) content = await service.list(*filters) return ObjectListResponse(content=content) @post() async def create_user( self, data: User, service: Service, ) -> ObjectResponse[User]: print(data) content = await service.create(data) return ObjectResponse(content=content) @get(DETAIL_ROUTE) async def get_user(self, service: Service, user_id: UUID) -> ObjectResponse[User]: content = await service.get(user_id) return ObjectResponse(content=content) @put(DETAIL_ROUTE) async def update_user( self, data: User, service: Service, user_id: UUID ) -> ObjectResponse[User]: data.id = user_id content = await service.update(user_id, data) return ObjectResponse(content=content)