word-waltz / files / src / utils / shareLink.ts
shareLink.ts
f755bca6 2026-03-23 Pavel Safronov | 1 | /** |
| 2 | * utils/shareLink.ts — URL construction and parsing | |
| 3 | * | |
| 4 | * The encryption key is embedded in the URL fragment (hash) so it is never | |
| 5 | * sent to any server. Format: | |
| 6 | * | |
| 7 | * https://host/game/#gameId=<id>&key=<base64url-key> | |
| 8 | * | |
| 9 | * The fragment is parsed on the client to extract both values. | |
| 10 | */ | |
| 11 | ||
94a747e4 2026-03-24 Pavel Safronov | 12 | |
| 13 | function shareBase(): string { | |
| 14 | return window.location.origin + window.location.pathname; | |
| 15 | } | |
| 16 | ||
f755bca6 2026-03-23 Pavel Safronov | 17 | /** |
| 18 | * Build a shareable game URL. | |
| 19 | */ | |
| 20 | export function buildLink( | |
| 21 | gameId: string, | |
| 22 | base64urlKey: string, | |
4a3e918a 2026-03-26 Pavel Safronov | 23 | role?: 'a' | 'b', |
94a747e4 2026-03-24 Pavel Safronov | 24 | base: string = shareBase(), |
f755bca6 2026-03-23 Pavel Safronov | 25 | ): string { |
4a3e918a 2026-03-26 Pavel Safronov | 26 | const params: Record<string, string> = { gameId, key: base64urlKey }; |
| 27 | if (role) params.role = role; | |
| 28 | const fragment = new URLSearchParams(params).toString(); | |
f755bca6 2026-03-23 Pavel Safronov | 29 | return `${base}#${fragment}`; |
| 30 | } | |
| 31 | ||
4a3e918a 2026-03-26 Pavel Safronov | 32 | /** Parse a game URL fragment to extract gameId, key, and optional role. */ |
f755bca6 2026-03-23 Pavel Safronov | 33 | export function parseLink(url: string = window.location.hash): { |
| 34 | gameId: string | null; | |
| 35 | key: string | null; | |
4a3e918a 2026-03-26 Pavel Safronov | 36 | role: 'a' | 'b' | null; |
f755bca6 2026-03-23 Pavel Safronov | 37 | } { |
| 38 | const fragment = url.startsWith('#') ? url.slice(1) : url; | |
| 39 | const params = new URLSearchParams(fragment); | |
4a3e918a 2026-03-26 Pavel Safronov | 40 | const role = params.get('role'); |
f755bca6 2026-03-23 Pavel Safronov | 41 | return { |
| 42 | gameId: params.get('gameId'), | |
| 43 | key: params.get('key'), | |
4a3e918a 2026-03-26 Pavel Safronov | 44 | role: role === 'a' || role === 'b' ? role : null, |
f755bca6 2026-03-23 Pavel Safronov | 45 | }; |
| 46 | } |