1import { isDid, isHandle } from "@atcute/lexicons/syntax";
2import { createAuthorizationUrl } from "@atcute/oauth-browser-client";
3import { createSignal } from "solid-js";
4
5interface UseOAuthScopeFlowOptions {
6 onError?: (error: unknown) => void;
7 onRedirecting?: () => void;
8 beforeRedirect?: (account: string) => Promise<void>;
9}
10
11export const useOAuthScopeFlow = (options: UseOAuthScopeFlowOptions = {}) => {
12 const [showScopeSelector, setShowScopeSelector] = createSignal(false);
13 const [pendingAccount, setPendingAccount] = createSignal("");
14 const [shouldForceRedirect, setShouldForceRedirect] = createSignal(false);
15
16 const initiate = (account: string) => {
17 if (!account) return;
18 setPendingAccount(account);
19 setShouldForceRedirect(false);
20 setShowScopeSelector(true);
21 };
22
23 const initiateWithRedirect = (account: string) => {
24 if (!account) return;
25 setPendingAccount(account);
26 setShouldForceRedirect(true);
27 setShowScopeSelector(true);
28 };
29
30 const complete = async (scopeString: string, scopeIds: string) => {
31 try {
32 const account = pendingAccount();
33
34 if (options.beforeRedirect && !shouldForceRedirect()) {
35 try {
36 await options.beforeRedirect(account);
37 setShowScopeSelector(false);
38 return;
39 } catch {}
40 }
41
42 localStorage.setItem("pendingScopes", scopeIds);
43
44 options.onRedirecting?.();
45
46 const authUrl = await createAuthorizationUrl({
47 scope: scopeString,
48 target:
49 isHandle(account) || isDid(account) ?
50 { type: "account", identifier: account }
51 : { type: "pds", serviceUrl: account },
52 });
53
54 await new Promise((resolve) => setTimeout(resolve, 250));
55 location.assign(authUrl);
56 } catch (e) {
57 console.error(e);
58 options.onError?.(e);
59 setShowScopeSelector(false);
60 }
61 };
62
63 const cancel = () => {
64 setShowScopeSelector(false);
65 setPendingAccount("");
66 setShouldForceRedirect(false);
67 };
68
69 return {
70 showScopeSelector,
71 pendingAccount,
72 initiate,
73 initiateWithRedirect,
74 complete,
75 cancel,
76 };
77};