use thiserror::Error;
#[derive(Debug, Error)]
pub enum BuildError {
#[error("Failed to build the Pkarr client: {0}")]
Pkarr(#[from] pkarr::errors::BuildError),
#[error("Failed to build the HTTP client: {0}")]
Http(#[from] reqwest::Error),
}
#[derive(Debug, Error)]
pub enum Error {
#[error("Request failed: {0}")]
Request(#[from] RequestError),
#[error("Pkarr operation failed: {0}")]
Pkarr(#[from] PkarrError),
#[error("Failed to parse URL: {0}")]
Parse(#[from] url::ParseError),
#[error("Authentication error: {0}")]
Authentication(#[from] AuthError),
#[error("Client build failed: {0}")]
Build(#[from] BuildError),
}
#[derive(Debug, Error)]
pub enum PkarrError {
#[error("DNS operation failed: {0}")]
Dns(#[from] pkarr::dns::SimpleDnsError),
#[error("Failed to build or sign DNS packet: {0}")]
SignPacket(#[from] pkarr::errors::SignedPacketBuildError),
#[error("Failed to publish record to the DHT: {0}")]
Publish(#[from] pkarr::errors::PublishError),
#[error("Failed to query the DHT: {0}")]
Query(#[from] pkarr::errors::QueryError),
#[error("Pkarr record is malformed or missing required data: {0}")]
InvalidRecord(String),
}
impl PkarrError {
#[must_use]
pub const fn is_retryable(&self) -> bool {
matches!(self, Self::Publish(_) | Self::Query(_))
}
}
#[derive(Debug, Error)]
pub enum AuthError {
#[error("SessionInfo handling failed: {0}")]
SessionInfo(#[from] pubky_common::session::Error),
#[error("Token verification failed: {0}")]
VerificationFailed(#[from] pubky_common::auth::Error),
#[error("Cryptography error: {0}")]
DecryptError(#[from] pubky_common::crypto::DecryptError),
#[error("General authentication error: {0}")]
Validation(String),
#[error("The provided auth request has expired or was cancelled.")]
RequestExpired,
}
#[derive(Debug, Error)]
pub enum RequestError {
#[error("HTTP transport error: {0}")]
Transport(#[from] reqwest::Error),
#[error("Server responded with an error: {status} - {message}")]
Server {
status: reqwest::StatusCode,
message: String,
},
#[error("Invalid request/URI: {message}")]
Validation {
message: String,
},
#[error("JSON decode error: {message}")]
DecodeJson {
message: String,
},
}
pub type Result<T> = std::result::Result<T, Error>;
macro_rules! impl_from_for_error {
($from_type:ty, $to_variant:path) => {
impl From<$from_type> for Error {
fn from(err: $from_type) -> Self {
$to_variant(err.into())
}
}
};
}
impl_from_for_error!(pkarr::errors::SignedPacketBuildError, Error::Pkarr);
impl_from_for_error!(pkarr::errors::PublishError, Error::Pkarr);
impl_from_for_error!(pkarr::errors::QueryError, Error::Pkarr);
impl_from_for_error!(pkarr::dns::SimpleDnsError, Error::Pkarr);
impl_from_for_error!(pubky_common::session::Error, Error::Authentication);
impl_from_for_error!(pubky_common::auth::Error, Error::Authentication);
impl_from_for_error!(pubky_common::crypto::DecryptError, Error::Authentication);
impl_from_for_error!(reqwest::Error, Error::Request);