@megacorp-ai/auth-react
v0.5.2
Published
React client for @megacorp-ai/auth: SignIn component, useSession, useRole, ImpersonationBanner
Readme
@megacorp-ai/auth-react
React client for @megacorp-ai/auth: a Better Auth React client preconfigured with the email-OTP and admin plugins, plus a <SignIn /> form, useSession, useRole, and <ImpersonationBanner />. Talks only to /api/auth/* on your origin.
Requires React 19+.
Install
npm install @megacorp-ai/auth-react react react-domUsage
// auth.ts
import { createAuthClient } from "@megacorp-ai/auth-react";
export const authClient = createAuthClient(); // same origin; pass { baseURL } for a separate API hostimport { ImpersonationBanner, SignIn, useRole, useSession } from "@megacorp-ai/auth-react";
import { authClient } from "./auth";
function SignInPage() {
const { refetch } = useSession(authClient);
return (
<SignIn
client={authClient}
initialEmail={new URLSearchParams(location.search).get("email") ?? ""}
onSignedIn={() => refetch().then(() => navigate("/app"))}
classNames={{ form: "stack", error: "error" }}
/>
);
}
function App() {
const { user, isPending, signOut } = useSession(authClient);
const { canInvite } = useRole(authClient);
if (isPending) return null;
if (!user) return <SignInPage />;
return (
<>
<ImpersonationBanner client={authClient} className="banner" />
{canInvite && <InvitePanel />}
<button onClick={() => signOut()}>Sign out</button>
</>
);
}API
createAuthClient({ baseURL? })returns anAuthClient: a sealed, structural view of the Better Auth client exposing exactlyuseSession,signOut,emailOtp.sendVerificationOtp,signIn.emailOtp,admin.impersonateUser, andadmin.stopImpersonating— the complete surface this package's own hooks and components use. The object has more properties on it at runtime (the full Better Auth client), but they are not part of this type or this contract; build custom UI on the hooks/components below instead of reaching past them.useSession(client)returns{ data, user, isPending, error, refetch, signOut }.useRole(client)returns{ roles, isPending, hasRole(...roles), isMegacorpAdmin, isCustomerAdmin, canInvite }.useImpersonation(client)returns{ isImpersonating, start(userId), stop() }, wrapping the admin plugin's impersonate/stop pair with the session refetch each needs.<ImpersonationBanner>is built on it.parseRoles(role)splits the server's role string. Roles aremegacorp_admin,customer_admin,member.<SignIn client initialEmail? onSignedIn? classNames? labels? />renders the two-step email and code form. Unstyled; passclassNamesforroot,form,label,input,button,secondaryButton,error,hint, andlabelsto change copy.createTeamApi({ baseURL? })returns{ list, invite, disable, enable, setRole, audit }for the invite and team endpoints. Failures throwTeamApiErrorwithstatusandcode(CANNOT_CHANGE_OWN_ROLE,CANNOT_DISABLE_SELF,LAST_ADMIN,FORBIDDEN,UNAUTHENTICATED,NOT_FOUND,INVALID_BODY,LOCK_TIMEOUT(503, retry), …).enableresolves{ ok, changed }. Team scope is by role, not organization: acustomer_adminsees every non-staff member in the app.audit({ userId?, limit?, before? })returns{ entries, nextBefore }newest first (passnextBeforeback asbeforefor the next page); staff see everything, acustomer_adminsees only entries about people they may manage.<ImpersonationBanner client className? buttonClassName? onStopped? />shows who is impersonating whom with a stop button. Renders nothing otherwise.
Notes
- Cookies carry the session, so the API must be same-origin or behind a proxy that forwards
/api/auth. In Vite dev, proxy/apito your server withxfwd: true. - Sign-up is disabled server-side. Unknown emails see the same "code sent" screen and receive nothing.
- No analytics or telemetry in this package.
License
MIT
