tryx 1.0.0 copy "tryx: ^1.0.0" to clipboard
tryx: ^1.0.0 copied to clipboard

A powerful Dart library for functional, reliable, and expressive error handling using Result types. Provides type-safe error handling without exceptions, with support for async operations, streams, an [...]

Tryx #

Pub Version Dart SDK Version License: MIT Build Status

A powerful Dart library for functional, reliable, and expressive error handling using Result types. Tryx provides type-safe error handling without exceptions, with comprehensive support for async operations, streams, and advanced recovery patterns.

๐Ÿš€ Features #

  • ๐Ÿ”’ Type-Safe Error Handling: Eliminate runtime exceptions with compile-time safety
  • โšก Zero-Cost Abstractions: Minimal performance overhead with maximum safety
  • ๐ŸŒŠ Async & Stream Support: Seamless integration with Future and Stream
  • ๐Ÿ”— Functional Chaining: Chain operations with map, flatMap, recover, and more
  • ๐Ÿ›ก๏ธ Advanced Recovery Patterns: Circuit breakers, retry policies, and fallback chains
  • ๐Ÿ“Š Performance Monitoring: Built-in performance tracking and slow operation detection
  • ๐ŸŽฏ Migration Helpers: Easy transition from try-catch to functional error handling
  • ๐Ÿ“š Comprehensive Documentation: Extensive examples and API documentation

๐Ÿ“ฆ Installation #

Add tryx to your pubspec.yaml:

dependencies:
  tryx: ^1.0.0

Then run:

dart pub get

๐ŸŽฏ Quick Start #

Basic Usage #

import 'package:tryx/tryx.dart';

void main() {
  // Safe function execution
  final result = safe(() => int.parse('42'));

  result.when(
    success: (value) => print('Parsed: $value'), // Parsed: 42
    failure: (error) => print('Error: $error'),
  );

  // Chaining operations
  final chainedResult = safe(() => '123')
      .flatMap((str) => safe(() => int.parse(str)))
      .map((number) => number * 2)
      .recover((error) => 0); // Fallback value

  print('Result: ${chainedResult.getOrNull()}'); // Result: 246
}

Async Operations #

import 'package:tryx/tryx.dart';

Future<void> fetchUserData() async {
  final result = await safeAsync(() => fetchUser('123'));

  final userData = await result
      .mapAsync((user) async => await enrichUserData(user))
      .whenAsync(
        success: (enrichedUser) async {
          await saveToCache(enrichedUser);
          return 'Success: ${enrichedUser.name}';
        },
        failure: (error) async => 'Failed to fetch user: $error',
      );

  print(userData);
}

Stream Processing #

import 'package:tryx/tryx.dart';

void processNumberStream() {
  final numberStrings = Stream.fromIterable(['1', '2', 'invalid', '4']);

  numberStrings
      .safeMap<int, String>(
        int.parse,
        errorMapper: (error) => 'Parse error: $error',
      )
      .where((result) => result.isSuccess)
      .successes()
      .listen((number) => print('Parsed: $number'));
  // Output: Parsed: 1, Parsed: 2, Parsed: 4
}

๐Ÿ“– Core Concepts #

Result Type #

The Result<T, E> type represents either a success with value T or a failure with error E:

// Creating Results
final success = Result<int, String>.success(42);
final failure = Result<int, String>.failure('Something went wrong');

// Pattern matching
final message = result.when(
  success: (value) => 'Got: $value',
  failure: (error) => 'Error: $error',
);

// Safe access
final value = result.getOrNull(); // Returns value or null
final valueOrDefault = result.getOrElse(() => 0); // Returns value or default

Safe Function Execution #

// Synchronous
final result = safe(() => riskyOperation());

// Asynchronous
final asyncResult = await safeAsync(() => asyncRiskyOperation());

// With custom error mapping
final customResult = await safeWith<String, CustomError>(
  () => someOperation(),
  errorMapper: (error) => CustomError.from(error),
);

Functional Chaining #

final result = safe(() => '42')
    .map((str) => str.length)           // Transform success value
    .flatMap((len) => validateLength(len)) // Chain with another Result
    .mapError((error) => 'Validation failed: $error') // Transform error
    .recover((error) => 0)              // Provide fallback
    .onSuccess((value) => print('Success: $value')) // Side effects
    .onFailure((error) => logError(error));

๐Ÿ›ก๏ธ Advanced Features #

Circuit Breaker Pattern #

import 'package:tryx/tryx.dart';

final circuitBreaker = CircuitBreaker(
  config: CircuitBreakerConfig(
    failureThreshold: 5,
    timeout: Duration(seconds: 30),
  ),
);

final result = await circuitBreaker.execute(() => apiCall());

Retry Policies #

// Configure global retry policy
TryxConfig.configure(
  defaultRetryPolicy: RetryPolicies.exponentialBackoff(
    maxAttempts: 3,
    initialDelay: Duration(milliseconds: 100),
  ),
);

