verify 1.1.1

  • Readme
  • Changelog
  • Example
  • Installing
  • 79

Validations made simple

Build Status Pub Package Codecov MIT License

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

Requirements #

The implementation of Verify relies heavily on dart extension methods, which are available for Dart versions >= 2.6

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 your own error types) organize validators however you want
  • Bloc friendly (See examples for a concrete implementation)

Usage #

Creating validators #

A Validator is just a simple function alias:

// S is the input type and T the output type
typedef Validator<S, T> = Either<List<ValidationError>, T> Function(S subject);

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(Error('must contain @'))
};

Create simple validators from predicates

A simpler way is to use some of the built in helpers.

final contains@ = Verify.property(
  (String email) => email.contains('@'),
    error: Error('email has to contain @')
    );

final notEmpty = Verify.property<String>((str) => !str.isEmpty, error: Error('field required'));

Reuse validators #

Use composition to build up more complex validators.

final Validator_<String> emailValidator = Verify.all([ contains@, notEmpty ])

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'));

Field validations #

Given a model, for instance a user:

class User extends Equatable {
  final String phone;
  final String mail;
  final int age;

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

  @override
  List<Object> get props => [phone, mail, age];
}

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);

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>

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 = RegExp(r"(^\d+$)") // Validator<String, int>
        .matchOr(Error('not just digits'))
        .map((str) => int.tryParse(str));

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;
}

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)
    .groupedErrorsBy((error) => error.field);

This way you have quick access to errors segmented by field.

Changelog #

[1.1.1] #

  • Update documentation
  • Update to latest dartz

[1.1.0] #

  • Added example with bloc and freezed.
  • Better support for form validation enabling grouped errors by field.
  • Add inOrder sequenced composition.
  • Fix all definition
  • Updated documentation.

example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:verify_example/pages/signup_page.dart';

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      home: SignUpPage(),
    );
  }
}

Use this package as a library

1. Depend on it

Add this to your package's pubspec.yaml file:


dependencies:
  verify: ^1.1.1

2. Install it

You can install packages from the command line:

with pub:


$ pub get

with Flutter:


$ flutter pub get

Alternatively, your editor might support pub get or flutter pub get. Check the docs for your editor to learn more.

3. Import it

Now in your Dart code, you can use:


import 'package:verify/verify.dart';
  
Popularity:
Describes how popular the package is relative to other packages. [more]
59
Health:
Code health derived from static analysis. [more]
100
Maintenance:
Reflects how tidy and up-to-date the package is. [more]
99
Overall:
Weighted score of the above. [more]
79
Learn more about scoring.

We analyzed this package on May 23, 2020, and provided a score, details, and suggestions below. Analysis was completed with status completed using:

  • Dart: 2.8.1
  • pana: 0.13.8-dev

Health suggestions

Fix lib/src/verify.dart. (-0.50 points)

Analysis of lib/src/verify.dart reported 1 hint:

line 218 col 17: The declaration '_compose' isn't referenced.

Maintenance suggestions

The package description is too short. (-1 points)

Add more detail to the description field of pubspec.yaml. Use 60 to 180 characters to describe the package, what it does, and its target use case.

Dependencies

Package Constraint Resolved Available
Direct dependencies
Dart SDK >=2.6.0 <3.0.0
dartz ^0.9.1 0.9.1
meta ^1.1.8 1.1.8
Dev dependencies
equatable ^1.0.0
lint ^1.0.0
test ^1.14.2
test_coverage ^0.4.1