Skip to content
Source
Sign inSign up

managedAuth.tsx

71 lines2.5 KB

1import { useClerk } from "@clerk/react";
2import {
3 createCloudAccountService,
4 ManagedRelay,
5 setManagedRelaySession,
6} from "@t3tools/client-runtime/relay";
7import {
8 reportAtomCommandResult,
9 runAtomCommand,
10 settleAsyncResult,
11} from "@t3tools/client-runtime/state/runtime";
12import * as Effect from "effect/Effect";
13import { useEffect, type ReactNode } from "react";
14​
15import { environmentCatalog } from "../connection/catalog";
16import { runtime } from "../lib/runtime";
17import { appAtomRegistry } from "../rpc/atomRegistry";
18import { resolveRelayClerkTokenOptions } from "./publicConfig";
19​
20export function deactivateManagedRelayAuthentication(): void {
21 setManagedRelaySession(appAtomRegistry, null);
23​
24export function activateManagedRelayAuthentication(
25 accountId: string,
26 readClerkToken: () => Promise<string | null>,
27): void {
28 setManagedRelaySession(appAtomRegistry, {
29 accountId,
30 readClerkToken,
31 });
33​
34type ClerkInstance = ReturnType<typeof useClerk>;
35​
36function clerkTokenReader(clerk: ClerkInstance): () => Promise<string | null> {
37 return async () =>
38 clerk.session ? await clerk.session.getToken(resolveRelayClerkTokenOptions()) : null;
40​
41const managedRelayAccountService = createCloudAccountService<ClerkInstance>({
42 deactivate: deactivateManagedRelayAuthentication,
43 detach: deactivateManagedRelayAuthentication,
44 cleanUp: async () => {
45 const results = await Promise.all([
46 runAtomCommand(appAtomRegistry, environmentCatalog.removeRelayEnvironments, undefined, {
47 reportFailure: false,
48 reportDefect: false,
49 }),
50 settleAsyncResult(() =>
51 runtime.runPromiseExit(
52 ManagedRelay.ManagedRelayClient.pipe(Effect.flatMap((client) => client.resetTokenCache)),
53 ),
54 ),
55 ]);
56 for (const result of results) {
57 reportAtomCommandResult(result, { label: "cloud account cleanup" });
58 }
59 },
60 activate: ({ source, accountId }) =>
61 activateManagedRelayAuthentication(accountId, clerkTokenReader(source)),
62});
63​
64export function ManagedRelayAuthProvider({ children }: { readonly children: ReactNode }) {
65 // ClerkProvider creates the Clerk instance and owns its lifetime, so the
66 // account service observes it for as long as this provider is mounted.
67 const clerk = useClerk();
68 // oxlint-disable-next-line t3code/no-unreasoned-state-sync -- attaches the Clerk instance to the managed relay account service for the provider's lifetime
69 useEffect(() => managedRelayAccountService.attach(clerk), [clerk]);
70 return children;