fuzzyworld

word-waltz / files / src / utils / shareLink.ts

shareLink.ts

Blame: the commit that last changed each line · file · history

f755bca6 2026-03-23 Pavel Safronov1/**
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 Safronov12
13function shareBase(): string {
14 return window.location.origin + window.location.pathname;
15}
16
f755bca6 2026-03-23 Pavel Safronov17/**
18 * Build a shareable game URL.
19 */
20export function buildLink(
21 gameId: string,
22 base64urlKey: string,
4a3e918a 2026-03-26 Pavel Safronov23 role?: 'a' | 'b',
94a747e4 2026-03-24 Pavel Safronov24 base: string = shareBase(),
f755bca6 2026-03-23 Pavel Safronov25): string {
4a3e918a 2026-03-26 Pavel Safronov26 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 Safronov29 return `${base}#${fragment}`;
30}
31
4a3e918a 2026-03-26 Pavel Safronov32/** Parse a game URL fragment to extract gameId, key, and optional role. */
f755bca6 2026-03-23 Pavel Safronov33export function parseLink(url: string = window.location.hash): {
34 gameId: string | null;
35 key: string | null;
4a3e918a 2026-03-26 Pavel Safronov36 role: 'a' | 'b' | null;
f755bca6 2026-03-23 Pavel Safronov37} {
38 const fragment = url.startsWith('#') ? url.slice(1) : url;
39 const params = new URLSearchParams(fragment);
4a3e918a 2026-03-26 Pavel Safronov40 const role = params.get('role');
f755bca6 2026-03-23 Pavel Safronov41 return {
42 gameId: params.get('gameId'),
43 key: params.get('key'),
4a3e918a 2026-03-26 Pavel Safronov44 role: role === 'a' || role === 'b' ? role : null,
f755bca6 2026-03-23 Pavel Safronov45 };
46}