first commit
This commit is contained in:
60
docs/ui/react/react-auth/src/lib/better-auth-adapter.md
Normal file
60
docs/ui/react/react-auth/src/lib/better-auth-adapter.md
Normal file
@@ -0,0 +1,60 @@
|
||||
# `better-auth-adapter`
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
|
||||
## Purpose
|
||||
|
||||
`better-auth-adapter.ts` provides the response-narrowing bridge between `better-auth/client` (which returns a `BetterAuthError | BetterAuthData<T>` union with native `Date` timestamps) and the package's internal `User` / `Session` / `AuthResponse` shapes (which carry ISO-string timestamps for serialisation safety). The module exposes two structural type guards (`isBetterAuthError`, `hasBetterAuthData`) that narrow `unknown` to the appropriate branch without `any`, plus four `transform*` functions that map a successful payload onto an internal shape and surface the error branch's message when the call failed. No `any` types appear anywhere — every guard accepts `unknown` and narrows through explicit field checks.
|
||||
|
||||
## Features
|
||||
|
||||
- Two type guards: `isBetterAuthError(unknown)`, `hasBetterAuthData<T>(unknown)`.
|
||||
- Four transforms: `transformSessionResponse`, `transformAuthResponse`, `transformGenericResponse`, `transformUpdateProfileResponse`.
|
||||
- ISO-string normalisation for every `Date` field on the way out.
|
||||
- Robust to `null` / `undefined` / malformed payloads — returns a default with a `message` string when the shape doesn't match.
|
||||
|
||||
## Usage: Basic
|
||||
|
||||
```ts
|
||||
import { transformSessionResponse } from "@suaveplan/react-auth";
|
||||
|
||||
const raw = await client.getSession();
|
||||
const { user, session, error } = transformSessionResponse(raw);
|
||||
```
|
||||
|
||||
## Usage: Advanced
|
||||
|
||||
Chain the guards directly when you need to act differently on each branch:
|
||||
|
||||
```ts
|
||||
import {
|
||||
hasBetterAuthData,
|
||||
isBetterAuthError,
|
||||
transformAuthResponse,
|
||||
} from "@suaveplan/react-auth";
|
||||
|
||||
const raw = await client.signIn({ email, password });
|
||||
if (isBetterAuthError(raw)) {
|
||||
logger.warn({ code: raw.error, message: raw.message }, "sign-in rejected");
|
||||
return;
|
||||
}
|
||||
if (hasBetterAuthData<{ user: unknown }>(raw)) {
|
||||
const out = transformAuthResponse(raw);
|
||||
if (out.user) await persistSession(out.user);
|
||||
}
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
- `function isBetterAuthError(response: unknown): response is { error: string; message: string }`
|
||||
- `function hasBetterAuthData<T = unknown>(response: unknown): response is { data: T }`
|
||||
- `function transformSessionResponse(response: unknown): { session: Session | null; user: User | null; error?: string }`
|
||||
- `function transformAuthResponse(response: unknown): AuthResponse`
|
||||
- `function transformGenericResponse(response: unknown): AuthResponse`
|
||||
- `function transformUpdateProfileResponse(response: unknown): AuthResponse`
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
The two top-level guards use `typeof value === "object" && value !== null` plus structural field checks. They do not use `instanceof` because the underlying client may return plain objects parsed from JSON. The user-shape guard checks `id`, `email`, `emailVerified`, `name`, `createdAt`, and `updatedAt` are present and of the expected primitive class (`Date | string`); the session-shape guard checks `id`, `userId`, and `expiresAt`. When the payload includes a `Date` instance for any timestamp, the transform calls `.toISOString()`; when it's already a string, it is passed through. The `transformUser` helper hard-codes `roles: 0` and `status: 0` because those fields belong to the internal `User` type but are not modelled by better-auth's session payload — call sites that need richer role data must read them from the `Session` row directly (Wave 2 wires this through the form components).
|
||||
Reference in New Issue
Block a user