import type { Context } from "@wrnexus/core"; import type { AuthEngine } from "./engine.ts"; import type { AuthSession, AuthUser } from "./types.ts"; export type AuthRouteName = | "signIn" | "signUp" | "signOut" | "forgotPassword" | "resetPassword" | "verifyEmail" | "verifyPhone" | "twoFactor" | "sessions" | "passkeys"; const DEFAULT_AUTH_ROUTES: Record = { signIn: "/sign-in", signUp: "/sign-up", signOut: "/api/auth/logout", forgotPassword: "/forgot-password", resetPassword: "/reset-password", verifyEmail: "/verify-email", verifyPhone: "/verify-phone", twoFactor: "/two-factor", sessions: "/account/sessions", passkeys: "/account/passkeys", }; export function authRoute( name: AuthRouteName, options: { basePath?: string; overrides?: Partial> } = {}, ): string { const route = options.overrides?.[name] ?? DEFAULT_AUTH_ROUTES[name]; if (!options.basePath || route.startsWith("http://") || route.startsWith("https://")) return route; return `${options.basePath.replace(/\/$/, "")}/${route.replace(/^\//, "")}`; } export function authSuccess>( data: T, init: ResponseInit = {}, ): Response { return Response.json({ ok: true, ...data }, { status: init.status ?? 200, ...init }); } export function authFailure( code: string, message: string, status = 400, details?: Record, ): Response { return Response.json( { ok: false, error: { code, message, ...(details ? { details } : {}) } }, { status }, ); } export function requireAuthUser(ctx: Context): AuthUser { if (!ctx.user || typeof ctx.user !== "object") { throw new Response("Unauthorized", { status: 401 }); } return ctx.user as AuthUser; } export function optionalAuthUser(ctx: Context): AuthUser | null { return ctx.user && typeof ctx.user === "object" ? (ctx.user as AuthUser) : null; } export async function currentAuthSession( engine: AuthEngine, sessionId: string | undefined, ): Promise { if (!sessionId) return null; const session = await engine.store.findSession(sessionId); return session ?? null; } export function authComponentProps( input: Record, defaults: { color?: string; size?: string; class?: string } = {}, ): Record { return { color: defaults.color ?? "primary", size: defaults.size ?? "md", class: defaults.class ?? "", ...input, }; }