TypeScript 97.4%
SQL 1%
JavaScript 0.9%
CSS 0.6%
1/** Shape of the error object returned by the Better Auth client (`{ data, error }`). */2export interface AuthClientError {3 code?: string;4 message?: string;5 status?: number;6 statusText?: string;7}89export const GENERIC_ERROR = "Something went wrong on our side. Please try again in a moment.";1011/** Map Better Auth error codes to short, human, provider-agnostic messages. Never leaks raw server text. */12export function humanAuthError(error: AuthClientError | null | undefined, context: "login" | "signup" | "reset" | "forgot" | "verify" = "login"): string {13 if (!error) return GENERIC_ERROR;14 if (error.status === 429) return "Too many attempts. Please wait a minute and try again.";15 switch (error.code) {16 case "INVALID_EMAIL_OR_PASSWORD":17 case "INVALID_PASSWORD":18 case "USER_NOT_FOUND":19 return context === "login" ? "That email and password don't match." : "We couldn't find an account for that email.";20 case "INVALID_EMAIL":21 return "That doesn't look like a valid email address.";22 case "EMAIL_NOT_VERIFIED":23 return "Please verify your email before signing in.";24 case "USER_ALREADY_EXISTS":25 case "USER_ALREADY_EXISTS_USE_ANOTHER_EMAIL":26 return "An account with this email already exists. Try signing in instead.";27 case "PASSWORD_TOO_SHORT":28 return "Your password must be at least 10 characters.";29 case "PASSWORD_TOO_LONG":30 return "Your password must be 128 characters or fewer.";31 case "INVALID_TOKEN":32 return context === "verify" ? "This verification link is invalid or has already been used." : "This reset link is invalid or has already been used. Request a new one.";33 case "TOKEN_EXPIRED":34 return context === "verify" ? "This verification link has expired. Request a new one below." : "This reset link has expired. Request a new one.";35 case "FAILED_TO_CREATE_USER":36 case "FAILED_TO_CREATE_SESSION":37 case "FAILED_TO_UPDATE_USER":38 return GENERIC_ERROR;39 default:40 if (error.status && error.status >= 500) return GENERIC_ERROR;41 if (error.status === 0 || error.status === undefined) return "We couldn't reach the server. Check your connection and try again.";42 return GENERIC_ERROR;43 }44}4546export function isValidEmail(email: string): boolean {47 return /^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/.test(email.trim());48}4950export const PASSWORD_MIN = 10;51export const PASSWORD_MAX = 128;5253export function passwordLengthError(pw: string): string | null {54 if (pw.length < PASSWORD_MIN) return `Use at least ${PASSWORD_MIN} characters.`;55 if (pw.length > PASSWORD_MAX) return `Use at most ${PASSWORD_MAX} characters.`;56 return null;57}5859/** Only allow same-origin relative paths for post-login redirects. */60export function safeNext(next: string | string[] | undefined): string {61 const v = Array.isArray(next) ? next[0] : next;62 if (!v || !v.startsWith("/") || v.startsWith("//") || v.startsWith("/\\")) return "/app/chat";63 if (v.startsWith("/login") || v.startsWith("/signup")) return "/app/chat";64 return v;65}66