UNPKG

overcentric

Version:

Overcentric watches your website, product, and users - and tells you what matters and what to do about it.

99 lines (98 loc) 4.03 kB
import { generateUuid } from './identity'; const SESSION_TIMEOUT = 30 * 60 * 1000; // 30 minutes in milliseconds const COOKIE_MAX_AGE = 30 * 60; // 30 minutes in seconds function sessionCookieName(projectId) { return `overcentric_session_id_${projectId}`; } function activityCookieName(projectId) { return `overcentric_session_activity_${projectId}`; } function sessionKey(projectId) { return `overcentric_session_${projectId}`; } function setCrossDomainCookie(name, value, maxAge) { try { const isSecure = window.location.protocol === 'https:'; const secureFlag = isSecure ? '; Secure' : ''; document.cookie = `${name}=${value}; path=/; max-age=${maxAge}; SameSite=Lax${secureFlag}`; try { const domain = window.location.hostname.split('.').slice(-2).join('.'); document.cookie = `${name}=${value}; domain=.${domain}; path=/; max-age=${maxAge}; SameSite=Lax${secureFlag}`; } catch (e) { console.debug('Could not set cookie on parent domain'); } } catch (e) { console.warn(`Failed to set ${name} cookie:`, e); } } function getCookie(name) { var _a, _b; try { const value = (_b = (_a = document.cookie .split('; ') .find(row => row.startsWith(`${name}=`))) === null || _a === void 0 ? void 0 : _a.split('=')) === null || _b === void 0 ? void 0 : _b[1]; return value || null; } catch (e) { console.warn(`Failed to get ${name} cookie:`, e); return null; } } /** * Get or create a session ID scoped to the given project. */ export function getSessionId(projectId) { const now = Date.now(); const SESSION_COOKIE_NAME = sessionCookieName(projectId); const ACTIVITY_COOKIE_NAME = activityCookieName(projectId); const SESSION_KEY = sessionKey(projectId); const storedSessionId = getCookie(SESSION_COOKIE_NAME); const lastActivityStr = getCookie(ACTIVITY_COOKIE_NAME); const lastActivity = lastActivityStr ? parseInt(lastActivityStr, 10) : 0; if (storedSessionId && lastActivity && (now - lastActivity) < SESSION_TIMEOUT) { setCrossDomainCookie(ACTIVITY_COOKIE_NAME, String(now), COOKIE_MAX_AGE); return storedSessionId; } // Fallback: Try localStorage for backward compatibility const stored = localStorage.getItem(SESSION_KEY); if (stored) { try { const session = JSON.parse(stored); if ((now - session.lastActivity) < SESSION_TIMEOUT) { setCrossDomainCookie(SESSION_COOKIE_NAME, session.id, COOKIE_MAX_AGE); setCrossDomainCookie(ACTIVITY_COOKIE_NAME, String(now), COOKIE_MAX_AGE); session.lastActivity = now; localStorage.setItem(SESSION_KEY, JSON.stringify(session)); return session.id; } } catch (error) { console.error('Error parsing stored session:', error); } } const newId = generateUuid(); setCrossDomainCookie(SESSION_COOKIE_NAME, newId, COOKIE_MAX_AGE); setCrossDomainCookie(ACTIVITY_COOKIE_NAME, String(now), COOKIE_MAX_AGE); const newSession = { id: newId, lastActivity: now }; localStorage.setItem(SESSION_KEY, JSON.stringify(newSession)); return newId; } /** * Update the last activity timestamp for the current session. */ export function updateSessionActivity(projectId) { const now = Date.now(); const ACTIVITY_COOKIE_NAME = activityCookieName(projectId); const SESSION_KEY = sessionKey(projectId); setCrossDomainCookie(ACTIVITY_COOKIE_NAME, String(now), COOKIE_MAX_AGE); const stored = localStorage.getItem(SESSION_KEY); if (stored) { try { const session = JSON.parse(stored); session.lastActivity = now; localStorage.setItem(SESSION_KEY, JSON.stringify(session)); } catch (error) { console.error('Error updating session activity:', error); } } }