from __future__ import annotations from typing import Any, Dict, Optional import httpx from app.config import settings class SupabaseRestClient: """轻量封装 Supabase RESTful API,兼容本地 sb_secret 密钥。""" def __init__(self) -> None: base_url = settings.supabase_url.rstrip("/") self.client = httpx.Client( base_url=f"{base_url}/rest/v1", headers={ "apikey": settings.supabase_service_role_key, "Authorization": f"Bearer {settings.supabase_service_role_key}", }, timeout=10.0, ) def insert(self, table: str, payload: Dict[str, Any]) -> Dict[str, Any]: response = self.client.post( f"/{table}", json=payload, headers={"Prefer": "return=representation"}, ) response.raise_for_status() data = response.json() if isinstance(data, list): return data[0] return data def select_one(self, table: str, filters: Dict[str, Any]) -> Optional[Dict[str, Any]]: params = {key: f"eq.{value}" for key, value in filters.items()} params["select"] = "*" response = self.client.get(f"/{table}", params=params) response.raise_for_status() data = response.json() if isinstance(data, list) and data: return data[0] return None def update(self, table: str, filters: Dict[str, Any], payload: Dict[str, Any]) -> None: params = {key: f"eq.{value}" for key, value in filters.items()} response = self.client.patch( f"/{table}", params=params, json=payload, headers={"Prefer": "return=minimal"}, ) response.raise_for_status() supabase_rest = SupabaseRestClient()