Skip to content

callius/target-dart

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

47 Commits
 
 
 
 
 
 
 
 

Repository files navigation

Target

Target is a library for Functional Domain Modeling in Dart, the Dart implementation of target-kt, inspired by arrow-kt.

Target aims to provide a set of tools for Dart to empower users to quickly write pure, functionally validated domain models. For this, it includes a set of atomic components: ValueFailure, ValueObject, and ValueValidator. These components can be used on their own, or in conjunction with the included build_runner annotation processor.

Getting Started

Value Failure

A ValueFailure is an interface representing a failure during value validation.

abstract interface class ValueFailure<T> {
  abstract final T failedValue;
}

Value Object

A ValueObject is an interface representing a validated value. By convention, value object implementations have a private primary constructor, so that they are not instantiated outside a ValueValidator. A value object implementation must declare a static implementation of a value validator, of, when used in conjunction with the annotation processor package.

abstract interface class ValueObject<T> {
  abstract final T value;
}

Value Validator

A ValueValidator is an interface defining value validation functions. The primary validation function, of, takes an input and returns either a ValueFailure or a ValueObject. The value validator is also callable, delegating to of. By convention, the value object's private constructor is often passed to its primary constructor as a reference.

abstract class ValueValidator<I extends Object, F extends ValueFailure<I>, T extends ValueObject<I>> {
  const ValueValidator();

  Either<F, T> of(I input);

// ...
}

Examples

The included StringInRegexValidator class is an example of a ValueValidator implementation.

class StringRegexValidator<T extends ValueObject<String>>
    extends ValueValidator<String, GenericValueFailure<String>, T> {
  final T Function(String input) _ctor;
  final RegExp regExp;

  const StringRegexValidator(this._ctor, {required this.regExp});

  @override
  Either<GenericValueFailure<String>, T> of(String input) {
    if (regExp.hasMatch(input)) {
      return Right(_ctor(input));
    } else {
      return Left(GenericValueFailure(input));
    }
  }
}

The included EmailAddress class is an example of an annotation processor compatible ValueObject implementation.

/// A W3C HTML5 email address.
final class EmailAddress extends GenericValueObject<String> {
  static const of = EmailAddressValidator(EmailAddress._);

  const EmailAddress._(super.value);
}

This value object can then be used to validate an email address like so:

Future<Either<UserCreateFailure, User>> createUser(UserParamsDto params) {
  return eitherAsync((r) {
    final emailAddress = EmailAddress.of(params.emailAddress)
        .leftMap(UserCreateFailure.invalidEmailAddress)
        .let(r.bind);

    // ... validating other params ...
    return repositoryCreate(
      UserParams(
        emailAddress: emailAddress,
        // ... passing other validated params ...
      ),
    ).then(r.bind);
  });
}

About

Target - Functional domain modeling in Dart

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages