df_safer_dart 0.16.3 copy "df_safer_dart: ^0.16.3" to clipboard
df_safer_dart: ^0.16.3 copied to clipboard

A package inspired by functional programming, designed to enhance the structure, safety, and debuggability of mission-critical code.

example/main.dart

import 'package:df_safer_dart/df_safer_dart.dart';
import 'dart:convert';

typedef KeyValueMap = Map<String, dynamic>;

// A network call that can fail. Async handles both success and exceptions.
Async<String> fetchUserData(int userId) => Async(() async {
  await Future<void>.delayed(
    const Duration(milliseconds: 10),
  ); // Simulate network latency
  if (userId == 1) {
    return '{"config":{"notifications":{"sound":"chime.mp3"}}}';
  }
  if (userId == 2) {
    return '{"config":{}}';
  }
  if (userId == 3) {
    return '{"config": "bad_data"}';
  }
  throw Exception(
    'User Not Found',
  ); // This will be caught by Async and become an Err
});

// A parser that can fail. Sync automatically catches the jsonDecode exception.
Sync<KeyValueMap> parseJson(String json) =>
    Sync(() => jsonDecode(json) as KeyValueMap);

// A helper to safely extract a typed value. It cannot fail, it can only be absent,
// so it returns an Option.
Option<T> getFromMap<T extends Object>(KeyValueMap map, String key) {
  final value = map[key];
  return letAsOrNone<T>(value); // A safe-cast helper from the library
}

/// This is the logic pipeline. It reads like a description of the happy path.
/// There are no try-catch blocks and no null checks.
Async<Option<String>> getUserNotificationSound(int userId) {
  return fetchUserData(userId) // Starts with Async<String>
      .map(
        // The .unwrap() here will throw if parseJson created an Err.
        // The Async monad's .map will catch that throw and turn the
        // whole chain into an Err state.
        (jsonString) => UNSAFE(() => parseJson(jsonString).unwrap()),
      )
      .map(
        // This .map only runs if fetching and parsing were successful.
        (data) =>
            // Start the Option chain to safely drill into the data.
            // .flatMap is used to chain functions that return another Option.
            getFromMap<KeyValueMap>(data, 'config')
                .flatMap(
                  (config) => getFromMap<KeyValueMap>(config, 'notifications'),
                )
                .flatMap(
                  (notifications) => getFromMap<String>(notifications, 'sound'),
                ),
      );
}

void main() async {
  for (var id in [1, 2, 3, 4, 5]) {
    print('Processing User ID: $id');

    // Execute the pipeline. `await value` opens the Async box.
    final finalResult = await getUserNotificationSound(id).value;

    switch (finalResult) {
      case Ok(value: final optionSound):
        switch (optionSound) {
          // Success! The value is an Option<String>.
          // Now open the Option box.
          case Some(value: final sound):
            print('  -> Success: Sound setting is "$sound"\n');
          case None():
            print('  -> Success: Sound setting was not specified.\n');
        }
      case Err err:
        // The entire pipeline failed at some point.
        print('  -> Failure: An error occurred: ${err.error}\n');
    }
  }
}
8
likes
140
points
5.22k
downloads

Publisher

verified publisherdev-cetera.com

Weekly Downloads

A package inspired by functional programming, designed to enhance the structure, safety, and debuggability of mission-critical code.

Homepage
Repository (GitHub)
View/report issues

Topics

#rust #error-handling #functional-programming #debugging #safety

Documentation

API reference

Funding

Consider supporting this project:

www.buymeacoffee.com

License

MIT (license)

Dependencies

df_safer_dart_annotations, df_type, equatable, meta, path, stack_trace

More

Packages that depend on df_safer_dart