45 lines
2.0 KiB
Dart
45 lines
2.0 KiB
Dart
import 'package:freezed_annotation/freezed_annotation.dart';
|
|
|
|
part 'api_exception.freezed.dart';
|
|
|
|
/// Typed errors thrown by [NodeMasterApiClient]/repositories. Riverpod's
|
|
/// `AsyncValue` (via `FutureProvider`/`AsyncNotifier`) already catches
|
|
/// thrown exceptions into `AsyncValue.error`, so this is the result-type
|
|
/// boundary — no separate `Result<T, E>` wrapper is layered on top.
|
|
@freezed
|
|
sealed class ApiException with _$ApiException implements Exception {
|
|
/// DNS/connection failure — couldn't reach the host at all.
|
|
const factory ApiException.network(String message) = ApiNetworkException;
|
|
|
|
/// Connect/send/receive timeout.
|
|
const factory ApiException.timeout() = ApiTimeoutException;
|
|
|
|
/// The server responded with a 4xx/5xx and (usually) a `{"error": msg}`
|
|
/// body.
|
|
const factory ApiException.server(int statusCode, String message) = ApiServerException;
|
|
|
|
/// The response body wasn't the JSON shape a model expected.
|
|
const factory ApiException.parse(String message) = ApiParseException;
|
|
|
|
/// Request was cancelled (e.g. the active connection changed mid-flight).
|
|
const factory ApiException.cancelled() = ApiCancelledException;
|
|
|
|
/// Anything else.
|
|
const factory ApiException.unknown(String message) = ApiUnknownException;
|
|
}
|
|
|
|
extension ApiExceptionUserMessage on ApiException {
|
|
/// Short, user-facing copy — screens can use this directly or switch on
|
|
/// the exception type themselves for more specific handling.
|
|
String get userMessage => switch (this) {
|
|
ApiNetworkException() => "Can't reach this node — check the URL and that it's reachable.",
|
|
ApiTimeoutException() => 'The node took too long to respond.',
|
|
ApiServerException(:final statusCode, :final message) => statusCode == 404
|
|
? 'Not found.'
|
|
: 'Server error ($statusCode): $message',
|
|
ApiParseException() => 'Received an unexpected response from the node.',
|
|
ApiCancelledException() => 'Cancelled.',
|
|
ApiUnknownException(:final message) => message,
|
|
};
|
|
}
|