from collections.abc import AsyncIterator from contextlib import asynccontextmanager from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware from slowapi import _rate_limit_exceeded_handler from slowapi.errors import RateLimitExceeded from slowapi.middleware import SlowAPIMiddleware from app.auth.router import router as auth_router from app.config import settings from app.database import engine from app.limiter import limiter from app.routers.budgets import router as budgets_router from app.routers.categories import router as categories_router from app.routers.dashboard import router as dashboard_router from app.routers.export import router as export_router from app.routers.history import router as history_router from app.routers.transactions import router as transactions_router @asynccontextmanager async def lifespan(_app: FastAPI) -> AsyncIterator[None]: yield await engine.dispose() def create_app() -> FastAPI: app = FastAPI( title="Budget Tracker API", version="0.1.0", lifespan=lifespan, ) app.state.limiter = limiter app.add_exception_handler(RateLimitExceeded, _rate_limit_exceeded_handler) app.add_middleware(SlowAPIMiddleware) app.add_middleware( CORSMiddleware, allow_origins=settings.CORS_ORIGINS, allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) @app.get("/health") async def health_check() -> dict[str, str]: return {"status": "ok"} api_prefix = "/api/v1" app.include_router(auth_router, prefix=api_prefix) app.include_router(transactions_router, prefix=api_prefix) app.include_router(categories_router, prefix=api_prefix) app.include_router(dashboard_router, prefix=api_prefix) app.include_router(budgets_router, prefix=api_prefix) app.include_router(history_router, prefix=api_prefix) app.include_router(export_router, prefix=api_prefix) return app app = create_app()