# `better-auth-adapter` _(no submodules)_ ## Purpose `better-auth-adapter.ts` provides the response-narrowing bridge between `better-auth/client` (which returns a `BetterAuthError | BetterAuthData` 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(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(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).