/** Shared auth cookies so storefront + customer.{domain} share one login. */ export const SHARED_ACCESS_TOKEN_KEY = "meshkee_customer_access_token"; export const SHARED_REFRESH_TOKEN_KEY = "meshkee_customer_refresh_token"; const CHUNK_SIZE = 2800; const MAX_CHUNKS = 24; function cookieDomain(): string | undefined { if (typeof window === "undefined") return undefined; const host = window.location.hostname.toLowerCase(); if (host === "localhost" || host === "127.0.0.1") return undefined; const parts = host.split(".").filter(Boolean); if (parts.length < 2) return undefined; return `.${parts.slice(-2).join(".")}`; } function readRawCookie(name: string): string | null { if (typeof document === "undefined") return null; const prefix = `${name}=`; const match = document.cookie.split("; ").find((row) => row.startsWith(prefix)); if (!match) return null; return match.slice(prefix.length); } function writeRawCookie(name: string, value: string | null) { if (typeof document === "undefined") return; const domain = cookieDomain(); if (value == null) { let cookie = `${name}=; path=/; max-age=0; SameSite=Lax`; if (domain) cookie += `; domain=${domain}`; document.cookie = cookie; return; } const maxAge = 60 * 60 * 24 * 30; let cookie = `${name}=${value}; path=/; max-age=${maxAge}; SameSite=Lax`; if (domain) cookie += `; domain=${domain}`; document.cookie = cookie; } function clearChunkedCookie(name: string) { writeRawCookie(name, null); const n = Number(readRawCookie(`${name}_n`) || "0"); writeRawCookie(`${name}_n`, null); for (let i = 0; i < Math.max(n, MAX_CHUNKS); i++) { writeRawCookie(`${name}_${i}`, null); } } function writeCookie(name: string, value: string | null) { clearChunkedCookie(name); if (value == null || value === "") return; const encoded = encodeURIComponent(value); if (encoded.length <= 3500) { writeRawCookie(name, encoded); return; } const chunks: string[] = []; for (let i = 0; i < encoded.length; i += CHUNK_SIZE) { chunks.push(encoded.slice(i, i + CHUNK_SIZE)); } writeRawCookie(`${name}_n`, String(chunks.length)); chunks.forEach((chunk, i) => writeRawCookie(`${name}_${i}`, chunk)); } function readCookie(name: string): string | null { const n = Number(readRawCookie(`${name}_n`) || "0"); if (n > 0) { let encoded = ""; for (let i = 0; i < n; i++) { const part = readRawCookie(`${name}_${i}`); if (part == null) return null; encoded += part; } try { return decodeURIComponent(encoded); } catch { return null; } } const raw = readRawCookie(name); if (raw == null) return null; try { return decodeURIComponent(raw); } catch { return null; } } export function writeSharedAuthCookies(accessToken: string, refreshToken?: string) { writeCookie(SHARED_ACCESS_TOKEN_KEY, accessToken); if (refreshToken) writeCookie(SHARED_REFRESH_TOKEN_KEY, refreshToken); } export function clearSharedAuthCookies() { writeCookie(SHARED_ACCESS_TOKEN_KEY, null); writeCookie(SHARED_REFRESH_TOKEN_KEY, null); } export function readSharedAccessToken(): string | null { return readCookie(SHARED_ACCESS_TOKEN_KEY); } export function readSharedRefreshToken(): string | null { return readCookie(SHARED_REFRESH_TOKEN_KEY); } export function hydrateLocalTokensFromSharedCookies( accessKey = SHARED_ACCESS_TOKEN_KEY, refreshKey = SHARED_REFRESH_TOKEN_KEY, ): boolean { if (typeof window === "undefined") return false; if (localStorage.getItem(accessKey)) return false; const access = readSharedAccessToken(); if (!access) return false; localStorage.setItem(accessKey, access); const refresh = readSharedRefreshToken(); if (refresh) localStorage.setItem(refreshKey, refresh); return true; }