portal-session.ts 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. /**
  2. * Browser helpers: mint / clear / read first-party portal session after any login method.
  3. */
  4. export type AuthMethod = "email" | "wallet" | "konnos" | "demo";
  5. export function userIdFromEngineBody(
  6. data: Record<string, unknown>,
  7. ): string | null {
  8. const user = data.user as { id?: string } | undefined;
  9. const session = data.session as { userId?: string } | undefined;
  10. const id =
  11. user?.id ||
  12. session?.userId ||
  13. (typeof data.userId === "string" ? data.userId : null);
  14. return id || null;
  15. }
  16. export async function establishPortalSession(input: {
  17. userId: string;
  18. email?: string;
  19. method?: AuthMethod;
  20. walletAddress?: string;
  21. }): Promise<void> {
  22. if (typeof window === "undefined") return;
  23. try {
  24. await fetch("/api/session", {
  25. method: "POST",
  26. credentials: "include",
  27. headers: { "content-type": "application/json" },
  28. body: JSON.stringify({
  29. userId: input.userId,
  30. email: input.email,
  31. method: input.method ?? "email",
  32. walletAddress: input.walletAddress,
  33. }),
  34. });
  35. } catch {
  36. /* soft gate */
  37. }
  38. }
  39. export async function clearPortalSession(): Promise<void> {
  40. if (typeof window === "undefined") return;
  41. try {
  42. await fetch("/api/session", { method: "DELETE", credentials: "include" });
  43. } catch {
  44. /* ignore */
  45. }
  46. }
  47. export type PortalSessionState =
  48. | {
  49. authenticated: true;
  50. userId: string;
  51. email?: string | null;
  52. method?: AuthMethod | null;
  53. walletAddress?: string | null;
  54. }
  55. | { authenticated: false };
  56. export async function fetchPortalSession(): Promise<PortalSessionState> {
  57. try {
  58. const res = await fetch("/api/session", { credentials: "include" });
  59. const data = (await res.json()) as {
  60. authenticated?: boolean;
  61. userId?: string;
  62. email?: string | null;
  63. method?: AuthMethod | null;
  64. walletAddress?: string | null;
  65. };
  66. if (data.authenticated && data.userId) {
  67. let email: string | null = data.email ?? null;
  68. let method: AuthMethod | null = data.method ?? null;
  69. let walletAddress: string | null = data.walletAddress ?? null;
  70. if (typeof document !== "undefined") {
  71. const em = document.cookie.match(/(?:^|;\s*)krypco_email=([^;]+)/);
  72. if (!email && em?.[1]) email = decodeURIComponent(em[1]);
  73. const m = document.cookie.match(/(?:^|;\s*)krypco_method=([^;]+)/);
  74. if (!method && m?.[1]) method = decodeURIComponent(m[1]) as AuthMethod;
  75. const w = document.cookie.match(/(?:^|;\s*)krypco_wallet=([^;]+)/);
  76. if (!walletAddress && w?.[1])
  77. walletAddress = decodeURIComponent(w[1]);
  78. }
  79. return {
  80. authenticated: true,
  81. userId: data.userId,
  82. email,
  83. method,
  84. walletAddress,
  85. };
  86. }
  87. return { authenticated: false };
  88. } catch {
  89. return { authenticated: false };
  90. }
  91. }