"""FastAPI app factory for CartSnitch API Gateway.""" from contextlib import asynccontextmanager from fastapi import APIRouter, FastAPI from cartsnitch_api.auth.routes import router as auth_router from cartsnitch_api.cache import cache_client from cartsnitch_api.middleware.audit import add_audit_middleware from cartsnitch_api.middleware.cors import add_cors_middleware from cartsnitch_api.middleware.error_handler import add_error_handlers, add_error_monitor_middleware from cartsnitch_api.middleware.rate_limit import add_rate_limit_middleware from cartsnitch_api.routes.alerts import router as alerts_router from cartsnitch_api.routes.coupons import router as coupons_router from cartsnitch_api.routes.health import router as health_router from cartsnitch_api.routes.prices import router as prices_router from cartsnitch_api.routes.products import router as products_router from cartsnitch_api.routes.public import router as public_router from cartsnitch_api.routes.purchases import router as purchases_router from cartsnitch_api.routes.scraping import router as scraping_router from cartsnitch_api.routes.shopping import router as shopping_router from cartsnitch_api.routes.stores import router as stores_router from cartsnitch_api.routes.user import router as user_router @asynccontextmanager async def lifespan(app: FastAPI): from cartsnitch_api.database import dispose_engine await cache_client.initialize() yield await cache_client.close() await dispose_engine() def create_app() -> FastAPI: app = FastAPI( title="CartSnitch API", description="Grocery price tracking and shrinkflation detection API", version="0.1.0", lifespan=lifespan, ) # Middleware (order matters — outermost first) add_cors_middleware(app) add_error_monitor_middleware(app) add_rate_limit_middleware(app) add_audit_middleware(app) # Exception handlers add_error_handlers(app) # Routers app.include_router(health_router) app.include_router(auth_router) # Data endpoints mounted under /api/v1 v1_router = APIRouter(prefix="/api/v1") v1_router.include_router(user_router) v1_router.include_router(stores_router) v1_router.include_router(purchases_router) v1_router.include_router(products_router) v1_router.include_router(prices_router) v1_router.include_router(coupons_router) v1_router.include_router(shopping_router) v1_router.include_router(alerts_router) v1_router.include_router(scraping_router) v1_router.include_router(public_router) app.include_router(v1_router) return app app = create_app()