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

Zero-boilerplate async initialization gating for Dart. Ensure your class's async methods automatically suspend until asynchronous setup is complete.

example/initializable_example.dart

// ignore_for_file: unused_local_variable, avoid_print

import 'package:initializable/initializable.dart';

// ============================================================
// Example 1: Non-Throwing Initialization (CacheService)
// ============================================================

/// A cache service that requires async warm-up before use.
///
/// Uses the [Initializable] mixin to gate all data-access methods
/// behind the [warmUp] initialization phase.
class CacheService with Initializable {
  late Map<String, String> _store;

  /// Loads the cache from disk and opens the initialization gate.
  Future<void> warmUp() async {
    // Simulate async disk loading
    await Future<void>.delayed(const Duration(milliseconds: 100));
    _store = {'user:1': 'Alice', 'user:2': 'Bob'};
    markInitialized(); // 🔓 Gate opens — all waiting methods proceed
  }

  /// Returns a cached value by key.
  ///
  /// Automatically waits for [warmUp] to complete before accessing the store.
  Future<String?> get(String key) => guarded(() async {
        return _store[key];
      });

  /// Returns all cached keys.
  Future<List<String>> keys() => guarded(() async {
        return _store.keys.toList();
      });

  /// Sync method — no gating needed.
  String get cacheDir => '/tmp/cache';
}

// ============================================================
// Example 2: Throwing Initialization (DatabaseService)
// ============================================================

/// A database service whose connection can fail.
///
/// Uses [ThrowingInitializable] to propagate connection errors
/// to all methods that depend on the connection.
class DatabaseService with ThrowingInitializable {
  String? _connectionId;

  /// Attempts to connect to the database.
  ///
  /// On success, opens the gate. On failure, propagates the error
  /// to all waiting callers.
  Future<void> connect(String url) async {
    try {
      // Simulate async connection
      await Future<void>.delayed(const Duration(milliseconds: 50));

      if (url.isEmpty) {
        throw ArgumentError('Connection URL cannot be empty');
      }

      _connectionId = 'conn_${url.hashCode}';
      markInitialized(); // ✅ Success
    } catch (e, st) {
      markFailed(e, st); // ❌ Propagate to all waiters
    }
  }

  /// Executes a query — waits for connection, or throws if it failed.
  Future<List<String>> query(String sql) => guarded(() async {
        return ['row1: $sql via $_connectionId'];
      });
}

// ============================================================
// Main — Demonstrates both patterns
// ============================================================

Future<void> main() async {
  // --- Non-throwing example ---
  print('=== CacheService (Non-Throwing) ===');
  final cache = CacheService();

  // Kick off warm-up concurrently
  final warmUpFuture = cache.warmUp();

  // These calls automatically wait for warmUp() to finish
  final user = await cache.get('user:1');
  print('user:1 = $user'); // Alice

  final allKeys = await cache.keys();
  print('keys = $allKeys'); // [user:1, user:2]

  print('initialized: ${cache.initialized}'); // true
  await warmUpFuture;

  // --- Throwing example (success) ---
  print('\n=== DatabaseService (Success) ===');
  final db = DatabaseService();
  await db.connect('postgres://localhost:5432');

  final rows = await db.query('SELECT * FROM users');
  print('query result: $rows');
  print('initialized: ${db.initialized}'); // true

  // --- Throwing example (failure) ---
  print('\n=== DatabaseService (Failure) ===');
  final failingDb = DatabaseService();
  await failingDb.connect(''); // Empty URL → failure

  try {
    await failingDb.query('SELECT 1');
  } catch (e) {
    print('query threw: $e'); // ArgumentError
  }
  print('initialized: ${failingDb.initialized}'); // false
}
2
likes
160
points
142
downloads

Documentation

API reference

Publisher

verified publisherkarindam.in

Weekly Downloads

Zero-boilerplate async initialization gating for Dart. Ensure your class's async methods automatically suspend until asynchronous setup is complete.

Repository (GitHub)
View/report issues

Topics

#async #initialization #concurrency #gate #mixin

License

MIT (license)

Dependencies

meta

More

Packages that depend on initializable