forward2<U, E0 extends Object, E1 extends Object> method

Result<U, Errors2<E0, E1>> forward2<U, E0 extends Object, E1 extends Object>({
  1. U success(
    1. T r
    )?,
  2. Object failure(
    1. Object err
    )?,
})

Allows to forward and transform successful and failed results. If operation was successful, calls success callback and returns successful result with transformed data. If operation failed, calls failure callback for each error and returns failed result with transformed errors. Example:


Errors2<Unauthorized, ValidationError> httpPost(String path, Object data) {
  ...
}

AsyncResult<AuthToken, Errors2<InvalidCredentials, EmailNotConfirmed>> login(String login, String password) {
  final response = httpPost('/auth/login', {'login': login, 'password': password});
  return response.forward2(
    success: (r) => AuthToken.parse(r.data),
    failure: (e) => switch (e) {
      (ValidationError e) when e.code == 'email-not-confirmed' => EmailNotConfirmed(),
      (Unauthorized _) => InvalidCredentials(),
      _ => e
    });
}

Implementation

Result<U, Errors2<E0, E1>> forward2<U, E0 extends Object, E1 extends Object>({
  U Function(T r)? success,
  Object Function(Object err)? failure,
}) {
  final expected = Errors2<E0, E1>();

  if (success == null && failure == null) {
    throw AssertionError('Either success or failure should be provided');
  }

  if (_data == null && errors.isEmpty) {
    throw AssertionError('Result object in incorrect state, should have either data or errors');
  }

  if (_data != null) {
    if (success == null) {
      throw AssertionError('Cannot forward a successful result without a success callback');
    }

    return Result.success(success(_data as T), expected);
  }

  if (errors.isNotEmpty && failure == null) {
    throw AssertionError('Cannot forward a failed result without a failure callback');
  }

  var resultingErrors = errors;
  if (failure != null) {
    resultingErrors = resultingErrors.map(failure).toList();
  }

  final unexpected = resultingErrors.where((e) => !expected.isExpectedError(e));
  if (unexpected.isNotEmpty) {
    throw AssertionError('Cannot forward an unexpected errors: $unexpected');
  }

  return Result.error(resultingErrors, expected);
}