import type { AuthUser } from '../../types.js'; import type { CsrfClientOptions } from '../csrf.js'; export interface AuthStoreConfig { apiPath?: string; /** * CSRF cookie/header names. Only needed when the server overrides the * defaults via `config.csrf.cookieName`/`headerName`. Omit to use the * package defaults. Mutating requests echo the CSRF token automatically; * when no token cookie exists the request is sent unchanged (origin-only * mode keeps working). */ csrf?: CsrfClientOptions; /** * Custom fetch implementation for all API calls. Defaults to the global * `fetch`. Useful for mock backends in demos/tests or custom retry layers — * the same injection point every component exposes. */ fetcher?: typeof globalThis.fetch; } /** * Outcome of a store action. On failure it carries the server's wire contract * — machine `code` plus English `error` prose — instead of a hardcoded string, * so a consumer localizes it exactly like the components do: * * ```ts * const result = await auth.login(email, password); * if (!result.success) message = errorMessageFromCode(result.code, t, result.error) ?? t.common.error; * ``` * * A request that never reached the server yields the client-synthesized * `code: 'network_error'` (mapped to `auth.errors.networkError`). */ export interface AuthActionResult { success: boolean; /** English server prose (the `error` field of the wire contract), if any. */ error?: string; /** Machine error code (`AuthErrorCode` or the client-side `network_error`). */ code?: string; twoFactorRequired?: boolean; } /** * Runes store for session state (`user`, `isAuthenticated`, `loading`) plus the * five auth actions, for consumers that build their own forms or need the * session across routes (a layout guard, a header menu). Its routes are the * same handlers the pre-built pages call — `POST {apiPath}/login`, * `/register`, `/logout`, `/2fa/verify`, `GET {apiPath}/me`. * * The pages (`LoginPage`, `RegisterPage`) do **not** instantiate this store. * They own no session: they render a form, call the endpoint through the same * request core (`postJson` in `utils/http.ts` — one implementation of fetch, * CSRF and body parsing) and report `onSuccess`, leaving `user` to whichever * store the consumer holds. A second store inside a page would be state nobody * reads, disagreeing with the consumer's until its next `checkStatus()`. What * each side does with the parsed body is its own — the one rule both apply is * that a success status without `user` is not a success. */ export declare function createAuthStore(config?: AuthStoreConfig): { readonly user: AuthUser | null; readonly loading: boolean; readonly isAuthenticated: boolean; readonly twoFactorRequired: boolean; login: (email: string, password: string) => Promise>; register: (name: string, email: string, password: string, token: string) => Promise>; logout: () => Promise>; checkStatus: () => Promise>; verifyTwoFactor: (code: string) => Promise>; };