Files
Jyotisha/frontend/src/lib/supabase/admin-client-core.ts
T
jesse-uxandGrok (agent loop) b184448871 fix(db): check callers against the adapter that actually runs
The self-hosted client was typed as a full Supabase client, so an old scoring poll called .single() on a plain promise and failed. The new DataClient only lists methods the adapter implements.

Co-Authored-By: Grok (agent loop)
2026-10-15 09:21:14 +08:00

45 lines
1.5 KiB
TypeScript

import { createClient } from "@supabase/supabase-js";
import type { DataClient } from "@/lib/db/data-client";
import { createLocalPostgresDataClient } from "@/lib/db/local-postgres-client-core";
import {
getSupabaseUrl,
SupabaseConfigurationError,
} from "./config";
export function createAdminSupabaseClient(): DataClient {
if (process.env.AUTH_PROVIDER?.trim() === "self-hosted") {
const connectionString = process.env.SERVICE_DATABASE_URL?.trim();
if (!connectionString) {
throw new SupabaseConfigurationError(["SERVICE_DATABASE_URL"]);
}
if (!connectionString.startsWith("postgresql://")) {
throw new Error("SERVICE_DATABASE_URL must be a PostgreSQL URL");
}
return createLocalPostgresDataClient(
connectionString,
null,
"service_role",
) as DataClient;
}
const url = getSupabaseUrl();
const serviceRoleKey = process.env.SUPABASE_SERVICE_ROLE_KEY;
if (!serviceRoleKey) {
throw new SupabaseConfigurationError(["SUPABASE_SERVICE_ROLE_KEY"]);
}
// 回滚分支,运行时形状是超集
return createClient(url, serviceRoleKey, {
auth: { autoRefreshToken: false, persistSession: false },
}) as unknown as DataClient;
}
export function isAdminEmail(email: string | null | undefined) {
const configured = process.env.ADMIN_EMAILS;
if (!configured?.trim() || !email) return false;
const normalized = email.trim().toLowerCase();
return configured
.split(",")
.some((candidate) => candidate.trim().toLowerCase() === normalized);
}