afa67's picture
deploy dry-run demo
257a670 verified
Raw
History Blame
1.35 kB
"""Supabase Storage helpers — so avatars, products, clips and final videos all live
in Supabase, not on local disk (SPEC_NEW §3). Uses the service-role key over the
Storage REST API. Falls back to local disk at the call sites if not configured.
"""
from __future__ import annotations
import httpx
from .config import get_settings
def enabled() -> bool:
s = get_settings()
return bool(s.supabase_url and s.supabase_service_role_key)
def is_remote(path: str | None) -> bool:
return bool(path) and str(path).startswith(("http://", "https://"))
def public_url(bucket: str, path: str) -> str:
base = get_settings().supabase_url.rstrip("/")
return f"{base}/storage/v1/object/public/{bucket}/{path}"
def upload_bytes(bucket: str, path: str, data: bytes, content_type: str) -> str:
"""Upload to a public bucket; return the public URL. Raises on failure."""
s = get_settings()
base = s.supabase_url.rstrip("/")
r = httpx.post(
f"{base}/storage/v1/object/{bucket}/{path}", content=data,
headers={"Authorization": f"Bearer {s.supabase_service_role_key}",
"Content-Type": content_type, "x-upsert": "true"},
timeout=180,
)
if r.status_code >= 400:
raise RuntimeError(f"Supabase Storage {r.status_code}: {r.text[:200]}")
return public_url(bucket, path)