Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 | 8x 8x 8x 10x 1x 1x 1x 1x 2x 2x 2x 2x 2x 1x 1x 1x 1x 1x 1x 1x 1x 2x 8x 8x | "use client";
import { useCallback, useEffect, useState } from "react";
import { createAuthClient } from "better-auth/react";
interface ClientSession {
user: {
id: string;
email: string;
name?: string | null;
};
}
// The better-auth browser client. Points at the /api/auth mount that
// auth-server.ts serves (NextAuth is retired — better-auth owns /api/auth now).
// We build the baseURL from the live origin at call time so it works on
// localhost, preview, and prod without an env var — better-auth only needs the
// origin + basePath.
//
// Adored supports Google login only. There is NO SessionProvider:
// better-auth's useSession is a hook backed by a nanostore, so the old NextAuth
// <SessionProvider> wrapper is gone.
//
// In the browser we use the live origin. During SSR/prerender there is no
// window; better-auth's client still parses baseURL as an absolute URL at
// construction, so we hand it a valid absolute placeholder (never actually
// fetched server-side — these are "use client" call sites). At runtime in the
// browser the origin branch always wins.
const baseURL =
typeof window !== "undefined"
? `${window.location.origin}/api/auth`
: "http://localhost/api/auth";
export const authClient = createAuthClient({
baseURL,
});
export function isClientDevAuthBypassEnabled(): boolean {
return process.env.NODE_ENV === "development" && process.env.NEXT_PUBLIC_AUTH_BYPASS === "1";
}
async function readDevSession(): Promise<ClientSession | null> {
const response = await fetch("/api/users/me");
Iif (!response.ok) return null;
const user = await response.json();
return {
user: {
id: user.id,
email: user.email,
name: user.name,
},
};
}
function useDevSession() {
const [data, setData] = useState<ClientSession | null>(null);
const [isPending, setIsPending] = useState(true);
const [error, setError] = useState<Error | null>(null);
const refetch = useCallback(async () => {
setIsPending(true);
try {
const session = await readDevSession();
setData(session);
setError(null);
return { data: session, error: null };
} catch (err) {
const nextError = err instanceof Error ? err : new Error("Unable to read dev session");
setData(null);
setError(nextError);
return { data: null, error: nextError };
} finally {
setIsPending(false);
}
}, []);
useEffect(() => {
let cancelled = false;
void readDevSession()
.then((session) => {
Iif (cancelled) return;
setData(session);
setError(null);
})
.catch((err) => {
if (cancelled) return;
setData(null);
setError(err instanceof Error ? err : new Error("Unable to read dev session"));
})
.finally(() => {
Eif (!cancelled) setIsPending(false);
});
return () => {
cancelled = true;
};
}, []);
return { data, isPending, error, refetch };
}
// Thin re-exports so call sites import from one place and never reach for the
// old NextAuth react client again.
export const useSession = isClientDevAuthBypassEnabled()
? useDevSession
: authClient.useSession;
export const { signIn, signOut } = authClient;
|