@daveyplate/better-auth-ui
Version:
Plug & play shadcn/ui components for better-auth
107 lines (95 loc) • 3.18 kB
text/typescript
import { type ClassValue, clsx } from "clsx"
import { twMerge } from "tailwind-merge"
import * as z from "zod"
import type { AuthLocalization } from "../localization/auth-localization"
import type { PasswordValidation } from "../types/password-validation"
import type { AuthView, AuthViewPaths } from "./auth-view-paths"
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs))
}
export function isValidEmail(email: string) {
const emailRegex: RegExp = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
return emailRegex.test(email)
}
/**
* Converts error codes from SNAKE_CASE to camelCase
* Example: INVALID_TWO_FACTOR_COOKIE -> invalidTwoFactorCookie
*/
export function errorCodeToCamelCase(errorCode: string): string {
return errorCode
.toLowerCase()
.replace(/_([a-z])/g, (_, char) => char.toUpperCase())
}
/**
* Gets a localized error message from an error object
*/
export function getLocalizedError({
error,
localization
}: {
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
error: any
localization?: Partial<AuthLocalization>
}) {
if (typeof error === "string") {
if (localization?.[error as keyof AuthLocalization])
return localization[error as keyof AuthLocalization]
}
if (error?.error) {
if (error.error.code) {
const errorCode = error.error.code as keyof AuthLocalization
if (localization?.[errorCode]) return localization[errorCode]
}
return (
error.error.message ||
error.error.code ||
error.error.statusText ||
localization?.REQUEST_FAILED
)
}
return error?.message || localization?.REQUEST_FAILED || "Request failed"
}
export function getSearchParam(paramName: string) {
return typeof window !== "undefined"
? new URLSearchParams(window.location.search).get(paramName)
: null
}
export function getAuthViewByPath(authViewPaths: AuthViewPaths, path?: string) {
for (const authViewPathsKey in authViewPaths) {
if (authViewPaths[authViewPathsKey as AuthView] === path) {
return authViewPathsKey as AuthView
}
}
}
export function getKeyByValue<T extends Record<string, unknown>>(
object: T,
value?: T[keyof T]
): keyof T | undefined {
return (Object.keys(object) as Array<keyof T>).find(
(key) => object[key] === value
)
}
export function getPasswordSchema(
passwordValidation?: PasswordValidation,
localization?: AuthLocalization
) {
let schema = z.string().min(1, {
message: localization?.PASSWORD_REQUIRED
})
if (passwordValidation?.minLength) {
schema = schema.min(passwordValidation.minLength, {
message: localization?.PASSWORD_TOO_SHORT
})
}
if (passwordValidation?.maxLength) {
schema = schema.max(passwordValidation.maxLength, {
message: localization?.PASSWORD_TOO_LONG
})
}
if (passwordValidation?.regex) {
schema = schema.regex(passwordValidation.regex, {
message: localization?.INVALID_PASSWORD
})
}
return schema
}