"use server"; import { cookies } from "next/headers"; type RequestCookies = Awaited>; const decodeValue = (value?: string) => { if (!value) return value; let v = value; // 说明:部分环境下 cookies() 读取到的值仍是 URL 编码(例如 %5B%22...%22%5D), // Supabase Auth Helpers 期望拿到可直接 JSON.parse 的字符串,因此这里做一次解码。 // 若不是合法的 URL 编码字符串,decodeURIComponent 会抛错,我们直接兜底返回原值。 if (v.includes("%")) { try { v = decodeURIComponent(v); } catch { // ignore } } return v.startsWith("base64-") ? Buffer.from(v.slice(7), "base64").toString("utf8") : v; }; const encodeValue = (value: string) => { if (!value) return value; // Next.js 会自动 base64 编码,我们只需处理已有 base64 前缀的情况 if (value.startsWith("base64-")) { return value; } return value; }; const wrapCookies = (store: RequestCookies) => { return { get: (name: string) => { const cookie = store.get(name); if (!cookie) return cookie; return { ...cookie, value: decodeValue(cookie.value) }; }, getAll: (...args: Parameters) => store.getAll(...args).map((cookie) => ({ ...cookie, value: decodeValue(cookie.value) })), set: (...args: Parameters) => { const [name, value, options] = args as unknown as [ unknown, unknown, unknown, ]; if (typeof name === "string" && typeof value === "string") { (store as any).set(name, encodeValue(value), options as any); return; } (store as any).set(...(args as any)); }, delete: (...args: Parameters) => store.delete(...args), has: (...args: Parameters) => store.has(...args), }; }; export const getDecodedCookies = async () => { const store = await cookies(); return wrapCookies(store) as RequestCookies; };