1/* M8: token estafet disimpan di perangkat pemiliknya, bukan di state sesi dan
2 bukan di server (hanya hash-nya yang ada di basis data). Kuncinya per id
3 estafet, dan nilainya memuat peran sekaligus, supaya satu perangkat bisa
4 mengenali dirinya sebagai pembuat atau teman pada link yang sama.
5
6 Pola dan pemakaian localStorage mengikuti features/share/stripToken.ts. */
7
8const KEY_PREFIX = "snapme:relay-token:"
9
10interface StoredRelayToken {
11 role: "host" | "guest"
12 token: string
13}
14
15export function saveRelayToken(
16 id: string,
17 role: StoredRelayToken["role"],
18 token: string
19): void {
20 if (typeof window === "undefined") {
21 return
22 }
23 try {
24 window.localStorage.setItem(
25 KEY_PREFIX + id,
26 JSON.stringify({ role, token } satisfies StoredRelayToken)
27 )
28 } catch {
29 /* Mode privat: estafet tetap jalan, hanya tidak bisa dilanjutkan dari
30 perangkat ini setelah halaman ditutup. */
31 }
32}
33
34export function readRelayToken(id: string): StoredRelayToken | null {
35 return parseRelayToken(rawRelayToken(id))
36}
37
38/** Nilai mentah dari localStorage. Dipakai sebagai snapshot
39 * `useSyncExternalStore`: identitasnya stabil selama isinya tidak berubah,
40 * sedangkan objek hasil parse selalu baru dan akan memicu render tanpa henti. */
41export function rawRelayToken(id: string): string | null {
42 if (typeof window === "undefined") {
43 return null
44 }
45 try {
46 return window.localStorage.getItem(KEY_PREFIX + id)
47 } catch {
48 return null
49 }
50}
51
52export function parseRelayToken(raw: string | null): StoredRelayToken | null {
53 if (raw === null) {
54 return null
55 }
56 try {
57 const parsed: unknown = JSON.parse(raw)
58 if (typeof parsed !== "object" || parsed === null) {
59 return null
60 }
61 const value = parsed as Record<string, unknown>
62 if (
63 (value.role !== "host" && value.role !== "guest") ||
64 typeof value.token !== "string" ||
65 value.token === ""
66 ) {
67 return null
68 }
69 return { role: value.role, token: value.token }
70 } catch {
71 return null
72 }
73}
74
75export function clearRelayToken(id: string): void {
76 if (typeof window === "undefined") {
77 return
78 }
79 try {
80 window.localStorage.removeItem(KEY_PREFIX + id)
81 } catch {
82 /* Tidak ada yang bisa dihapus. */
83 }
84}
85