# `auth-context`
_(no submodules)_
## Purpose
`auth-context.tsx` exposes the React Context surface for the auth flow. It defines `AuthContext`, the `AuthProvider` component, and the `useAuth()` hook. The provider owns an `AuthClient` instance (either injected or constructed from `config`) and a state block of `{ user, session, isLoading, isAuthenticated, error }`. On mount (unless `skipInitialCheck` is set) it fetches the current session, normalises it through `transformSessionResponse`, and settles the state. It exposes eleven action callbacks (`signIn`, `signUp`, `signOut`, `updateProfile`, `changePassword`, `forgotPassword`, `resetPassword`, `verifyEmail`, `resendVerificationEmail`, `deleteAccount`, `refreshSession`) — every action wraps `client` calls with loading/error state mutations, re-fetches the session where appropriate, records the corresponding OTel counter, and re-throws on failure so callers can `catch` for form-level UI handling. `useAuth()` outside an `AuthProvider` throws `ReactAuthContextMissingError` so the failure is immediate and typed rather than a downstream `undefined` access.
## Features
- `AuthContext` + `AuthProvider` + `useAuth()` triple.
- 11 typed action callbacks; each settles `isLoading` and surfaces `error` deterministically.
- `skipInitialCheck` flag short-circuits the mount-time session fetch (test surface).
- `onAuthStateChange` callback fires on every state transition (useful for analytics).
- Re-throws action errors so form-level UI can render messages; never silently swallows.
## Usage: Basic
```tsx
import { AuthProvider, useAuth } from "@suaveplan/react-auth";
function Inside() {
const { user, signOut } = useAuth();
return user ? : null;
}
;
```
## Usage: Advanced
Inject a pre-built client and observe state changes:
```tsx
import {
AuthProvider,
createAuthClient,
type AuthState,
} from "@suaveplan/react-auth";
const client = createAuthClient({
baseURL: "https://auth.example.com",
siteDomain: "tenant-a",
});
function onAuthStateChange(state: AuthState) {
analytics.track("auth_state", { authenticated: state.isAuthenticated });
}
{/* ... */}
;
```
## API Reference
- `interface AuthState` — `{ user: User | null; session: Session | null; isLoading: boolean; isAuthenticated: boolean; error: Error | null }`.
- `interface AuthContextValue extends AuthState` — adds `client: AuthClient` plus the 11 action callbacks.
- `interface AuthProviderProps` — `{ children: ReactNode; config: AuthClientConfig; client?: AuthClient; onAuthStateChange?: (state: AuthState) => void; skipInitialCheck?: boolean }`.
- `const AuthContext: React.Context` — context handle.
- `function AuthProvider(props: AuthProviderProps): ReactNode` — wraps children with the context.
- `function useAuth(): AuthContextValue` — reads the context; throws `ReactAuthContextMissingError` when outside an `AuthProvider`.
## Implementation Notes
State is consolidated in a single `useState` block so transitions are atomic — callers never see a half-updated value. Every action wraps its critical section in `try`/`catch`/`finally`-style logic but with explicit `setState` calls rather than a `finally` clause, because the success and failure branches set different sets of fields. Caught values pass through `toError(value)` which wraps non-`Error` throwables so the `error` field is always a real `Error` (this avoids violating biome's `useThrowOnlyError` rule when a downstream surface re-throws from the context). Session fetches go through `timedSessionFetch` which records the wall-clock duration into the `react_auth.session_fetch.duration_ms` histogram with a `success`/`failure` label. The `mounted` ref guards the initial-load effect from setting state after unmount; React 19's `StrictMode` double-mount runs the cleanup before the second mount, so the first effect's `mounted = false` is honoured.