sync-storage.ts

3.9 KB · raw

1import type { TrustedNetwork, PairedDevice, IncomingPairingRequest } from '../shared/sync-types';23const TRUSTED_NETWORKS_KEY = 'peach_trusted_networks';4const PAIRED_DEVICES_KEY = 'peach_paired_devices';5const INCOMING_PAIR_KEY = 'peach_incoming_pair';67// ---------------------------------------------------------------------------8// Trusted Networks9// ---------------------------------------------------------------------------1011export async function getTrustedNetworks(): Promise<TrustedNetwork[]> {12  try {13    const result = await chrome.storage.local.get(TRUSTED_NETWORKS_KEY);14    return (result as { peach_trusted_networks?: TrustedNetwork[] })[TRUSTED_NETWORKS_KEY] ?? [];15  } catch {16    return [];17  }18}1920export async function addTrustedNetwork(network: TrustedNetwork): Promise<void> {21  try {22    const networks = await getTrustedNetworks();23    networks.push(network);24    await chrome.storage.local.set({ [TRUSTED_NETWORKS_KEY]: networks });25  } catch (err) {26    throw new Error(`Failed to add trusted network: ${err}`);27  }28}2930export async function removeTrustedNetwork(addedAt: number): Promise<void> {31  try {32    const networks = await getTrustedNetworks();33    const filtered = networks.filter((n) => n.addedAt !== addedAt);34    await chrome.storage.local.set({ [TRUSTED_NETWORKS_KEY]: filtered });35  } catch (err) {36    throw new Error(`Failed to remove trusted network: ${err}`);37  }38}3940// ---------------------------------------------------------------------------41// Paired Devices42// ---------------------------------------------------------------------------4344export async function getPairedDevices(): Promise<PairedDevice[]> {45  try {46    const result = await chrome.storage.local.get(PAIRED_DEVICES_KEY);47    return (result as { peach_paired_devices?: PairedDevice[] })[PAIRED_DEVICES_KEY] ?? [];48  } catch {49    return [];50  }51}5253export async function addPairedDevice(device: PairedDevice): Promise<void> {54  try {55    const devices = await getPairedDevices();56    const exists = devices.some((d) => d.deviceId === device.deviceId);57    if (exists) throw new Error(`Device ${device.deviceId} is already paired`);58    devices.push(device);59    await chrome.storage.local.set({ [PAIRED_DEVICES_KEY]: devices });60  } catch (err) {61    throw new Error(`Failed to add paired device: ${err}`);62  }63}6465export async function removePairedDevice(deviceId: string): Promise<void> {66  try {67    const devices = await getPairedDevices();68    const filtered = devices.filter((d) => d.deviceId !== deviceId);69    await chrome.storage.local.set({ [PAIRED_DEVICES_KEY]: filtered });70  } catch (err) {71    throw new Error(`Failed to remove paired device: ${err}`);72  }73}7475// ---------------------------------------------------------------------------76// Incoming Pairing Request77//78// Stored in session storage so the request disappears when the browser closes79// and never lands on disk. The 60-second expiry is enforced by the consumer80// (`getIncomingPairingRequest` returns null past expiry and clears storage).81// ---------------------------------------------------------------------------8283export async function setIncomingPairingRequest(84  request: IncomingPairingRequest85): Promise<void> {86  await chrome.storage.session.set({ [INCOMING_PAIR_KEY]: request });87}8889export async function getIncomingPairingRequest(): Promise<IncomingPairingRequest | null> {90  try {91    const result = await chrome.storage.session.get(INCOMING_PAIR_KEY);92    const request = (result as { peach_incoming_pair?: IncomingPairingRequest })[INCOMING_PAIR_KEY];93    if (!request) return null;94    if (Date.now() >= request.expiresAt) {95      await clearIncomingPairingRequest();96      return null;97    }98    return request;99  } catch {100    return null;101  }102}103104export async function clearIncomingPairingRequest(): Promise<void> {105  try {106    await chrome.storage.session.remove(INCOMING_PAIR_KEY);107  } catch {108    // session storage may be unavailable in some contexts; safe to ignore.109  }110}