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 for JsError { fn from(value: JsValue) -> Self { Self::JsError( js_sys::JSON::stringify(&value) .unwrap() .as_string() .unwrap(), ) } } pub async fn api_request Deserialize<'a>>( method: &str, endpoint: &str, body: Option, ) -> Result, 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::::from(Binding::new(bind_value!($value), bind_change!($value))) }; }