Files
PolyWeather/frontend/lib/supabase/server.ts
2026-05-29 17:22:33 +08:00

140 lines
3.4 KiB
TypeScript

import { createServerClient, type CookieOptions } from "@supabase/ssr";
import { NextRequest, NextResponse } from "next/server";
type CookieAdapter = {
getAll: () => { name: string; value: string }[];
setAll: (cookies: { name: string; value: string; options?: CookieOptions }[]) => void;
};
function readSupabasePublicEnv() {
const url = process.env.NEXT_PUBLIC_SUPABASE_URL?.trim();
const anonKey = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY?.trim();
return { anonKey, url };
}
export function hasSupabaseServerEnv() {
const { anonKey, url } = readSupabasePublicEnv();
return Boolean(url && anonKey);
}
export function hasSupabaseSessionCookieValues(
cookies: { name: string; value: string }[],
) {
return cookies.some((cookie) => {
const name = cookie.name.toLowerCase();
const value = String(cookie.value || "").trim();
if (!value) return false;
return (
name === "supabase-auth-token" ||
(name.startsWith("sb-") && name.includes("-auth-token"))
);
});
}
export function createSupabaseServerClient(
cookieAdapter: CookieAdapter,
) {
const { anonKey, url } = readSupabasePublicEnv();
if (!url || !anonKey) {
throw new Error("Supabase env is not configured");
}
return createServerClient(url, anonKey, {
cookies: cookieAdapter,
});
}
export function createSupabaseMiddlewareClient(
request: NextRequest,
response: NextResponse,
) {
return createSupabaseServerClient({
getAll() {
return request.cookies.getAll().map((item) => ({
name: item.name,
value: item.value,
}));
},
setAll(cookiesToSet) {
for (const cookie of cookiesToSet) {
response.cookies.set(cookie.name, cookie.value, cookie.options);
}
},
});
}
export function createSupabaseRouteClient(
request: NextRequest,
response: NextResponse,
) {
return createSupabaseServerClient({
getAll() {
return request.cookies.getAll().map((item) => ({
name: item.name,
value: item.value,
}));
},
setAll(cookiesToSet) {
for (const cookie of cookiesToSet) {
response.cookies.set(cookie.name, cookie.value, cookie.options);
}
},
});
}
export async function refreshMiddlewareSession(request: NextRequest) {
let response = NextResponse.next({
request: {
headers: request.headers,
},
});
if (!hasSupabaseServerEnv()) {
return { response, user: null };
}
const supabaseCookies = request.cookies.getAll().map((item) => ({
name: item.name,
value: item.value,
}));
if (!hasSupabaseSessionCookieValues(supabaseCookies)) {
return { response, user: null };
}
const supabase = createSupabaseServerClient({
getAll() {
return supabaseCookies;
},
setAll(cookiesToSet) {
for (const cookie of cookiesToSet) {
request.cookies.set(cookie.name, cookie.value);
}
response = NextResponse.next({
request: {
headers: request.headers,
},
});
for (const cookie of cookiesToSet) {
response.cookies.set(cookie.name, cookie.value, cookie.options);
}
},
});
try {
const {
data,
error,
} = await supabase.auth.getClaims();
if (error || !data?.claims?.sub) {
return { response, user: null };
}
const user = {
id: String(data.claims.sub || ""),
email: String(data.claims.email || ""),
};
return { response, user };
} catch {
return { response, user: null };
}
}