from contextlib import asynccontextmanager from fastapi import FastAPI, Request from fastapi.middleware.cors import CORSMiddleware from fastapi.responses import JSONResponse from app import __version__ from app.api.v1 import api_router from app.api.v1 import health from app.core.config import settings from app.core.logging import configure_logging, get_logger from app.middlewares.tenant import TenantHeaderMiddleware from shared.exceptions import AppError from shared.responses import ErrorDetail, ErrorResponse configure_logging(settings.log_level) logger = get_logger(__name__) @asynccontextmanager async def lifespan(app: FastAPI): logger.info("service_starting", extra={"service": settings.service_name}) yield def create_app() -> FastAPI: app = FastAPI( title="Delivery & Fleet Platform", version=__version__, description="Torbat Driver — Delivery & Fleet Platform (Phase 10.1 Driver Management)", lifespan=lifespan, ) app.add_middleware( CORSMiddleware, allow_origins=settings.cors_origin_list, allow_origin_regex=r"https?://([a-z0-9-]+\.)*torbatyar\.ir", allow_credentials=False, allow_methods=["*"], allow_headers=["*"], ) app.add_middleware(TenantHeaderMiddleware) @app.exception_handler(AppError) async def app_error_handler(request: Request, exc: AppError) -> JSONResponse: return JSONResponse( status_code=exc.status_code, content=ErrorResponse( error=ErrorDetail( code=exc.error_code, message=exc.message, details=exc.details ) ).model_dump(), ) @app.exception_handler(Exception) async def unhandled_handler(request: Request, exc: Exception) -> JSONResponse: logger.error("unhandled_exception", extra={"error": str(exc)}, exc_info=exc) return JSONResponse( status_code=500, content=ErrorResponse( error=ErrorDetail(code="internal_error", message="خطای داخلی سرور") ).model_dump(), ) app.include_router(health.router) app.include_router(api_router, prefix=settings.api_v1_prefix) return app app = create_app()