143 lines
3.5 KiB
Rust
143 lines
3.5 KiB
Rust
use std::ops::Deref;
|
|
|
|
use anyhow::anyhow;
|
|
use serde::{Deserialize, Serialize};
|
|
use thiserror::Error;
|
|
use wasm_bindgen::{prelude::*, JsCast};
|
|
use wasm_bindgen_futures::JsFuture;
|
|
use web_sys::{Headers, Request, RequestInit, RequestMode, Response};
|
|
use yew::html::IntoPropValue;
|
|
|
|
#[derive(Error, Debug, Clone)]
|
|
pub enum JsError {
|
|
#[error("javascript error: {0}")]
|
|
JsError(String),
|
|
}
|
|
|
|
impl From<JsValue> for JsError {
|
|
fn from(value: JsValue) -> Self {
|
|
Self::JsError(
|
|
js_sys::JSON::stringify(&value)
|
|
.unwrap()
|
|
.as_string()
|
|
.unwrap(),
|
|
)
|
|
}
|
|
}
|
|
|
|
pub async fn api_request<B: Serialize, R: for<'a> Deserialize<'a>>(
|
|
method: &str,
|
|
endpoint: &str,
|
|
body: Option<B>,
|
|
) -> Result<Option<R>, anyhow::Error> {
|
|
let api_key = "7de10bf6-278d-11ed-ad60-a8a15919d1b3";
|
|
|
|
let mut req_opts = RequestInit::new();
|
|
req_opts.method(method);
|
|
|
|
let headers = Headers::new().map_err(JsError::from)?;
|
|
headers
|
|
.append("X-API-Key", api_key)
|
|
.map_err(JsError::from)?;
|
|
req_opts.headers(&headers);
|
|
|
|
if let Some(body) = body {
|
|
let value = JsValue::from_serde(&body)?;
|
|
req_opts.body(
|
|
js_sys::JSON::stringify(&value)
|
|
.ok()
|
|
.map(JsValue::from)
|
|
.as_ref(),
|
|
);
|
|
}
|
|
web_sys::console::log_1(&JsValue::from("here"));
|
|
|
|
let request = Request::new_with_str_and_init(
|
|
&format!("http://localhost:8000/api/{}", endpoint),
|
|
&req_opts,
|
|
)
|
|
.map_err(JsError::from)?;
|
|
|
|
let window = web_sys::window().unwrap();
|
|
let resp_value = JsFuture::from(window.fetch_with_request(&request))
|
|
.await
|
|
.map_err(JsError::from)?;
|
|
let resp: Response = resp_value.dyn_into().unwrap();
|
|
|
|
let json = resp.json().map_err(JsError::from)?;
|
|
|
|
if let Ok(data) = JsFuture::from(json).await.map_err(JsError::from) {
|
|
if let Ok(data) = data.into_serde() {
|
|
return Ok(Some(data));
|
|
}
|
|
}
|
|
|
|
Ok(None)
|
|
}
|
|
|
|
#[macro_export]
|
|
macro_rules! clone {
|
|
($($var:ident),* $(,)? => $body:expr) => {{
|
|
$(let $var = $var.clone();)*
|
|
$body
|
|
}};
|
|
}
|
|
|
|
#[macro_export]
|
|
macro_rules! clone_cb {
|
|
($($var:ident),* $(,)? => $body:expr) => {
|
|
clone!($($var,)* => {
|
|
Callback::from($body)
|
|
})
|
|
};
|
|
($($var:ident),* $(,)? => $($param:ident),* $(,)? => $body:expr) => {
|
|
clone!($($var,)* => {
|
|
move |$($param,)*| {
|
|
Callback::from($body)
|
|
}
|
|
})
|
|
};
|
|
}
|
|
|
|
#[macro_export]
|
|
macro_rules! clone_cb_spawn {
|
|
($($var:ident),* => $body:expr) => {
|
|
clone_cb!($($var,)* => move |_| {
|
|
clone!($($var,)* => spawn_local(async move { $body }))
|
|
})
|
|
};
|
|
($($var:ident),* $(,)? => $($param:ident),* => $body:expr) => {
|
|
clone_cb!($($var,)* => $($param),* => move |_| {
|
|
clone!($($var,)* => spawn_local(async move { $body }))
|
|
})
|
|
};
|
|
}
|
|
|
|
#[macro_export]
|
|
macro_rules! init {
|
|
($var:ident => $body:expr) => {
|
|
clone!($var => use_mount(move || spawn_local(async move { $body })))
|
|
};
|
|
}
|
|
|
|
#[macro_export]
|
|
macro_rules! bind_value {
|
|
($value:ident) => {
|
|
(*$value).clone()
|
|
};
|
|
}
|
|
|
|
#[macro_export]
|
|
macro_rules! bind_change {
|
|
($value:ident) => {
|
|
clone_cb!($value => move |value| $value.set(value))
|
|
};
|
|
}
|
|
|
|
#[macro_export]
|
|
macro_rules! bind {
|
|
($value:ident) => {
|
|
Binding::<String>::from(Binding::new(bind_value!($value), bind_change!($value)))
|
|
};
|
|
}
|