(function() { var STORAGE_KEY = 'crank_user'; var sessionCache = null; var sessionPromise = null; function isLoginPage() { return /\/html\/login\.html$/.test(window.location.pathname); } function loginUrl() { return (window.APP_BASE || '') + 'html/login.html'; } function homeUrl() { return (window.APP_BASE || '') + 'index.html'; } function clearUserMirror() { sessionCache = null; sessionPromise = null; try { localStorage.removeItem(STORAGE_KEY); } catch (_error) {} } function primaryMembership(session) { return session && session.memberships && session.memberships.length ? session.memberships[0] : null; } function initials(displayName, email) { var source = displayName || email || 'Crank'; return source .split(/\s+/) .filter(Boolean) .slice(0, 2) .map(function(part) { return part.charAt(0).toUpperCase(); }) .join('') || 'CR'; } function persistUserMirror(session) { var membership = primaryMembership(session); var user = { id: session.user.id, name: session.user.display_name, email: session.user.email, role: membership ? String(membership.role || '').replace(/^\w/, function(char) { return char.toUpperCase(); }) : 'Viewer', workspace: membership ? membership.workspace.slug : '', workspaceId: membership ? membership.workspace.id : '', initials: initials(session.user.display_name, session.user.email), }; try { localStorage.setItem(STORAGE_KEY, JSON.stringify(user)); } catch (_error) {} } function replaceSession(session) { sessionCache = session; persistUserMirror(session); return session; } async function fetchSession(force) { if (!force && sessionCache) { return sessionCache; } if (!force && sessionPromise) { return sessionPromise; } sessionPromise = window.CrankApi.getSession() .then(function(session) { return replaceSession(session); }) .catch(function(error) { clearUserMirror(); throw error; }) .finally(function() { sessionPromise = null; }); return sessionPromise; } async function guardProtectedPage() { try { return await fetchSession(false); } catch (error) { if (error && error.status === 401) { window.location.replace(loginUrl()); return null; } throw error; } } async function guardLoginPage() { try { await fetchSession(false); window.location.replace(homeUrl()); } catch (error) { if (!error || error.status !== 401) { throw error; } } } async function login(email, password) { var session = await window.CrankApi.login({ email: email, password: password, }); replaceSession(session); window.location.href = homeUrl(); } async function logout() { try { await window.CrankApi.logout(); } finally { clearUserMirror(); window.location.href = loginUrl(); } } function handleUnauthorized() { if (isLoginPage()) { clearUserMirror(); return; } clearUserMirror(); window.location.replace(loginUrl()); } window.CrankAuth = { fetchSession: fetchSession, replaceSession: replaceSession, guardProtectedPage: guardProtectedPage, guardLoginPage: guardLoginPage, login: login, logout: logout, handleUnauthorized: handleUnauthorized, }; }());