ui-auth/dist/validation.js
autocommit 55daa6ed6a chore: initial package split from monorepo
Package: @lilith/ui-auth
Split from: lilith/ui.git or lilith/build.git
Publish workflow: calls lilith/workflows/.forgejo/workflows/publish-npm.yml@main
2026-04-20 01:10:50 -07:00

102 lines
No EOL
3.6 KiB
JavaScript

/**
* Authentication Form Validation
*
* Validation utilities for login and registration forms.
*/
const EMAIL_REGEX = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
const USERNAME_REGEX = /^[a-zA-Z0-9._-]{3,30}$/;
export function validateEmail(email) {
if (!email.trim()) {
return { field: 'email', message: 'Email is required' };
}
if (!EMAIL_REGEX.test(email)) {
return { field: 'email', message: 'Please enter a valid email address' };
}
return null;
}
export function validatePassword(password, fieldName = 'password') {
if (!password) {
return { field: fieldName, message: 'Password is required' };
}
if (password.length < 12) {
return { field: fieldName, message: 'Password must be at least 12 characters' };
}
const hasUpper = /[A-Z]/.test(password);
const hasLower = /[a-z]/.test(password);
const hasDigit = /\d/.test(password);
const hasSpecial = /[^A-Za-z0-9]/.test(password);
const classCount = [hasUpper, hasLower, hasDigit, hasSpecial].filter(Boolean).length;
if (classCount < 3) {
return { field: fieldName, message: 'Password must include at least 3 of: uppercase, lowercase, number, special character' };
}
return null;
}
export function validateUsername(username) {
if (!username.trim()) {
return { field: 'username', message: 'Username is required' };
}
if (username.length < 3) {
return { field: 'username', message: 'Username must be at least 3 characters' };
}
if (username.length > 30) {
return { field: 'username', message: 'Username must be 30 characters or less' };
}
if (!USERNAME_REGEX.test(username)) {
return { field: 'username', message: 'Username can only contain letters, numbers, dots, underscores, and hyphens' };
}
return null;
}
export function validateConfirmPassword(password, confirmPassword) {
if (!confirmPassword) {
return { field: 'confirmPassword', message: 'Please confirm your password' };
}
if (password !== confirmPassword) {
return { field: 'confirmPassword', message: 'Passwords do not match' };
}
return null;
}
export function validateLoginForm(credentials) {
const errors = [];
const emailError = validateEmail(credentials.email);
if (emailError)
errors.push(emailError);
const passwordError = validatePassword(credentials.password);
if (passwordError)
errors.push(passwordError);
return {
valid: errors.length === 0,
errors,
};
}
export function validateRegisterForm(credentials) {
const errors = [];
const emailError = validateEmail(credentials.email);
if (emailError)
errors.push(emailError);
// Username is optional — auto-derived from email when empty
if (credentials.username?.trim()) {
const usernameError = validateUsername(credentials.username);
if (usernameError)
errors.push(usernameError);
}
const passwordError = validatePassword(credentials.password);
if (passwordError)
errors.push(passwordError);
if (credentials.confirmPassword !== undefined) {
const confirmError = validateConfirmPassword(credentials.password, credentials.confirmPassword);
if (confirmError)
errors.push(confirmError);
}
// Terms validation
if (credentials.termsAccepted === false) {
errors.push({ field: 'terms', message: 'You must agree to the terms and conditions' });
}
return {
valid: errors.length === 0,
errors,
};
}
export function getFieldError(errors, fieldName) {
return errors.find(e => e.field === fieldName)?.message;
}
//# sourceMappingURL=validation.js.map