roctokit 0.15.0

Github v3 Client interfaces
Documentation
use http::{Request, Response};
use serde::{ser, Deserialize};

use crate::auth::Auth;

#[cfg(target_arch = "wasm32")]
pub mod wasm;

#[cfg(feature = "reqwest")]
pub mod reqwest;

#[cfg(feature = "ureq")]
pub mod ureq;

#[derive(thiserror::Error, Debug)]
pub enum AdapterError {
    #[error(transparent)]
    SerdeJson(#[from] serde_json::Error),
    #[error(transparent)]
    SerdeUrl(#[from] serde_urlencoded::ser::Error),
    #[error("client error: {description}")]
    Client {
        description: String,
        #[source]
        source: Option<Box<dyn std::error::Error>>,
    },
    #[error("endpoint error: {description}")]
    Endpoint {
        description: String,
        status_code: u16,
        #[source]
        source: Option<Box<dyn std::error::Error>>,
    },
}


#[cfg(all(
    not(feature = "reqwest"),
    not(feature = "ureq"),
    not(target_arch = "wasm32")
))]
impl GitHubResponseExt for http::Response<Vec<u8>> {
    fn is_success(&self) -> bool {
        unimplemented!("Use a client adapter feature, or target wasm");
    }

    fn status_code(&self) -> u16 {
        unimplemented!("Use a client adapter feature, or target wasm");
    }
    #[allow(refining_impl_trait)]
    fn to_json<E: for<'de> Deserialize<'de> + std::fmt::Debug>(self) -> Result<E, serde_json::Error> {
        unimplemented!("Use a client adapter feature, or target wasm");
    }

    async fn to_json_async<E: for<'de> Deserialize<'de> + Unpin + std::fmt::Debug>(
        self,
    ) -> Result<E, serde_json::Error> {
        unimplemented!("Use a client adapter feature, or target wasm");
    }
}

#[allow(dead_code)]
pub struct GitHubRequest<'a, T> {
    pub uri: String,
    pub method: &'a str,
    pub body: Option<T>,
    pub headers: Vec<(&'a str, &'a str)>,
}

pub trait GitHubResponseExt {
    fn is_success(&self) -> bool;
    fn status_code(&self) -> u16;
    fn to_json<E: for<'de> Deserialize<'de> + std::fmt::Debug>(
        self,
    ) -> Result<E, serde_json::Error>;
    #[allow(async_fn_in_trait)]
    async fn to_json_async<E: for<'de> Deserialize<'de> + Unpin + std::fmt::Debug>(
        self,
    ) -> Result<E, serde_json::Error>;
}

pub trait Client
where
    AdapterError: From<Self::Err>,
{
    type Req;
    type Body;
    type Err;

    fn new(auth: &Auth) -> Result<Self, Self::Err>
    where
        Self: Sized;
    fn build(&self, req: GitHubRequest<Self::Body>) -> Result<Self::Req, Self::Err>;
    fn fetch(&self, req: Self::Req) -> Result<impl GitHubResponseExt, Self::Err>;
    #[allow(async_fn_in_trait)]
    async fn fetch_async(&self, req: Self::Req) -> Result<impl GitHubResponseExt, Self::Err>;
    fn from_json<A: ser::Serialize>(model: A) -> Result<Self::Body, Self::Err>;
}

#[cfg(target_arch = "wasm32")]
pub fn client(auth: &Auth) -> Result<wasm::Client, wasm::AdapterError> {
    wasm::Client::new(auth)
}
#[cfg(feature = "ureq")]
pub fn client(auth: &Auth) -> Result<ureq::Client, ureq::AdapterError> {
    ureq::Client::new(auth)
}
#[cfg(feature = "reqwest")]
pub fn client(auth: &Auth) -> Result<reqwest::Client, reqwest::AdapterError> {
    reqwest::Client::new(auth)
}