15 releases (3 major breaking)

3.0.0 Oct 29, 2024
2.0.0 Sep 16, 2024
1.1.1 Jun 6, 2024
1.1.0 May 18, 2024
0.1.5 Jun 18, 2023

#733 in Web programming

Download history 39/week @ 2024-11-27 48/week @ 2024-12-04 74/week @ 2024-12-11 31/week @ 2024-12-18 9/week @ 2025-01-01 42/week @ 2025-01-08 13/week @ 2025-01-15 24/week @ 2025-01-22 65/week @ 2025-01-29 181/week @ 2025-02-05 83/week @ 2025-02-12 37/week @ 2025-02-19 51/week @ 2025-02-26 62/week @ 2025-03-05 25/week @ 2025-03-12

179 downloads per month
Used in 4 crates (2 directly)

GPL-3.0-or-later

3KB

Resolver API

Declare your API in the Rust type system.

Declare API

/// User entity
#[derive(Serialize, Deserialize)]
pub struct User {
  pub id: i64,
  pub username: String,
}

/// Get User request 
#[derive(Serialize, Deserialize, Debug, Resolve)]
#[response(User)]
pub struct GetUser {
  pub id: i64,
}

Implement API

The API can be implemented using any transport. A common one is HTTP, for example using axum:

impl Resolve<()> for GetUser {
  async fn resolve(self, _: &()) -> Result<User, std::convert::Infallible> {
    Ok(User { id: self.id, username: String::new("example") }))
  }
}

struct Response(axum::response::Response);

impl<T> From<T> for Response
where
  T: serde::Serialize,
{
  fn from(value: T) -> Self {
    Response(axum::Json(value).into_response())
  }
}

#[derive(Deserialize, Resolve)]
#[response(Response)]
#[error(Response)]
enum Request {
  GetUser(GetUser),
}

let app = Router::new()
  .route(
    "/",
    post(
      |Json(req): Json<Request>| async move {
        match req.resolve(&()).await {
          Ok(res) => res.0,
          Err(err) => err.0,
        }
      },
    ),
  );

let listener = tokio::net::TcpListener::bind("127.0.0.1:5555")
  .await?;

axum::serve(listener, app).await?;

Call API

fn reqwest() -> &'static reqwest::Client {
  static REQWEST: OnceLock<reqwest::Client> = OnceLock::new();
  REQWEST.get_or_init(reqwest::Client::default)
}

async fn resolve<T>(req: &T) -> Result<T::Response, Error> {
  let res = client
    .post("http://127.0.0.1:5555")
    .json(req)
    .send()
    .await?;
  if res.status().is_success() {
    res.json().await
  } else {
    // handle error
  }
}

// knows response is "User" type
let user = resolve(&GetUser { id: 0 })
  .await
  .unwrap(); 

Dependencies

~205–640KB
~15K SLoC