from __future__ import annotations from contextlib import asynccontextmanager from fastapi import FastAPI, Request from fastapi.exceptions import RequestValidationError from fastapi.middleware.cors import CORSMiddleware from fastapi.responses import JSONResponse from fastapi.staticfiles import StaticFiles from app.common.config.settings import get_settings from app.common.errors.app_error import AppError from app.common.middleware.logging import LoggingMiddleware, configure_logging from app.common.middleware.request_id import RequestIdMiddleware from app.core.bootstrap import init_database from app.modules.admins.router import auth_router as admin_auth_router from app.modules.admins.router import router as admins_router from app.modules.assets.router import router as assets_router from app.modules.auth.router import router as auth_router from app.modules.growth_rules.router import router as growth_rules_router from app.modules.invites.router import router as invites_router from app.modules.payments.router import admin_router as admin_payments_router from app.modules.payments.router import router as payments_router from app.modules.pricing.router import router as pricing_router from app.modules.providers.router import router as providers_router from app.modules.system.router import router as system_router from app.modules.users.router import router as users_router from app.modules.video_models.router import router as video_models_router from app.modules.video_tasks.router import admin_router as admin_video_tasks_router from app.modules.video_tasks.router import router as video_tasks_router from app.modules.wallets.router import router as wallets_router settings = get_settings() @asynccontextmanager async def lifespan(_: FastAPI): configure_logging() settings.storage_root.mkdir(parents=True, exist_ok=True) init_database() yield app = FastAPI(title=settings.app_name, debug=settings.app_debug, lifespan=lifespan) app.add_middleware(RequestIdMiddleware) app.add_middleware(LoggingMiddleware) app.add_middleware( CORSMiddleware, allow_origins=settings.parsed_cors_origins, allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) app.mount("/storage", StaticFiles(directory=settings.storage_root), name="storage") @app.exception_handler(AppError) async def app_error_handler(request: Request, exc: AppError): return JSONResponse( status_code=exc.status_code, content={ "code": exc.code, "message": exc.message, "requestId": getattr(request.state, "request_id", ""), "errors": exc.errors, }, ) @app.exception_handler(RequestValidationError) async def validation_error_handler(request: Request, exc: RequestValidationError): return JSONResponse( status_code=422, content={ "code": 10003, "message": "validation error", "requestId": getattr(request.state, "request_id", ""), "errors": exc.errors(), }, ) @app.exception_handler(Exception) async def unhandled_error_handler(request: Request, exc: Exception): return JSONResponse( status_code=500, content={ "code": 50000, "message": "internal server error", "requestId": getattr(request.state, "request_id", ""), "errors": [], }, ) @app.get("/health") def health(): return {"status": "ok"} @app.get("/ready") def ready(): return {"status": "ok"} app.include_router(auth_router) app.include_router(users_router) app.include_router(wallets_router) app.include_router(payments_router) app.include_router(invites_router) app.include_router(assets_router) app.include_router(video_models_router) app.include_router(video_tasks_router) app.include_router(admin_auth_router) app.include_router(admins_router) app.include_router(admin_payments_router) app.include_router(providers_router) app.include_router(pricing_router) app.include_router(growth_rules_router) app.include_router(system_router) app.include_router(admin_video_tasks_router)