kernl-backend / backend /db /supabase.py
ALPHA0008's picture
feat: dashboard UI overhaul + auth flow + auto-company-load
5f7dc7e
import os
from supabase import create_client, Client
from dotenv import load_dotenv
load_dotenv()
SUPABASE_URL = os.getenv("SUPABASE_URL")
SUPABASE_KEY = os.getenv("SUPABASE_KEY")
if SUPABASE_URL and SUPABASE_KEY:
supabase: Client = create_client(SUPABASE_URL, SUPABASE_KEY)
else:
# We allow the app to start without Supabase for local testing if needed,
# but actual DB calls will fail if not provided.
supabase = None
def get_client():
return supabase
def get_current_brain(company_id: str):
if not supabase:
return None
res = (
supabase.table("skills_files")
.select("*")
.eq("company_id", company_id)
.eq("is_current", True)
.execute()
)
if res.data:
return res.data[0]
return None
def save_skills_file(data: dict):
if not supabase:
return None
res = supabase.table("skills_files").insert(data).execute()
return res.data
def save_compile_run(data: dict):
if not supabase:
return None
res = supabase.table("compile_runs").insert(data).execute()
return res.data
def update_compile_run(run_id: str, data: dict):
if not supabase:
return None
res = supabase.table("compile_runs").update(data).eq("id", run_id).execute()
return res.data
def get_source_hashes(company_id: str):
if not supabase:
return {}
# Get the latest current brain
brain = get_current_brain(company_id)
if brain:
return brain.get("source_hashes", {})
return {}
def save_source_file(data: dict):
if not supabase:
return None
res = supabase.table("source_files").insert(data).execute()
return res.data
def get_skills_by_brain_id(brain_id: str):
if not supabase:
return []
res = supabase.table("skills").select("*").eq("skills_file_id", brain_id).execute()
return res.data
def insert_skills(data: list):
if not supabase:
return None
res = supabase.table("skills").insert(data).execute()
return res.data
def get_brain_by_version(company_id: str, version: str):
if not supabase:
return None
res = (
supabase.table("skills_files")
.select("*")
.eq("company_id", company_id)
.eq("version", version)
.execute()
)
if res.data:
return res.data[0]
return None
# ─────────────────────────────────────────────
# Phase 3 β€” Company CRUD
# ─────────────────────────────────────────────
def get_company(company_id: str):
if not supabase:
return None
res = supabase.table("companies").select("*").eq("id", company_id).execute()
return res.data[0] if res.data else None
def upsert_company(company_id: str, data: dict):
if not supabase:
return None
existing = get_company(company_id)
if existing:
data.pop("id", None)
data.pop("created_at", None)
res = supabase.table("companies").update(data).eq("id", company_id).execute()
else:
data.setdefault("id", company_id)
res = supabase.table("companies").insert(data).execute()
return res.data[0] if res.data else None
def get_company_stats(company_id: str):
if not supabase:
return {"skill_count": 0, "source_count": 0, "last_compile": None}
skill_res = (
supabase.table("skills")
.select("id", count="exact")
.eq("company_id", company_id)
.eq("stale", False)
.execute()
)
source_res = (
supabase.table("source_files")
.select("id", count="exact")
.eq("company_id", company_id)
.execute()
)
compile_res = (
supabase.table("compile_runs")
.select("completed_at, result_version")
.eq("company_id", company_id)
.eq("status", "complete")
.order("completed_at", desc=True)
.limit(1)
.execute()
)
return {
"skill_count": getattr(skill_res, "count", 0) or len(skill_res.data or []),
"source_count": getattr(source_res, "count", 0) or len(source_res.data or []),
"last_compile": compile_res.data[0] if compile_res.data else None,
}
# ─────────────────────────────────────────────
# Phase 4 β€” Skills Marketplace
# ─────────────────────────────────────────────
def import_skills_file(
company_id: str, skills: list, version: str, source_label: str
) -> dict | None:
if not supabase:
return None
supabase.table("skills_files").update({"is_current": False}).eq(
"company_id", company_id
).eq("is_current", True).execute()
brain_json = {
"skills": skills,
"meta": {"imported": True, "source": source_label, "version": version},
}
skills_file = {
"company_id": company_id,
"version": version,
"brain_json": brain_json,
"source_hashes": {},
"is_current": True,
}
skills_file_res = supabase.table("skills_files").insert(skills_file).execute()
if not skills_file_res.data:
return None
sf = skills_file_res.data[0]
skill_rows = [
{
"id": s.get("id", f"imported_{i}"),
"company_id": company_id,
"skills_file_id": sf["id"],
"name": s.get("rule", "")[:255],
"domain": s.get("category", "Unknown"),
"version": version,
"confidence": s.get("confidence", 0.5),
"skill_json": s,
}
for i, s in enumerate(skills)
]
if skill_rows:
supabase.table("skills").insert(skill_rows).execute()
return sf