Files
soconnor d057ba208d Add 'apps/mobile/' from commit '5fa30f365f21531094cd4d2045042bb4f1370ac3'
git-subtree-dir: apps/mobile
git-subtree-mainline: 86f8987dff
git-subtree-split: 5fa30f365f
2026-08-16 21:42:59 -04:00

81 lines
1.9 KiB
TypeScript

import { expoClient } from "@better-auth/expo/client";
import { createAuthClient } from "better-auth/react";
import { genericOAuthClient } from "better-auth/client/plugins";
import * as SecureStore from "expo-secure-store";
import {
createContext,
useContext,
useMemo,
type ReactNode,
} from "react";
type AuthClient = ReturnType<typeof createAuthClient>;
async function authFetch(input: RequestInfo | URL, init?: RequestInit) {
try {
return await fetch(input, init);
} catch (error) {
if (error instanceof Error && error.name === "AbortError") {
throw error;
}
return new Response(
JSON.stringify({
message: "Could not connect to the server.",
code: "NETWORK_ERROR",
}),
{
status: 503,
statusText: "Service Unavailable",
headers: { "content-type": "application/json" },
},
);
}
}
function createAppAuthClient(apiUrl: string, storagePrefix: string): AuthClient {
return createAuthClient({
baseURL: apiUrl,
fetchOptions: {
customFetchImpl: authFetch,
},
plugins: [
expoClient({
scheme: "beenvoice",
storagePrefix,
storage: SecureStore,
}),
genericOAuthClient(),
],
});
}
const AuthContext = createContext<AuthClient | null>(null);
export function AuthProvider({
apiUrl,
storagePrefix,
children,
}: {
apiUrl: string;
storagePrefix: string;
children: ReactNode;
}) {
const client = useMemo(
() => createAppAuthClient(apiUrl, storagePrefix),
[apiUrl, storagePrefix],
);
return <AuthContext.Provider value={client}>{children}</AuthContext.Provider>;
}
export function useAuthClient() {
const client = useContext(AuthContext);
if (!client) throw new Error("useAuthClient must be used within AuthProvider");
return client;
}
export function useSession() {
return useAuthClient().useSession();
}