import { useApiLazyQuery, useApiMutation, useApiQuery } from '@ema-platform/api'; export interface MySession { id: string; createdAt: string; email: string; /** IP address the session was created from — IAM sends no user agent. */ device: string; expiryTime: string; refreshCount: number; status: string; } /** `/sessions/my-sessions` answers with a tuple, not the usual `{items, count}`. */ type SessionsResponse = [MySession[], number]; const SESSIONS_URL = '/sessions/my-sessions'; const ORDER_BY = 'CreatedAt:DESC'; function unwrapList(data: unknown): SessionsResponse { if (!Array.isArray(data)) return [[], 0]; const [items, total] = data as Partial; return [items ?? [], total ?? 0]; } /** * The signed-in user's login sessions, and the two ways to end them. * * Uses the generic query/mutation endpoints rather than its own slice, so * freshness comes from `refetch()` rather than cache tags — the same shape as * `useTwoFactor`. */ export function useSessions({ skip, take }: { skip: number; take: number }) { const { data, isFetching, refetch } = useApiQuery({ url: SESSIONS_URL, params: { skip, take, orderBy: ORDER_BY }, }); const [fetchAll] = useApiLazyQuery(); const [send, { isLoading: isRevoking }] = useApiMutation(); const [sessions, total] = unwrapList(data); /** Every session id the user has, not just the ones on the current page. */ const allSessionIds = async (): Promise => { // `total` is one page stale at worst; ask for a page big enough to cover it // growing between render and click. const result = await fetchAll({ url: SESSIONS_URL, params: { skip: 0, take: Math.max(total, sessions.length) + 20, orderBy: ORDER_BY }, }).unwrap(); return unwrapList(result)[0].map((s) => s.id); }; const revoke = async (ids: string[]) => { if (ids.length === 0) return; await send( ids.length === 1 ? { url: `/sessions/revoke/${ids[0]}`, method: 'DELETE' } : { url: '/sessions/bulk-revoke', method: 'POST', body: { sessionIds: ids } }, ).unwrap(); await refetch(); }; return { sessions, total, isFetching, refetch, revoke, isRevoking, allSessionIds }; }