from contextlib import asynccontextmanager from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware from app.api.v1.jobs import router as jobs_router from app.api.v1.categories import router as categories_router from app.core.config import settings from app.db.base import Base from app.db.session import engine @asynccontextmanager async def lifespan(app: FastAPI): # Startup: Create tables if they don't exist async with engine.begin() as conn: await conn.run_sync(Base.metadata.create_all) # Seed default categories if empty from app.db.session import AsyncSessionLocal from app.db.models.category import Category from sqlalchemy import select async with AsyncSessionLocal() as session: result = await session.execute(select(Category)) if not result.scalars().first(): defaults = [ Category(name="Food"), Category(name="Shopping"), Category(name="Travel"), Category(name="Transport"), Category(name="Utilities"), Category(name="Cash Withdrawal"), Category(name="Entertainment"), Category(name="Other"), ] session.add_all(defaults) await session.commit() yield # Shutdown: Clean up pool await engine.dispose() app = FastAPI( title=settings.PROJECT_NAME, openapi_url=f"{settings.API_V1_STR}/openapi.json", lifespan=lifespan, ) # CORS Middleware app.add_middleware( CORSMiddleware, allow_origins=["*"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) # Include API Routers app.include_router(jobs_router, prefix=settings.API_V1_STR) app.include_router(categories_router, prefix=settings.API_V1_STR) # Root healthcheck endpoint @app.get("/health", tags=["health"]) def health_check(): return {"status": "ok", "project": settings.PROJECT_NAME}