first commit
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
# `<AuthProvider>` and `useAuth` / `useUser` / `useIsAuthenticated`
|
||||
|
||||
## Purpose
|
||||
|
||||
`auth-context.tsx` ships the `<AuthProvider>` React context provider together
|
||||
with the three hooks `useAuth`, `useUser`, and `useIsAuthenticated`. The
|
||||
provider wires a tenant-aware auth backend through an injectable `fetch`
|
||||
(`FetchLike`) and an injectable `navigate(url)` seam so consumers can plug
|
||||
real backends in production and stub them in tests without `vi.mock`. Every
|
||||
verb — `login`, `loginWithProvider`, `register`, `logout`,
|
||||
`requestPasswordReset`, `resetPassword` — is surfaced on the context value
|
||||
returned by `useAuth()` and translates HTTP failures into stable, code-tagged
|
||||
errors via `ReactAuthWhitelabelError`.
|
||||
|
||||
## Features
|
||||
|
||||
- Injectable `fetch: FetchLike` for testability — defaults to
|
||||
`globalThis.fetch`.
|
||||
- Injectable `navigate(url)` seam — defaults to `window.location.href = url`
|
||||
in browsers, no-op in non-browser environments.
|
||||
- Session probe on mount unless `initialUser` is supplied (SSR/hydration).
|
||||
- Network failures → `REACT_AUTH_WL.AUTH_NETWORK_FAILED`.
|
||||
- Non-ok responses → `REACT_AUTH_WL.AUTH_REJECTED` with the backend's
|
||||
`message` field threaded through when present.
|
||||
- Hooks called outside the provider throw
|
||||
`REACT_AUTH_WL.PROVIDER_OUTSIDE_TREE`.
|
||||
|
||||
## Usage: Basic
|
||||
|
||||
```tsx
|
||||
<AuthProvider config={{ authUrl: "/api/auth" }}>
|
||||
<App />
|
||||
</AuthProvider>
|
||||
```
|
||||
|
||||
```tsx
|
||||
const { login, user, isAuthenticated } = useAuth();
|
||||
await login("a@b.c", "pw");
|
||||
```
|
||||
|
||||
## Usage: Advanced
|
||||
|
||||
```tsx
|
||||
const config: AuthConfig = {
|
||||
authUrl: "https://auth.acme.com",
|
||||
redirectUrl: "/dashboard",
|
||||
fetch: customFetch, // testable seam
|
||||
navigate: (url) => router.navigate(url),
|
||||
providers: [{ id: "google", name: "Google" }],
|
||||
};
|
||||
|
||||
<AuthProvider config={config} initialUser={ssrUser}>
|
||||
<Routes>...</Routes>
|
||||
</AuthProvider>
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
- `AuthProvider({ config, initialUser?, children })` — context provider.
|
||||
- `useAuth()` — returns `AuthContextValue` (`user`, `isLoading`,
|
||||
`isAuthenticated`, `error`, `login`, `loginWithProvider`, `register`,
|
||||
`logout`, `requestPasswordReset`, `resetPassword`).
|
||||
- `useUser()` — returns `AuthUser | null`.
|
||||
- `useIsAuthenticated()` — returns `boolean`.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
The session probe in `useEffect` swallows transport errors on purpose — a
|
||||
session check that fails should not surface as a visible error to the user
|
||||
(they simply remain anonymous). Verbs called from the UI translate failures
|
||||
to typed errors AND surface them on the context's `error` state so a single
|
||||
error region can render the current failure without each call site
|
||||
re-implementing the same try/catch. Every verb sets `isLoading` true/false
|
||||
around the network call so consumers can disable submit buttons via
|
||||
`isLoading || isSubmitting`.
|
||||
Reference in New Issue
Block a user