Files
mnote/wolai-frontend/src/lib/server-cookies.ts
T

62 lines
2.0 KiB
TypeScript
Raw Normal View History

2026-04-13 19:21:42 +08:00
"use server";
import { cookies } from "next/headers";
type RequestCookies = Awaited<ReturnType<typeof cookies>>;
2025-11-23 10:55:04 +08:00
const decodeValue = (value?: string) => {
if (!value) return value;
2026-01-15 20:54:21 +08:00
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;
2025-11-23 10:55:04 +08:00
};
2026-04-13 19:21:42 +08:00
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<RequestCookies["getAll"]>) =>
store.getAll(...args).map((cookie) => ({ ...cookie, value: decodeValue(cookie.value) })),
2025-11-23 10:55:04 +08:00
set: (...args: Parameters<RequestCookies["set"]>) => {
2026-01-08 06:28:14 +08:00
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;
2025-11-23 10:55:04 +08:00
}
2026-01-08 06:28:14 +08:00
(store as any).set(...(args as any));
2025-11-23 10:55:04 +08:00
},
2026-04-13 19:21:42 +08:00
delete: (...args: Parameters<RequestCookies["delete"]>) => store.delete(...args),
has: (...args: Parameters<RequestCookies["has"]>) => store.has(...args),
};
};
export const getDecodedCookies = async () => {
const store = await cookies();
return wrapCookies(store) as RequestCookies;
};