3.4 KiB
better-auth-adapter
(no submodules)
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
Datefield on the way out. - Robust to
null/undefined/ malformed payloads — returns a default with amessagestring when the shape doesn't match.
Usage: Basic
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:
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): AuthResponsefunction transformGenericResponse(response: unknown): AuthResponsefunction 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).