from typing import TYPE_CHECKING, Optional from uuid import UUID from litestar import Controller, get from litestar.contrib.repository.filters import LimitOffset, SearchFilter from litestar.di import Provide from sqlalchemy.ext.asyncio import AsyncSession from app.domain.city import ( City, CityReadDTO, CityWriteDTO, Repository, Service, ) from app.lib.responses import ObjectListResponse, ObjectResponse if TYPE_CHECKING: from sqlalchemy.ext.asyncio import AsyncSession DETAIL_ROUTE = "/{city_id:uuid}" def provides_service(db_session: AsyncSession) -> Service: """Constructs repository and service objects for the request.""" return Service(Repository(session=db_session)) class CityController(Controller): dto = CityWriteDTO return_dto = CityReadDTO path = "/cities" dependencies = { "service": Provide(provides_service, sync_to_thread=False), } tags = ["Cities"] @get() async def get_cities( self, service: Service, search: Optional[str] = None ) -> ObjectListResponse[City]: 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) @get(DETAIL_ROUTE) async def get_city( self, service: Service, city_id: UUID ) -> ObjectResponse[City]: content = await service.get(city_id) return ObjectResponse(content=content)