formix_validators 0.1.0
formix_validators: ^0.1.0 copied to clipboard
Built-in validation rules for the Formix ecosystem. Includes validators for strings, numbers, dates, collections, phone numbers, and files.
formix_validators #
Built-in validation rules for the Formix ecosystem. Includes validators for strings, numbers, dates, collections, phone numbers, and files.
Installation #
dependencies:
formix_validators: ^0.1.0
formix_core: ^0.1.0
Available Validators #
- StringRules - String validation (required, email, length, patterns, etc.)
- NumberRules - Numeric validation (range, positive, precision, etc.)
- DateRules - Date/time validation (past, future, age, weekday, etc.)
- CollectionRules - Collection validation (length, unique, contains, etc.)
- PhoneRules - Phone number validation
- FileRules - File validation (size, extension, etc.)
StringRules #
import 'package:formix_validators/formix_validators.dart';
// Required (non-empty)
StringRules.required(error: 'Field is required')
// Trimmed not empty (ignores whitespace)
StringRules.trimmedNotEmpty(error: 'Cannot be blank')
// Length constraints
StringRules.minLength(8, error: 'Must be at least 8 characters')
StringRules.maxLength(100, error: 'Must be at most 100 characters')
StringRules.lengthRange(3, 20, error: 'Must be 3-20 characters')
// Email validation
StringRules.email(error: 'Invalid email format')
// Pattern matching
StringRules.matches(RegExp(r'^[a-zA-Z0-9_]+$'), error: 'Invalid characters')
// String content
StringRules.startsWith('+', error: 'Must start with +')
StringRules.endsWith('.com', error: 'Must end with .com')
StringRules.contains('@', error: 'Must contain @')
StringRules.equals(otherValue, error: 'Values must match')
StringRules.equalsIgnoreCase('yes', error: 'Must be yes')
// Character requirements
StringRules.hasUppercase(error: 'Must contain uppercase letter')
StringRules.hasLowercase(error: 'Must contain lowercase letter')
StringRules.hasDigit(error: 'Must contain a number')
StringRules.hasSpecialChar(error: 'Must contain special character')
// Format validators
StringRules.digitsOnly(error: 'Only digits allowed')
StringRules.alphaOnly(error: 'Only letters allowed')
StringRules.alphanumeric(error: 'Only letters and numbers allowed')
StringRules.url(error: 'Invalid URL')
StringRules.uuid(error: 'Invalid UUID')
StringRules.creditCard(error: 'Invalid credit card number')
Complete Email Validator Example #
final emailValidator = Validate.all<String, String>([
StringRules.required(error: 'Email is required'),
StringRules.email(error: 'Invalid email format'),
StringRules.maxLength(255, error: 'Email too long'),
]);
Password Validator Example #
final passwordValidator = Validate.all<String, String>([
StringRules.required(error: 'Password is required'),
StringRules.minLength(8, error: 'Must be at least 8 characters'),
StringRules.hasUppercase(error: 'Must contain uppercase letter'),
StringRules.hasLowercase(error: 'Must contain lowercase letter'),
StringRules.hasDigit(error: 'Must contain a number'),
StringRules.hasSpecialChar(error: 'Must contain special character'),
]);
NumberRules #
import 'package:formix_validators/formix_validators.dart';
// Basic constraints
NumberRules.min(0, error: 'Must be non-negative')
NumberRules.max(100, error: 'Must be at most 100')
NumberRules.range(1, 100, error: 'Must be 1-100')
// Comparison
NumberRules.greaterThan(0, error: 'Must be positive')
NumberRules.lessThan(100, error: 'Must be less than 100')
// Sign validation
NumberRules.positive(error: 'Must be positive')
NumberRules.nonNegative(error: 'Cannot be negative')
NumberRules.negative(error: 'Must be negative')
NumberRules.nonPositive(error: 'Must be non-positive')
// Special values
NumberRules.notZero(error: 'Cannot be zero')
NumberRules.finite(error: 'Must be a finite number')
// Integer constraints
NumberRules.integer(error: 'Must be a whole number')
NumberRules.even(error: 'Must be even')
NumberRules.odd(error: 'Must be odd')
NumberRules.multipleOf(5, error: 'Must be multiple of 5')
// Decimal precision
NumberRules.maxDecimalPlaces(2, error: 'Max 2 decimal places')
Age Validator Example #
final ageValidator = Validate.all<int, String>([
NumberRules.range(0, 150, error: 'Invalid age'),
]);
// With string input transformation
final ageFromString = Validate.transform<String, int, String>(
transform: (value) => int.tryParse(value),
onNull: 'Must be a number',
then: ageValidator,
);
Price Validator Example #
final priceValidator = Validate.all<double, String>([
NumberRules.nonNegative(error: 'Price cannot be negative'),
NumberRules.maxDecimalPlaces(2, error: 'Max 2 decimal places'),
NumberRules.max(1000000, error: 'Price too high'),
]);
DateRules #
import 'package:formix_validators/formix_validators.dart';
// Relative to now
DateRules.past(error: 'Must be in the past')
DateRules.future(error: 'Must be in the future')
// Relative to another date
DateRules.before(deadline, error: 'Must be before deadline')
DateRules.after(startDate, error: 'Must be after start date')
DateRules.range(startDate, endDate, error: 'Must be within range')
// Weekday validation
DateRules.weekday([1, 2, 3, 4, 5], error: 'Must be a weekday')
DateRules.businessDay(error: 'Must be a business day (Mon-Fri)')
// Age validation
DateRules.age(18, 120, error: 'Must be 18-120 years old')
DateRules.minAge(18, error: 'Must be at least 18 years old')
DateRules.maxAge(65, error: 'Must be under 65 years old')
Birth Date Validator Example #
final birthDateValidator = Validate.all<DateTime, String>([
DateRules.past(error: 'Birth date must be in the past'),
DateRules.age(0, 150, error: 'Invalid birth date'),
]);
Appointment Date Validator Example #
final appointmentValidator = Validate.all<DateTime, String>([
DateRules.future(error: 'Appointment must be in the future'),
DateRules.businessDay(error: 'Must be a business day'),
DateRules.range(
DateTime.now(),
DateTime.now().add(Duration(days: 90)),
error: 'Must be within 90 days',
),
]);
CollectionRules #
import 'package:formix_validators/formix_validators.dart';
// Length constraints
CollectionRules.notEmpty(error: 'Cannot be empty')
CollectionRules.minLength(1, error: 'At least one item required')
CollectionRules.maxLength(10, error: 'Maximum 10 items')
CollectionRules.lengthRange(1, 5, error: 'Must have 1-5 items')
// Uniqueness
CollectionRules.unique(error: 'No duplicates allowed')
CollectionRules.uniqueBy((item) => item.id, error: 'Duplicate IDs')
// Content checks
CollectionRules.contains(item, error: 'Must include item')
CollectionRules.containsAll([item1, item2], error: 'Missing required items')
CollectionRules.containsAny([item1, item2], error: 'Must include at least one')
CollectionRules.doesNotContain(item, error: 'Must not include item')
// Element validation
CollectionRules.every(predicate, error: 'All items must match')
CollectionRules.any(predicate, error: 'At least one must match')
CollectionRules.none(predicate, error: 'None should match')
Tags Validator Example #
final tagsValidator = Validate.all<List<String>, String>([
CollectionRules.minLength(1, error: 'At least one tag required'),
CollectionRules.maxLength(5, error: 'Maximum 5 tags'),
CollectionRules.unique(error: 'Duplicate tags not allowed'),
CollectionRules.every(
(tag) => tag.length <= 20,
error: 'Tags must be 20 characters or less',
),
]);
Using with Custom Error Types #
All validators support custom error types via generics:
// With enum errors
enum EmailError { required, invalidFormat, tooLong }
final validator = Validate.all<String, EmailError>([
StringRules.required(error: EmailError.required),
StringRules.email(error: EmailError.invalidFormat),
StringRules.maxLength(255, error: EmailError.tooLong),
]);
// With sealed class errors (recommended for i18n)
sealed class PasswordError {}
class PasswordRequired extends PasswordError {}
class PasswordTooShort extends PasswordError {
final int minLength;
PasswordTooShort(this.minLength);
}
final validator = Validate.all<String, PasswordError>([
StringRules.required(error: PasswordRequired()),
StringRules.minLength(8, error: PasswordTooShort(8)),
]);
Combining Validators #
// Complete user registration validator
final usernameValidator = Validate.all<String, String>([
StringRules.required(error: 'Username is required'),
StringRules.minLength(3, error: 'Too short'),
StringRules.maxLength(20, error: 'Too long'),
StringRules.alphanumeric(error: 'Only letters and numbers'),
]);
final emailValidator = Validate.all<String, String>([
StringRules.required(error: 'Email is required'),
StringRules.email(error: 'Invalid email'),
]);
final passwordValidator = Validate.allCollect<String, String>([
StringRules.required(error: 'Password is required'),
StringRules.minLength(8, error: 'At least 8 characters'),
StringRules.hasUppercase(error: 'Need uppercase'),
StringRules.hasDigit(error: 'Need number'),
]);
License #
MIT License - see LICENSE file for details.