diff --git a/Cargo.lock b/Cargo.lock index 73585e4..ec29b2b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -884,10 +884,11 @@ checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" [[package]] name = "js-sys" -version = "0.3.72" +version = "0.3.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9" +checksum = "6717b6b5b077764fb5966237269cb3c64edddde4b14ce42647430a78ced9e7b7" dependencies = [ + "once_cell", "wasm-bindgen", ] @@ -1189,6 +1190,7 @@ dependencies = [ "anyhow", "base32", "blake3", + "js-sys", "mime", "pubky", "pubky-common", diff --git a/Cargo.toml b/Cargo.toml index 46700e1..58ca167 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,6 +21,7 @@ mime = "0.3" utoipa = { git = "https://github.com/juhaku/utoipa", rev = "d522f744259dc4fde5f45d187983fb68c8167029", optional = true } wasm-bindgen = "0.2.99" serde-wasm-bindgen = "0.6.5" +js-sys = "0.3.76" [dev-dependencies] pubky = "0.3.0" diff --git a/src/traits.rs b/src/traits.rs index 8c09983..b63e5d3 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -1,7 +1,8 @@ use crate::common::timestamp; use base32::{decode, encode, Alphabet}; use blake3::Hasher; -use serde::de::DeserializeOwned; +use serde::{de::DeserializeOwned, Serialize}; +use wasm_bindgen::prelude::*; pub trait TimestampId { /// Creates a unique identifier based on the current timestamp. @@ -124,3 +125,21 @@ pub trait HasPath { pub trait HasPubkyIdPath { fn create_path(&self, pubky_id: &str) -> String; } + +pub trait JSdata: HasPath + Serialize { + // helper that returns { id, path, json } + fn get_data(&self) -> Result { + let path = self.create_path(); + + let json_val = serde_wasm_bindgen::to_value(&self) + .map_err(|e| JsValue::from_str(&format!("JSON Error: {}", e)))?; + + // Construct a small JS object + let obj = js_sys::Object::new(); + js_sys::Reflect::set(&obj, &JsValue::from_str("id"), &JsValue::null())?; + js_sys::Reflect::set(&obj, &JsValue::from_str("path"), &JsValue::from_str(&path))?; + js_sys::Reflect::set(&obj, &JsValue::from_str("json"), &json_val)?; + + Ok(obj.into()) + } +} diff --git a/src/user.rs b/src/user.rs index f3ad78f..0f70a5f 100644 --- a/src/user.rs +++ b/src/user.rs @@ -1,9 +1,10 @@ use crate::{ - traits::{HasPath, Validatable}, + traits::{HasPath, JSdata, Validatable}, APP_PATH, }; use serde::{Deserialize, Serialize}; use url::Url; +use wasm_bindgen::prelude::*; // Validation constants const MIN_USERNAME_LENGTH: usize = 3; @@ -19,26 +20,38 @@ const MAX_STATUS_LENGTH: usize = 50; use utoipa::ToSchema; /// URI: /pub/pubky.app/profile.json +#[wasm_bindgen] #[derive(Deserialize, Serialize, Debug, Default, Clone)] #[cfg_attr(feature = "openapi", derive(ToSchema))] pub struct PubkyAppUser { + #[wasm_bindgen(skip)] + // Avoid wasm-pack automatically generating getter/setters for the pub fields. pub name: String, + #[wasm_bindgen(skip)] pub bio: Option, + #[wasm_bindgen(skip)] pub image: Option, + #[wasm_bindgen(skip)] pub links: Option>, + #[wasm_bindgen(skip)] pub status: Option, } /// Represents a user's single link with a title and URL. +#[wasm_bindgen] #[derive(Serialize, Deserialize, Default, Clone, Debug)] #[cfg_attr(feature = "openapi", derive(ToSchema))] pub struct PubkyAppUserLink { + #[wasm_bindgen(skip)] pub title: String, + #[wasm_bindgen(skip)] pub url: String, } +#[wasm_bindgen] impl PubkyAppUser { /// Creates a new `PubkyAppUser` instance and sanitizes it. + #[wasm_bindgen(constructor)] pub fn new( name: String, bio: Option, @@ -55,8 +68,15 @@ impl PubkyAppUser { } .sanitize() } + + #[wasm_bindgen] + pub fn get_data(&self) -> Result { + JSdata::get_data(self) + } } +impl JSdata for PubkyAppUser {} + impl HasPath for PubkyAppUser { fn create_path(&self) -> String { format!("{}profile.json", APP_PATH) @@ -171,6 +191,15 @@ impl Validatable for PubkyAppUser { } } +#[wasm_bindgen] +impl PubkyAppUserLink { + /// Creates a new `PubkyAppUserLink` instance and sanitizes it. + #[wasm_bindgen(constructor)] + pub fn new(title: String, url: String) -> Self { + Self { title, url }.sanitize() + } +} + impl Validatable for PubkyAppUserLink { fn sanitize(self) -> Self { let title = self