// Use with safe functions
final result = await safeAsync(() => unreliableOperation());

Error Recovery Chains #

final fallbackChain = FallbackChain<User, ApiError>()
  ..addFallback(() => getCachedUser())
  ..addFallback(() => getDefaultUser())
  ..addValueFallback(User.guest());

final user = await fallbackChain.execute(() => fetchUser());

๐Ÿ”ง Configuration #

Global Configuration #

import 'package:tryx/tryx.dart';

void main() {
  // Configure Tryx globally
  TryxConfig.configure(
    enableGlobalLogging: true,
    logLevel: LogLevel.warning,
    enablePerformanceMonitoring: true,
    globalTimeout: Duration(seconds: 30),
  );

  // Or use presets
  TryxConfigPresets.production(); // For production
  TryxConfigPresets.development(); // For development
  TryxConfigPresets.testing(); // For testing
}

Custom Error Types #

sealed class ApiError {
  const ApiError();
}

class NetworkError extends ApiError {
  final String message;
  const NetworkError(this.message);
}

class ValidationError extends ApiError {
  final List<String> errors;
  const ValidationError(this.errors);
}

// Usage
Result<User, ApiError> fetchUser(String id) {
  return safeWith<User, ApiError>(
    () => apiClient.getUser(id),
    errorMapper: (error) {
      if (error is SocketException) {
        return NetworkError('Network connection failed');
      }
      return ValidationError(['Invalid user ID']);
    },
  );
}

๐Ÿงช Testing #

Tryx makes testing error scenarios straightforward:

import 'package:test/test.dart';
import 'package:tryx/tryx.dart';

void main() {
  group('User Service Tests', () {
    test('should handle network errors gracefully', () async {
      final result = await safeAsync(() => throw SocketException('No internet'));

      expect(result.isFailure, isTrue);
      expect(result.getOrNull(), isNull);

      final errorMessage = result.when(
        success: (_) => 'Should not reach here',
        failure: (error) => error.toString(),
      );

      expect(errorMessage, contains('SocketException'));
    });
  });
}

๐Ÿš€ Migration from try-catch #

Tryx provides migration helpers to ease the transition:

// Before (try-catch)
String parseNumber(String input) {
  try {
    return int.parse(input).toString();
  } catch (e) {
    return 'Error: $e';
  }
}

// After (Tryx)
String parseNumber(String input) {
  return safe(() => int.parse(input))
      .map((number) => number.toString())
      .getOrElse(() => 'Error: Invalid number');
}

// Or use migration helpers
String parseNumber(String input) {
  return MigrationPatterns.simpleTryCatch(
    () => int.parse(input).toString(),
    onError: (error) => 'Error: $error',
  );
}

๐Ÿ“Š Performance #

Tryx is designed for minimal overhead:

  • Zero-cost abstractions: No performance penalty for type safety
  • Lazy evaluation: Operations are only performed when needed
  • Memory efficient: Minimal memory allocation
  • Built-in monitoring: Track slow operations automatically
// Enable performance monitoring
TryxConfig.configure(
  enablePerformanceMonitoring: true,
  slowOperationThreshold: Duration(milliseconds: 100),
);

// Automatic logging of slow operations
final result = await safeAsync(() => slowDatabaseQuery());

๐Ÿค Contributing #

We welcome contributions! Please see our Contributing Guide for details.

Development Setup #

# Clone the repository
git clone https://github.com/Liv-Coder/tryx.git
cd tryx

# Install dependencies
dart pub get

# Run tests
dart test

# Run analysis
dart analyze

# Generate documentation
dart doc

๐Ÿ“š Documentation #

๐Ÿ†š Comparison with Other Libraries #

Feature Tryx dartz fpdart
Result Type โœ… โœ… โœ…
Async Support โœ… โŒ โœ…
Stream Integration โœ… โŒ โŒ
Circuit Breaker โœ… โŒ โŒ
Performance Monitoring โœ… โŒ โŒ
Migration Helpers โœ… โŒ โŒ
Global Configuration โœ… โŒ โŒ

๐Ÿ“„ License #

This project is licensed under the MIT License - see the LICENSE file for details.

๐Ÿ™ Acknowledgments #

  • Inspired by Rust's Result type and functional programming principles
  • Built with โค๏ธ for the Dart and Flutter community

Made with โค๏ธ by the Tryx team

โญ Star us on GitHub | ๐Ÿ“ฆ View on pub.dev | ๐Ÿ› Report Issues

1
likes
140
points
44
downloads

Publisher

unverified uploader

Weekly Downloads

A powerful Dart library for functional, reliable, and expressive error handling using Result types. Provides type-safe error handling without exceptions, with support for async operations, streams, and advanced recovery patterns.

Repository (GitHub)
View/report issues

Topics

#error-handling #functional-programming #result-type #dart #async

Documentation

API reference

License

MIT (license)

Dependencies

meta

More

Packages that depend on tryx