Files
mnote/wolai-frontend/src/lib/supabase/server.ts
T
2026-01-15 20:54:21 +08:00

72 lines
3.6 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { createServerComponentClient, createRouteHandlerClient } from "@supabase/auth-helpers-nextjs";
import { getDecodedCookies } from "@/lib/server-cookies";
import { getMnoteRuntimeConfig } from "@/lib/runtime-config";
const getAuthStorageKey = (supabaseUrl: string) => {
// 说明:supabase-js 默认用 “项目 refhostname 第一个片段)” 作为 storageKey
// 同时 auth-helpers 会把该 storageKey 作为 cookie 名(sb-<ref>-auth-token)。
// 我们服务端为了绕过 FRP 自签证书,会把 supabaseUrl 指向内网/本机(例如 127.0.0.1),
// 但 cookie 名必须仍然按“公网 supabaseUrl”计算,否则会读不到浏览器写入的 cookie。
const hostname = new URL(supabaseUrl).hostname;
const ref = hostname.split(".")[0] || hostname;
return `sb-${ref}-auth-token`;
};
export const createSupabaseServerClient = async () => {
const cookieStore = await getDecodedCookies();
const cfg = getMnoteRuntimeConfig();
const publicSupabaseUrl = cfg.supabaseUrl ?? process.env.NEXT_PUBLIC_SUPABASE_URL ?? "";
const internalSupabaseUrl =
cfg.supabaseInternalUrl || process.env.SUPABASE_INTERNAL_URL || publicSupabaseUrl;
const supabaseAnonKey =
cfg.supabaseAnonKey ?? process.env.SUPABASE_ANON_KEY ?? process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY;
if (!publicSupabaseUrl || !internalSupabaseUrl || !supabaseAnonKey) {
throw new Error(
"缺少 Supabase 环境变量,请配置 NEXT_PUBLIC_SUPABASE_URL / NEXT_PUBLIC_SUPABASE_ANON_KEY(可选:SUPABASE_INTERNAL_URL / SUPABASE_ANON_KEY 作为服务端内网地址)",
);
}
// 关键:服务端请求尽量走内网/本机(HTTP),避免 FRP Auto HTTPS 的证书导致 Node 侧校验失败。
// 但 storageKey/cookie 名称必须与浏览器端一致(使用 publicSupabaseUrl 计算),否则会读不到会话。
const storageKey = getAuthStorageKey(publicSupabaseUrl);
// 注意:@supabase/auth-helpers-nextjs 的 createServerComponentClient 签名是 (context, options)。
// 如果把 supabaseUrl/supabaseKey 放进第一个参数,会被当成 context 字段而忽略,导致仍使用默认
// NEXT_PUBLIC_SUPABASE_URLHTTPS),从而触发 Node 端自签证书报错。
return createServerComponentClient(
{ cookies: () => cookieStore as any },
{
supabaseUrl: internalSupabaseUrl,
supabaseKey: supabaseAnonKey,
// 关键:显式覆盖 storageKey,让 supabase-js 读取 sb-<公网 ref>-auth-token
// 而不是 sb-<127>-auth-token。
options: { auth: { storageKey } } as any,
} as any,
);
};
export const createSupabaseRouteClient = async () => {
const cookieStore = await getDecodedCookies();
const cfg = getMnoteRuntimeConfig();
const publicSupabaseUrl = cfg.supabaseUrl ?? process.env.NEXT_PUBLIC_SUPABASE_URL ?? "";
const internalSupabaseUrl =
cfg.supabaseInternalUrl || process.env.SUPABASE_INTERNAL_URL || publicSupabaseUrl;
const supabaseAnonKey =
cfg.supabaseAnonKey ?? process.env.SUPABASE_ANON_KEY ?? process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY;
if (!publicSupabaseUrl || !internalSupabaseUrl || !supabaseAnonKey) {
throw new Error(
"缺少 Supabase 环境变量,请配置 NEXT_PUBLIC_SUPABASE_URL / NEXT_PUBLIC_SUPABASE_ANON_KEY(可选:SUPABASE_INTERNAL_URL / SUPABASE_ANON_KEY 作为服务端内网地址)",
);
}
const storageKey = getAuthStorageKey(publicSupabaseUrl);
return createRouteHandlerClient(
{ cookies: () => cookieStore as any },
{
supabaseUrl: internalSupabaseUrl,
supabaseKey: supabaseAnonKey,
options: { auth: { storageKey } } as any,
} as any,
);
};