"""Database engine, session factory, and base model. All app code uses the async SQLAlchemy API. Alembic migrations use the synchronous psycopg2 URL for the CLI (see alembic/env.py). Usage in routes: from app.db import get_session from sqlalchemy.ext.asyncio import AsyncSession async def my_route(db: AsyncSession = Depends(get_session)): result = await db.execute(select(User).where(User.email == email)) user = result.scalar_one_or_none() """ from __future__ import annotations from collections.abc import AsyncGenerator from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker, create_async_engine from sqlalchemy.orm import DeclarativeBase from app.config.settings import settings engine = create_async_engine( settings.DATABASE_URL, pool_pre_ping=True, echo=False, ) async_session = async_sessionmaker(engine, expire_on_commit=False) class Base(DeclarativeBase): """Shared declarative base for all ORM models.""" async def get_session() -> AsyncGenerator[AsyncSession, None]: """FastAPI dependency that yields an async DB session per request.""" async with async_session() as session: yield session