import { browser } from "$app/environment"; import type { Did } from "@atcute/lexicons/syntax"; const PENDING_LOGIN_KEY = "tangled.pendingLogin"; const PENDING_CALLBACK_KEY = "tangled.pendingCallback"; const PENDING_LOGIN_MAX_AGE_MS = 10 * 60 * 1000; export interface PendingLogin { did: Did; handle: string; returnTo: string; at: number; } export interface PendingCallback { hash: string; login: PendingLogin; } const isPendingLogin = (value: unknown): value is PendingLogin => !!value && typeof value === "object" && typeof (value as PendingLogin).did === "string" && (value as PendingLogin).did.startsWith("did:") && typeof (value as PendingLogin).handle === "string" && typeof (value as PendingLogin).returnTo === "string" && typeof (value as PendingLogin).at === "number"; export const writePendingLogin = (login: Omit): void => { if (!browser) return; localStorage.setItem(PENDING_LOGIN_KEY, JSON.stringify({ ...login, at: Date.now() })); }; export const readPendingLogin = (): PendingLogin | null => { if (!browser) return null; try { const raw = localStorage.getItem(PENDING_LOGIN_KEY); if (!raw) return null; const parsed: unknown = JSON.parse(raw); if (!isPendingLogin(parsed)) return null; if (Date.now() - parsed.at > PENDING_LOGIN_MAX_AGE_MS) return null; return parsed; } catch { return null; } }; export const clearPendingLogin = (): void => { if (!browser) return; localStorage.removeItem(PENDING_LOGIN_KEY); }; export const stashPendingCallback = (callback: PendingCallback): void => { if (!browser) return; sessionStorage.setItem(PENDING_CALLBACK_KEY, JSON.stringify(callback)); }; export const consumePendingCallback = (): PendingCallback | null => { if (!browser) return null; try { const raw = sessionStorage.getItem(PENDING_CALLBACK_KEY); if (!raw) return null; sessionStorage.removeItem(PENDING_CALLBACK_KEY); const parsed: unknown = JSON.parse(raw); if ( !parsed || typeof parsed !== "object" || typeof (parsed as PendingCallback).hash !== "string" || !isPendingLogin((parsed as PendingCallback).login) ) { return null; } return parsed as PendingCallback; } catch { return null; } };