Validasi

A flexible, composable, and type-safe validation library for Dart & Flutter.
Documentation API Documentation
Caution
This is the complete rewrite of the Validasi library into a completely new API (with modifier support).
Installation
To use this package, add validasi as a dependency in your pubspec.yaml file:
dependencies:
validasi: ^1.0.0-rc.1
Check the pub.dev page for the latest pre-release version.
Quick Usage
To use this library, simply import package:validasi/validasi.dart and the rules from package:validasi/rules.dart. Here's a basic example:
import 'package:validasi/validasi.dart';
import 'package:validasi/rules.dart';
void main() {
final schema = Validasi.string([
Rules.nullable<String>(),
Rules.transform<String>((input) => input?.trim()),
Rules.string.minLength(3),
Rules.string.maxLength(16)
]);
final result = schema.validate(' Hello World! ');
print("isValid: ${result.isValid}, errors: ${result.errors.map((e) => e.message).join(', ')}, value: ${result.data}");
}
Async Validation
Async rules (like checking email availability against a server) run seamlessly alongside sync rules:
final schema = Validasi.string([
Rules.required(),
Rules.string.email(),
Rules.inlineAsync((email) async {
final taken = await userRepository.isEmailTaken(email!);
return !taken;
}, message: 'Email is already taken'),
]);
final result = await schema.validateAsync('user@example.com');
Container rules (hasFields, forEach, allValues, anyOf) automatically support async children when using validateAsync(). See Async Validation for more.
Validating Complex Data Structures
Map Validation:
final schema = Validasi.map<dynamic>([
Rules.map.hasFields({
'name': FieldRules<String>([
Rules.string.minLength(1),
]),
'age': FieldRules<int>([
Rules.number.moreThan(0),
]),
}),
]);
final result = schema.validate({'name': 'John', 'age': 30});
List Validation:
final schema = Validasi.list<String>([
Rules.iterable.forEach<String>([
Rules.string.minLength(1),
]),
]);
final result = schema.validate(['item1', 'item2', 'item3']);
Refer to the examples folder to see more usage samples or see the documentation.
Features
Type-Safe Validation Engine
Validasi provides type-safe validation schemas for various data types:
Validasi.string()- String validationValidasi.number<T>()- Numeric validation (int, double, num)Validasi.list<T>()- List/Iterable validationValidasi.map<T>()- Map validationValidasi.any<T>()- Generic type validation
Built-in Rules
The library comes with comprehensive built-in rules organized by data type. See the documentation for the full list:
- String Rules -
alpha,email,url,uuid,regex, and more - Number Rules -
finite,lessThan,moreThan, and more - List Rules -
minLength,maxLength,unique,contains,forEach, and more - Map Rules -
hasFields,hasFieldKeys,allowedKeys,requiredAny,matchesField, and more - Generic Rules -
required,nullable,transform,equals,anyOf,inline, and more
Preprocessing & Transformation
Use withPreprocess to transform input data before validation:
final schema = Validasi.string([Rules.string.minLength(3)])
.withPreprocess((value) => value.toString());
final result = schema.validate(123); // Converts to "123" then validates
Safe Validation
All validation returns a ValidasiResult object that contains:
isValid- Boolean indicating validation successdata- The validated (and potentially transformed) dataerrors- List of validation errors with messages and paths
Nested Validation with Error Paths
Validasi tracks error paths for nested structures, making it easy to identify exactly where validation fails:
final result = schema.validate(complexNestedData);
result.errors.forEach((error) {
print("Error at ${error.path?.join('.')}: ${error.message}");
});
License
The Validasi Library is licensed under MIT License.
Contribution
We welcome contributions! Here's how to set up the development environment:
Setting Up Development Environment
# Clone the repository
git clone https://github.com/albetnov/validasi
cd validasi
# Install root dependencies (includes melos)
dart pub get
# Install workspace dependencies
dart run melos bootstrap
Running Tests
The test structure in test/ directory mirrors the lib/src structure:
# Run all tests
dart run melos run test
# Run tests for root package only
dart run melos run test:validasi
# Run tests for MCP package only
dart run melos run test:mcp
# Run tests with coverage
dart test --coverage=coverage
# Format coverage report
dart pub global activate coverage
dart pub global run coverage:format_coverage --lcov --in=coverage --out=coverage/lcov.info --report-on=lib