freezed_result 1.0.3+1 copy "freezed_result: ^1.0.3+1" to clipboard
freezed_result: ^1.0.3+1 copied to clipboard

A Result<Success, Failure> that feels like a Freezed union. It holds the outcome of an operation—a value of type Success, or an error of type Failure—and methods to work with it.

example/main.dart

import 'package:freezed_result/freezed_result.dart';

import 'support.dart';

// Main Idea
// 1. Setup a local database
// 2. Call an API for a user to login
// 3. Store user data in the database
// 4. Store access token in secure storage
void main() async {
  final databaseResult = createDatabase();

  if (databaseResult.isFailure) {
    print('Error setting up the database: ${databaseResult.maybeError}');
    return;
  }

  // Authentication error: Validation error: Password too short.
  await authenticate(0, 'b');

  // Authentication error: Network error: Socket timeout
  await authenticate(1, 'password');

  // Bad user or password.
  await authenticate(2, 'password');

  // Authentication error: Database error: Cannot save user 3.
  await authenticate(3, 'password');

  // Authenticated user 4.
  await authenticate(4, 'password');
}

Future<void> authenticate(int id, String password) async {
  var result = await apiSignIn(id, password);
  if (result.isSuccess) {
    result = await saveUserData(result.maybeValue);
  }
  final authState = result.when(
    success: (user) => (user == null)
        ? AuthState.unauthenticated()
        : AuthState.authenticated(user),
    failure: (error) => AuthState.error(error),
  );
  print(authState.toString());
  print('');
}

Result<Nothing, DatabaseError> createDatabase() {
  // Use `nothing` instead of `void` (which wouldn't work)
  return Result.success(nothing);
}

Future<Result<User?, AuthFailure>> saveUserData(User? user) async {
  // Style 1: use standard try/catch directly return success/failure
  try {
    // User 3: not saved
    await Database().save(user); // Future<void>
    return Result.success(user);
  } on DatabaseError catch (e) {
    return Result.failure(AuthFailure.storage(e));
  }
}

Future<Result<User?, AuthFailure>> apiSignIn(int id, String password) async {
  if (password.length < 2) {
    // User 0: too short
    return Result.failure(AuthFailure.validation('Password too short.'));
  }

  // Style 2: use catching, then translate value & error for return type
  final apiResult = await Result.catching<int?, DioError>(
    // User 1: socket timeout
    // User 2: user not found
    () => FakeDio().get(id), // Future<int?>
  );
  return apiResult.mapWhen(
    success: (id) => id != null ? User(id) : null,
    failure: (error) => AuthFailure.network(error),
  );
}
16
likes
140
points
10
downloads

Publisher

verified publisherdaylogger.dev

Weekly Downloads

A Result<Success, Failure> that feels like a Freezed union. It holds the outcome of an operation—a value of type Success, or an error of type Failure—and methods to work with it.

Repository (GitHub)

Documentation

API reference

License

MIT (license)

Dependencies

collection, meta

More

Packages that depend on freezed_result