safeCall<T> static method

Future<Either<Failure, T>> safeCall<T>(
  1. Future<T> request(), {
  2. Either<Failure, T>? onError(
    1. Object error
    )?,
})

Safely executes a Supabase operation and returns an Either result.

  • On success: Returns Right(result)
  • On failure: Returns Left(Failure) based on the error registry mappings

The error handling priority is:

  1. onError callback (if provided) for custom handling
  2. Error registry mappings (auth, postgrest, storage, function, general)
  3. genericError from the registry as fallback

Example:

final result = await SupabaseNetworkHandler.safeCall(
  () => supabase.from('users').select().eq('id', userId).single(),
  onError: (error) {
    // Custom handling for specific cases
    if (error is PostgrestException && error.code == 'PGRST116') {
      return const Left(UserNotFoundFailure());
    }
    return null; // Fall through to registry
  },
);

Implementation

static Future<Either<Failure, T>> safeCall<T>(
  Future<T> Function() request, {
  Either<Failure, T>? Function(Object error)? onError,
}) async {
  assert(
    _errorRegistry != null,
    'Supabase error registry must be set before calling safeCall. '
    'Call SupabaseNetworkHandler.setErrorRegistry() at app startup.',
  );

  try {
    final result = await request();
    return Right(result);
  } on AuthException catch (e, stackTrace) {
    _logError(e, stackTrace);
    return _handleAuthException<T>(e, onError);
  } on PostgrestException catch (e, stackTrace) {
    _logError(e, stackTrace);
    return _handlePostgrestException<T>(e, onError);
  } on StorageException catch (e, stackTrace) {
    _logError(e, stackTrace);
    return _handleStorageException<T>(e, onError);
  } on FunctionException catch (e, stackTrace) {
    _logError(e, stackTrace);
    return _handleFunctionException<T>(e, onError);
  } catch (e, stackTrace) {
    _logError(e, stackTrace);
    return _handleGeneralException<T>(e, onError);
  }
}