/// Base class for every error the Rest API layer can produce. sealed class ApiException implements Exception { const ApiException(this.message, {this.uri}); final String message; final Uri? uri; @override String toString() => '$runtimeType: $message${uri != null ? ' ($uri)' : ''}'; } /// The server answered with a non success status code. class ApiHttpException extends ApiException { const ApiHttpException({ required this.statusCode, required String message, this.body, super.uri, }) : super(message); final int statusCode; final String? body; bool get isClientError => statusCode >= 400 && statusCode < 500; bool get isServerError => statusCode >= 500; @override String toString() => 'ApiHttpException($statusCode): $message${uri != null ? ' ($uri)' : ''}'; } /// The server could not be reached at all (no route, refused, offline, ...). class ApiNetworkException extends ApiException { const ApiNetworkException(super.message, {super.uri}); } /// The request ran longer than the configured timeout. class ApiTimeoutException extends ApiException { const ApiTimeoutException(super.message, {super.uri}); } /// The response body could not be parsed into the expected shape. class ApiParsingException extends ApiException { const ApiParsingException(super.message, {super.uri, this.body}); final String? body; }