from contextlib import asynccontextmanager from typing import AsyncIterator from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware from app.api.routes import health, resume, analysis from app.core.config import settings from app.core.logging import setup_logging setup_logging() @asynccontextmanager async def lifespan(_: FastAPI) -> AsyncIterator[None]: """Startup / shutdown hook.""" # Ensure upload directory exists (config.py also does this at import time, # but this is the canonical place for startup side-effects). settings.upload_dir.mkdir(parents=True, exist_ok=True) yield app = FastAPI( title="AI Resume Reviewer API", description=( "Hybrid ATS-style resume analysis: rules + embeddings + LLM. " "Phase 0/1 — ingestion and extraction only." ), version="0.1.0", lifespan=lifespan, ) # ── CORS ────────────────────────────────────────────────────────────────────── # Allow the Vite dev server (8081) and any localhost variant during development. # In production, lock this to your actual frontend domain. app.add_middleware( CORSMiddleware, allow_origins=["*"], allow_credentials=False, allow_methods=["*"], allow_headers=["*"], expose_headers=["X-Session-Id"], ) # ── Routers ─────────────────────────────────────────────────────────────────── app.include_router(health.router, prefix="/api") app.include_router(resume.router, prefix="/api") app.include_router(analysis.router, prefix="/api")