verify

Creator: coderz1093

Last updated:

0 purchases

TODO
Add to Cart

Description:

verify

Validations made simple















A fp inspired validation DSL. For Dart and Flutter projects.
Features #

Completely extensible (create your own combinators, validator primitives, etc)
Flexible Verify is an extension based API (There is not single class created its all pure functions)
Customizable (Define you own error types if required) organize validators how ever you want
Bloc friendly (See examples for a concrete implementation)
Null safe (as a prerelease)

Usage #
Creating validators #
A Validator is just a simple function alias:
// One of 2 variats depending on wether the validated subject will be transformed into another type or not
typedef ValidatorT<S, T> = Either<List<dynamic>, T> Function(S subject);
typedef Validator<S> = Either<List<dynamic>, S> Function(S subject);
copied to clipboard
So you can create your own validator by just specifying a function for example:
final Validator<String> emailValidator = (String email) {
return email.contains('@') ? Right(email) : Left('Bad email format')
};
copied to clipboard
Create simple validators from predicates
A simpler way is to use some of the built in helpers.
final contains@ = Verify.that(
(String email) => email.contains('@'),
error: 'Bad email format'
);

copied to clipboard
Use custom errors and filter them by type
Reuse validators #
Use composition to build up more complex validators.
final Validator<String> emailValidator = Verify.all([ contains@, notEmpty ])
copied to clipboard
Validate and transform #
Validators are also capable of transforming their input, so for instance we can do
parsing and validation in one go.
final Validator<String, int> intParsingValidator = (String str) => Right(int.parse(str));

final validator = intParsingValidator.onException((_) => Error('not an integer'));
copied to clipboard
Field validations #
Given a model, for instance a user:
class User extends Equatable {
final String? phone;
final String? mail;
final int? age;

const User(this.phone, this.mail, this.age);

@override
List<Object> get props => [phone ?? '', mail ?? '', age ?? ''];
}
copied to clipboard
Additional checks can be performed on the object and its fields by chaining a series of check
and checkField methods.
final userValidator = Verify.empty<User>()
.check((user) => !user.phone!.isEmpty, error: Error('phone empty'))
.checkField((user) => user.mail!, emailValidator);

final someUser = User('','', 25);
final Either<List<Error>, User> validationResult = userValidator.verify(someUser);
copied to clipboard

Note: The difference between check and checkField is that the later ignore the verification when the value is null,
this will likely change in next version supporting null safety.

Run a validator #
Running a validator is a simple as passing in a parameter since its just a function.
To be a bit more eloquent a verify method is provided, this method is special because besides
forwarding the argument to the calling validator it can also be used to filter the error list and
have it cast to a specific error type. Just supply a specific type parameter.
final signUpValidation = Verify.subject<SignUpState>();
final errors = signUpValidation
.verify<SignUpError>(newState); // Either<List<SignUpError>, SignUpState>
copied to clipboard
Built in validators #
Verify doesn't come with many built in validators, because they are so simple to create.
It does come with some regex shorthands.
final validator = Verify.fromRegex(RegExp(r"(^\d+$)", error: Error('not just digits')) // Validator<String, int>
copied to clipboard
Form validation #
Often times you will have modeled your error type similar to:
enum FormField {
email,
password,
passwordConfirmation,
}

class SignUpError extends ValidationError {
final String message;
final FormField field;

SignUpError(this.message, {required this.field});

@override
String get errorDescription => message;
}
copied to clipboard
In these scenarios its convenient to be able to group errors by field.
The solution verify provides for this is:
final validator = Verify.inOrder<SignUpFormState>([
validateMail,
validatePassword,
validateConfirmation,
]);

final Map<FormField, SignUpError> errorMap = validator
.verify<SignUpError>(someState)
.errorsGroupedBy((error) => error.field);
copied to clipboard
Sequencing #
A slightly different API can be used to achieve the same results as the inOrder composition function.
final numberValidator = Verify.subject<int>()
.then(Verify.that(
(subject) => subject % 2 == 0,
error: Error('not even'),
))
.then(Verify.that(
(subject) => subject >= 10,
error: Error('single digit'),
));

final errors2 = numberValidator.errors(3); // yields 1 error
final errors = numberValidator.errors(4); // yields 1 error
copied to clipboard
This way you have quick access to errors segmented by field.

License

For personal and professional use. You cannot resell or redistribute these repositories in their original state.

Files In This Product:

Customer Reviews

There are no reviews.