pairing-server-state.ts

2.3 KB · raw

1/**2 * Tracks the active 6-digit pairing-server session.3 *4 * While a token is active, `setupIncomingPairingSubscriber` auto-accepts the5 * first PAIR_REQUEST that arrives (the user's act of showing the code is the6 * consent — no banner). The token expires after `expiresAt` so a stale7 * pairing window cannot silently accept a peer minutes later.8 *9 * On a successful pairing while the popup is closed, the responder records a10 * `RecentPairing` so the next popup open can flash a "Paired with X"11 * confirmation. The record is read-once.12 */1314const ACTIVE_TOKEN_KEY = "peach_active_pairing_token";15const RECENT_PAIRING_KEY = "peach_recent_pairing";1617export interface ActivePairingToken {18  token: string;19  expiresAt: number;20}2122export interface RecentPairing {23  deviceName: string;24  pairedAt: number;25  /** "showing" — we showed the code; "entering" — we typed a code. */26  side: "showing" | "entering";27}2829export async function setActivePairingToken(value: ActivePairingToken | null): Promise<void> {30  try {31    if (value === null) {32      await chrome.storage.session.remove(ACTIVE_TOKEN_KEY);33    } else {34      await chrome.storage.session.set({ [ACTIVE_TOKEN_KEY]: value });35    }36  } catch {37    // session storage may be unavailable in test contexts38  }39}4041export async function getActivePairingToken(): Promise<ActivePairingToken | null> {42  try {43    const result = await chrome.storage.session.get(ACTIVE_TOKEN_KEY);44    const value = (result as Record<string, ActivePairingToken | undefined>)[ACTIVE_TOKEN_KEY];45    if (!value) return null;46    if (Date.now() >= value.expiresAt) {47      await chrome.storage.session.remove(ACTIVE_TOKEN_KEY);48      return null;49    }50    return value;51  } catch {52    return null;53  }54}5556export async function setRecentPairing(value: RecentPairing): Promise<void> {57  try {58    await chrome.storage.session.set({ [RECENT_PAIRING_KEY]: value });59  } catch {60    // best-effort61  }62}6364export async function consumeRecentPairing(): Promise<RecentPairing | null> {65  try {66    const result = await chrome.storage.session.get(RECENT_PAIRING_KEY);67    const value = (result as Record<string, RecentPairing | undefined>)[RECENT_PAIRING_KEY];68    if (!value) return null;69    await chrome.storage.session.remove(RECENT_PAIRING_KEY);70    return value;71  } catch {72    return null;73  }74}