grain.social is a photo sharing platform built on atproto.
grain.social
atproto
photography
appview
1export async function login(handle: string): Promise<void> {
2 const res = await fetch(`/oauth/login?handle=${encodeURIComponent(handle)}`, {
3 redirect: "manual",
4 });
5 if (res.type === "opaqueredirect") {
6 window.location.href = `/oauth/login?handle=${encodeURIComponent(handle)}`;
7 return;
8 }
9 if (res.ok) return;
10 const body = await res.json().catch(() => ({ error: "Login failed" }));
11 throw new Error(body.error || "Login failed");
12}
13
14export async function createAccount(): Promise<void> {
15 const pds = import.meta.env.DEV ? "localhost:2583" : "selfhosted.social";
16 window.location.href = `/oauth/login?prompt=create&pds=${encodeURIComponent(pds)}`;
17}
18
19export async function logout(): Promise<void> {
20 (globalThis as any).__hatk_viewer = null;
21 await fetch("/auth/logout", { method: "POST" }).catch(() => {});
22}
23
24export function viewerDid(): string | null {
25 if (typeof window === "undefined") return null;
26 const viewer = (globalThis as any).__hatk_viewer;
27 return viewer?.did ?? null;
28}
29
30// Expose viewer for getViewer() bridge
31(globalThis as any).__hatk_auth = { viewerDid };