File size: 1,891 Bytes
53e1531 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | """
Shortlist — Supabase Database Client
Async Supabase client for FastAPI integration.
Handles connection lifecycle and provides dependency injection.
"""
from contextlib import asynccontextmanager
from typing import AsyncGenerator, Optional
from supabase import acreate_client, AsyncClient
from app.config import get_settings
# Module-level client reference — initialized during app lifespan
_supabase_client: Optional[AsyncClient] = None
async def init_supabase() -> AsyncClient:
"""
Initialize the async Supabase client.
Called once during application startup.
Uses the SERVICE_KEY for server-side operations.
"""
global _supabase_client
settings = get_settings()
if not settings.SUPABASE_URL or not settings.SUPABASE_SERVICE_KEY:
raise RuntimeError(
"SUPABASE_URL and SUPABASE_SERVICE_KEY must be set. "
"Check your .env file."
)
_supabase_client = await acreate_client(
supabase_url=settings.SUPABASE_URL,
supabase_key=settings.SUPABASE_SERVICE_KEY,
)
return _supabase_client
async def close_supabase() -> None:
"""
Cleanup Supabase client on shutdown.
"""
global _supabase_client
# supabase-py async client doesn't have explicit close,
# but we clear the reference for clean shutdown
_supabase_client = None
def get_supabase() -> AsyncClient:
"""
Dependency injection for route handlers.
Returns the initialized Supabase client.
Usage:
@router.get("/data")
async def get_data(db: AsyncClient = Depends(get_supabase)):
result = await db.table("table").select("*").execute()
"""
if _supabase_client is None:
raise RuntimeError(
"Supabase client not initialized. "
"Ensure init_supabase() was called during startup."
)
return _supabase_client
|