@frank-auth/react
Version:
Flexible and customizable React UI components for Frank Authentication
1 lines • 25.5 kB
Source Map (JSON)
{"version":3,"file":"validation.cjs","sources":["../../../src/utils/validation.ts"],"sourcesContent":["// Validation result interface\nexport interface ValidationResult {\n isValid: boolean;\n error?: string;\n errors?: string[];\n}\n\n// Validation rule interface\nexport type ValidationRule = (value: any) => ValidationResult | Promise<ValidationResult>\n\n// Common validation rules\nexport const required = (message = 'This field is required'): ValidationRule => {\n return (value: any): ValidationResult => {\n const isEmpty = value === null ||\n value === undefined ||\n (typeof value === 'string' && value.trim() === '') ||\n (Array.isArray(value) && value.length === 0);\n\n return {\n isValid: !isEmpty,\n error: isEmpty ? message : undefined,\n };\n };\n};\n\nexport const minLength = (min: number, message?: string): ValidationRule => {\n return (value: string): ValidationResult => {\n const actualMessage = message || `Must be at least ${min} characters`;\n const isValid = typeof value === 'string' && value.length >= min;\n\n return {\n isValid,\n error: isValid ? undefined : actualMessage,\n };\n };\n};\n\nexport const maxLength = (max: number, message?: string): ValidationRule => {\n return (value: string): ValidationResult => {\n const actualMessage = message || `Must be no more than ${max} characters`;\n const isValid = typeof value === 'string' && value.length <= max;\n\n return {\n isValid,\n error: isValid ? undefined : actualMessage,\n };\n };\n};\n\nexport const pattern = (regex: RegExp, message = 'Invalid format'): ValidationRule => {\n return (value: string): ValidationResult => {\n const isValid = typeof value === 'string' && regex.test(value);\n\n return {\n isValid,\n error: isValid ? undefined : message,\n };\n };\n};\n\nexport const email = (message = 'Invalid email address'): ValidationRule => {\n const emailRegex = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;\n\n return (value: string): ValidationResult => {\n if (!value) return { isValid: true }; // Allow empty for optional fields\n\n const isValid = emailRegex.test(value);\n return {\n isValid,\n error: isValid ? undefined : message,\n };\n };\n};\n\nexport const phone = (message = 'Invalid phone number'): ValidationRule => {\n // Basic international phone number regex\n const phoneRegex = /^\\+?[1-9]\\d{1,14}$/;\n\n return (value: string): ValidationResult => {\n if (!value) return { isValid: true }; // Allow empty for optional fields\n\n // Remove all non-digit characters except +\n const cleaned = value.replace(/[^\\d+]/g, '');\n const isValid = phoneRegex.test(cleaned);\n\n return {\n isValid,\n error: isValid ? undefined : message,\n };\n };\n};\n\nexport const username = (message = 'Username must be 3-30 characters and contain only letters, numbers, and underscores'): ValidationRule => {\n const usernameRegex = /^[a-zA-Z0-9_]{3,30}$/;\n\n return (value: string): ValidationResult => {\n if (!value) return { isValid: true }; // Allow empty for optional fields\n\n const isValid = usernameRegex.test(value);\n return {\n isValid,\n error: isValid ? undefined : message,\n };\n };\n};\n\nexport const password = (options: {\n minLength?: number;\n requireUppercase?: boolean;\n requireLowercase?: boolean;\n requireNumbers?: boolean;\n requireSymbols?: boolean;\n message?: string;\n} = {}): ValidationRule => {\n const {\n minLength: min = 8,\n requireUppercase = true,\n requireLowercase = true,\n requireNumbers = true,\n requireSymbols = false,\n message,\n } = options;\n\n return (value: string): ValidationResult => {\n if (!value) return { isValid: true }; // Allow empty for optional fields\n\n const errors: string[] = [];\n\n if (value.length < min) {\n errors.push(`Must be at least ${min} characters long`);\n }\n\n if (requireUppercase && !/[A-Z]/.test(value)) {\n errors.push('Must contain at least one uppercase letter');\n }\n\n if (requireLowercase && !/[a-z]/.test(value)) {\n errors.push('Must contain at least one lowercase letter');\n }\n\n if (requireNumbers && !/\\d/.test(value)) {\n errors.push('Must contain at least one number');\n }\n\n if (requireSymbols && !/[^A-Za-z0-9]/.test(value)) {\n errors.push('Must contain at least one special character');\n }\n\n const isValid = errors.length === 0;\n\n return {\n isValid,\n error: message || (isValid ? undefined : errors[0]),\n errors: errors.length > 0 ? errors : undefined,\n };\n };\n};\n\nexport const confirmPassword = (originalPassword: string, message = 'Passwords do not match'): ValidationRule => {\n return (value: string): ValidationResult => {\n const isValid = value === originalPassword;\n\n return {\n isValid,\n error: isValid ? undefined : message,\n };\n };\n};\n\nexport const url = (message = 'Invalid URL'): ValidationRule => {\n return (value: string): ValidationResult => {\n if (!value) return { isValid: true }; // Allow empty for optional fields\n\n try {\n new URL(value);\n return { isValid: true };\n } catch {\n return {\n isValid: false,\n error: message,\n };\n }\n };\n};\n\nexport const number = (options: {\n min?: number;\n max?: number;\n integer?: boolean;\n message?: string;\n} = {}): ValidationRule => {\n const { min, max, integer = false, message } = options;\n\n return (value: any): ValidationResult => {\n if (value === null || value === undefined || value === '') {\n return { isValid: true }; // Allow empty for optional fields\n }\n\n const num = Number(value);\n\n if (isNaN(num)) {\n return {\n isValid: false,\n error: message || 'Must be a valid number',\n };\n }\n\n if (integer && !Number.isInteger(num)) {\n return {\n isValid: false,\n error: message || 'Must be a whole number',\n };\n }\n\n if (min !== undefined && num < min) {\n return {\n isValid: false,\n error: message || `Must be at least ${min}`,\n };\n }\n\n if (max !== undefined && num > max) {\n return {\n isValid: false,\n error: message || `Must be no more than ${max}`,\n };\n }\n\n return { isValid: true };\n };\n};\n\nexport const oneOf = (options: any[], message?: string): ValidationRule => {\n return (value: any): ValidationResult => {\n if (!value) return { isValid: true }; // Allow empty for optional fields\n\n const isValid = options.includes(value);\n const actualMessage = message || `Must be one of: ${options.join(', ')}`;\n\n return {\n isValid,\n error: isValid ? undefined : actualMessage,\n };\n };\n};\n\nexport const custom = (validator: (value: any) => boolean | string, message = 'Invalid value'): ValidationRule => {\n return (value: any): ValidationResult => {\n const result = validator(value);\n\n if (typeof result === 'boolean') {\n return {\n isValid: result,\n error: result ? undefined : message,\n };\n }\n\n // If validator returns a string, it's an error message\n return {\n isValid: false,\n error: result,\n };\n };\n};\n\nexport const asyncValidation = (validator: (value: any) => Promise<boolean | string>, message = 'Invalid value'): ValidationRule => {\n return async (value: any): Promise<ValidationResult> => {\n try {\n const result = await validator(value);\n\n if (typeof result === 'boolean') {\n return {\n isValid: result,\n error: result ? undefined : message,\n };\n }\n\n // If validator returns a string, it's an error message\n return {\n isValid: false,\n error: result,\n };\n } catch (error) {\n return {\n isValid: false,\n error: error instanceof Error ? error.message : 'Validation failed',\n };\n }\n };\n};\n\n// Combine multiple validation rules\nexport const combine = (...rules: ValidationRule[]): ValidationRule => {\n return async (value: any): Promise<ValidationResult> => {\n for (const rule of rules) {\n const result = await rule(value);\n if (!result.isValid) {\n return result;\n }\n }\n\n return { isValid: true };\n };\n};\n\n// Form validation utilities\nexport interface FormValidationRules {\n [fieldName: string]: ValidationRule | ValidationRule[];\n}\n\nexport interface FormValidationResult {\n isValid: boolean;\n errors: Record<string, string>;\n fieldErrors: Record<string, string[]>;\n}\n\nexport const validateForm = async (\n data: Record<string, any>,\n rules: FormValidationRules\n): Promise<FormValidationResult> => {\n const errors: Record<string, string> = {};\n const fieldErrors: Record<string, string[]> = {};\n\n for (const [fieldName, fieldRules] of Object.entries(rules)) {\n const value = data[fieldName];\n const rulesArray = Array.isArray(fieldRules) ? fieldRules : [fieldRules];\n\n for (const rule of rulesArray) {\n const result = await rule(value);\n\n if (!result.isValid) {\n errors[fieldName] = result.error || 'Invalid value';\n\n if (result.errors) {\n fieldErrors[fieldName] = result.errors;\n } else if (result.error) {\n fieldErrors[fieldName] = [result.error];\n }\n\n break; // Stop at first error for this field\n }\n }\n }\n\n return {\n isValid: Object.keys(errors).length === 0,\n errors,\n fieldErrors,\n };\n};\n\nexport const validateField = async (\n value: any,\n rules: ValidationRule | ValidationRule[]\n): Promise<ValidationResult> => {\n const rulesArray = Array.isArray(rules) ? rules : [rules];\n\n for (const rule of rulesArray) {\n const result = await rule(value);\n if (!result.isValid) {\n return result;\n }\n }\n\n return { isValid: true };\n};\n\n// Specific validation functions for auth forms\nexport const validateSignInForm = async (data: {\n identifier: string;\n password?: string;\n}): Promise<FormValidationResult> => {\n const rules: FormValidationRules = {\n identifier: [\n required('Email or username is required'),\n // Could be email or username, so we don't validate format here\n ],\n };\n\n if (data.password !== undefined) {\n rules.password = required('Password is required');\n }\n\n return validateForm(data, rules);\n};\n\nexport const validateSignUpForm = async (data: {\n emailAddress?: string;\n username?: string;\n password?: string;\n confirmPassword?: string;\n firstName?: string;\n lastName?: string;\n phoneNumber?: string;\n}): Promise<FormValidationResult> => {\n const rules: FormValidationRules = {};\n\n if (data.emailAddress !== undefined) {\n rules.emailAddress = [required('Email is required'), email()];\n }\n\n if (data.username !== undefined) {\n rules.username = [required('Username is required'), username()];\n }\n\n if (data.password !== undefined) {\n rules.password = [required('Password is required'), password()];\n }\n\n if (data.confirmPassword !== undefined) {\n rules.confirmPassword = [\n required('Please confirm your password'),\n confirmPassword(data.password || ''),\n ];\n }\n\n if (data.firstName !== undefined) {\n rules.firstName = [\n required('First name is required'),\n minLength(1),\n maxLength(50),\n ];\n }\n\n if (data.lastName !== undefined) {\n rules.lastName = [\n required('Last name is required'),\n minLength(1),\n maxLength(50),\n ];\n }\n\n if (data.phoneNumber !== undefined) {\n rules.phoneNumber = phone();\n }\n\n return validateForm(data, rules);\n};\n\nexport const validatePasswordResetForm = async (data: {\n emailAddress: string;\n}): Promise<FormValidationResult> => {\n const rules: FormValidationRules = {\n emailAddress: [required('Email is required'), email()],\n };\n\n return validateForm(data, rules);\n};\n\nexport const validatePasswordChangeForm = async (data: {\n currentPassword: string;\n newPassword: string;\n confirmPassword: string;\n}): Promise<FormValidationResult> => {\n const rules: FormValidationRules = {\n currentPassword: required('Current password is required'),\n newPassword: [required('New password is required'), password()],\n confirmPassword: [\n required('Please confirm your new password'),\n confirmPassword(data.newPassword),\n ],\n };\n\n return validateForm(data, rules);\n};\n\nexport const validateProfileForm = async (data: {\n firstName?: string;\n lastName?: string;\n username?: string;\n emailAddress?: string;\n phoneNumber?: string;\n bio?: string;\n website?: string;\n}): Promise<FormValidationResult> => {\n const rules: FormValidationRules = {};\n\n if (data.firstName !== undefined) {\n rules.firstName = [minLength(1), maxLength(50)];\n }\n\n if (data.lastName !== undefined) {\n rules.lastName = [minLength(1), maxLength(50)];\n }\n\n if (data.username !== undefined) {\n rules.username = username();\n }\n\n if (data.emailAddress !== undefined) {\n rules.emailAddress = email();\n }\n\n if (data.phoneNumber !== undefined) {\n rules.phoneNumber = phone();\n }\n\n if (data.bio !== undefined) {\n rules.bio = maxLength(500);\n }\n\n if (data.website !== undefined) {\n rules.website = url();\n }\n\n return validateForm(data, rules);\n};\n\nexport const validateOrganizationForm = async (data: {\n name: string;\n slug?: string;\n description?: string;\n website?: string;\n billingEmail?: string;\n}): Promise<FormValidationResult> => {\n const rules: FormValidationRules = {\n name: [\n required('Organization name is required'),\n minLength(1),\n maxLength(100),\n ],\n };\n\n if (data.slug !== undefined) {\n rules.slug = [\n pattern(/^[a-z0-9-]+$/, 'Slug can only contain lowercase letters, numbers, and hyphens'),\n minLength(3),\n maxLength(50),\n ];\n }\n\n if (data.description !== undefined) {\n rules.description = maxLength(500);\n }\n\n if (data.website !== undefined) {\n rules.website = url();\n }\n\n if (data.billingEmail !== undefined) {\n rules.billingEmail = email();\n }\n\n return validateForm(data, rules);\n};\n\nexport const validateInvitationForm = async (data: {\n emailAddress: string;\n roleId: string;\n customMessage?: string;\n}): Promise<FormValidationResult> => {\n const rules: FormValidationRules = {\n emailAddress: [required('Email is required'), email()],\n roleId: required('Role is required'),\n };\n\n if (data.customMessage !== undefined) {\n rules.customMessage = maxLength(500);\n }\n\n return validateForm(data, rules);\n};\n\n// Utility functions for validation\nexport const isValidEmail = (email: string): boolean => {\n const emailRegex = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;\n return emailRegex.test(email);\n};\n\nexport const isValidPhone = (phone: string): boolean => {\n const phoneRegex = /^\\+?[1-9]\\d{1,14}$/;\n const cleaned = phone.replace(/[^\\d+]/g, '');\n return phoneRegex.test(cleaned);\n};\n\nexport const isValidUsername = (username: string): boolean => {\n const usernameRegex = /^[a-zA-Z0-9_]{3,30}$/;\n return usernameRegex.test(username);\n};\n\nexport const isValidUrl = (url: string): boolean => {\n try {\n new URL(url);\n return true;\n } catch {\n return false;\n }\n};\n\nexport const sanitizeInput = (input: string): string => {\n return input.trim().replace(/[<>]/g, '');\n};\n\nexport const normalizeEmail = (email: string): string => {\n return email.toLowerCase().trim();\n};\n\nexport const normalizePhone = (phone: string): string => {\n return phone.replace(/[^\\d+]/g, '');\n};"],"names":["required","message","value","isEmpty","minLength","min","actualMessage","isValid","maxLength","max","pattern","regex","email","emailRegex","phone","phoneRegex","cleaned","username","usernameRegex","password","options","requireUppercase","requireLowercase","requireNumbers","requireSymbols","errors","confirmPassword","originalPassword","url","number","integer","num","oneOf","custom","validator","result","asyncValidation","error","combine","rules","rule","validateForm","data","fieldErrors","fieldName","fieldRules","rulesArray","validateField","validateSignInForm","validateSignUpForm","validatePasswordResetForm","validatePasswordChangeForm","validateProfileForm","validateOrganizationForm","validateInvitationForm","isValidEmail","isValidPhone","isValidUsername","isValidUrl","sanitizeInput","input","normalizeEmail","normalizePhone"],"mappings":"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"}