IKHSAN
ENID Baca dalam Bahasa Indonesia

snapme

Public
Branch
master
Latest commit
130fdb828 October 2026

relayToken.ts

Open raw
/* M8: token estafet disimpan di perangkat pemiliknya, bukan di state sesi dan
   bukan di server (hanya hash-nya yang ada di basis data). Kuncinya per id
   estafet, dan nilainya memuat peran sekaligus, supaya satu perangkat bisa
   mengenali dirinya sebagai pembuat atau teman pada link yang sama.

   Pola dan pemakaian localStorage mengikuti features/share/stripToken.ts. */

const KEY_PREFIX = "snapme:relay-token:"

interface StoredRelayToken {
  role: "host" | "guest"
  token: string
}

export function saveRelayToken(
  id: string,
  role: StoredRelayToken["role"],
  token: string
): void {
  if (typeof window === "undefined") {
    return
  }
  try {
    window.localStorage.setItem(
      KEY_PREFIX + id,
      JSON.stringify({ role, token } satisfies StoredRelayToken)
    )
  } catch {
    /* Mode privat: estafet tetap jalan, hanya tidak bisa dilanjutkan dari
       perangkat ini setelah halaman ditutup. */
  }
}

export function readRelayToken(id: string): StoredRelayToken | null {
  return parseRelayToken(rawRelayToken(id))
}

/** Nilai mentah dari localStorage. Dipakai sebagai snapshot
 *  `useSyncExternalStore`: identitasnya stabil selama isinya tidak berubah,
 *  sedangkan objek hasil parse selalu baru dan akan memicu render tanpa henti. */
export function rawRelayToken(id: string): string | null {
  if (typeof window === "undefined") {
    return null
  }
  try {
    return window.localStorage.getItem(KEY_PREFIX + id)
  } catch {
    return null
  }
}

export function parseRelayToken(raw: string | null): StoredRelayToken | null {
  if (raw === null) {
    return null
  }
  try {
    const parsed: unknown = JSON.parse(raw)
    if (typeof parsed !== "object" || parsed === null) {
      return null
    }
    const value = parsed as Record<string, unknown>
    if (
      (value.role !== "host" && value.role !== "guest") ||
      typeof value.token !== "string" ||
      value.token === ""
    ) {
      return null
    }
    return { role: value.role, token: value.token }
  } catch {
    return null
  }
}

export function clearRelayToken(id: string): void {
  if (typeof window === "undefined") {
    return
  }
  try {
    window.localStorage.removeItem(KEY_PREFIX + id)
  } catch {
    /* Tidak ada yang bisa dihapus. */
  }
}
bytes
2,270
lines
85
Type
ts
Latest commit
28 October 2026