import { apiRequestData } from "../api/http"; import { verifyEmailLoginCode } from "../api/auth"; import type { LoginRequest, LoginResponse, MeResponse } from "../api/types"; import { getDeviceFingerprint } from "./deviceFingerprint"; const JSON_HEADERS = { "content-type": "application/json", }; const REFRESH_SUCCESS_REPLAY_MS = 1000; let refreshSessionPromise: Promise | null = null; let refreshSessionReplay: { data: LoginResponse; expiresAt: number } | null = null; let refreshSessionGeneration = 0; export function resetRefreshSessionCache() { refreshSessionGeneration += 1; refreshSessionPromise = null; refreshSessionReplay = null; } export async function loginWithPassword(payload: LoginRequest) { resetRefreshSessionCache(); return apiRequestData("/api/auth/login", { method: "POST", auth: false, retryOn401: false, headers: { ...JSON_HEADERS, "x-device-fingerprint": getDeviceFingerprint(), }, body: JSON.stringify(payload), }); } export async function loginWithEmailCode(payload: { email: string; code: string }) { resetRefreshSessionCache(); return verifyEmailLoginCode(payload); } async function requestRefreshSession() { return apiRequestData("/api/auth/refresh", { method: "POST", auth: false, retryOn401: false, headers: { "x-device-fingerprint": getDeviceFingerprint(), }, }); } export async function refreshSession() { const now = Date.now(); if (refreshSessionReplay && refreshSessionReplay.expiresAt > now) { return refreshSessionReplay.data; } if (!refreshSessionPromise) { const generation = refreshSessionGeneration; const requestPromise = requestRefreshSession() .then((data) => { if (generation === refreshSessionGeneration) { refreshSessionReplay = { data, expiresAt: Date.now() + REFRESH_SUCCESS_REPLAY_MS, }; } return data; }) .catch((error: unknown) => { if (generation === refreshSessionGeneration) { refreshSessionReplay = null; } throw error; }); refreshSessionPromise = requestPromise; void requestPromise .finally(() => { if (refreshSessionPromise === requestPromise) { refreshSessionPromise = null; } }) .catch(() => undefined); } return refreshSessionPromise; } export async function logoutSession() { try { return await apiRequestData>("/api/auth/logout", { method: "POST", auth: false, retryOn401: false, }); } finally { resetRefreshSessionCache(); } } export async function fetchCurrentEmployee(accessToken: string) { return apiRequestData("/api/me", { auth: true, retryOn401: false, accessTokenOverride: accessToken, }); }