use client_api::entity::{AFUserProfile, AuthProvider}; use client_api::error::{AppResponseError, ErrorCode}; use collab_entity::{CollabType, EncodedCollab}; use database_entity::dto::{ AFUserWorkspaceInfo, AFWorkspace, BatchQueryCollabResult, QueryCollab, QueryCollabParams, QueryCollabResult, }; use serde::{Deserialize, Serialize}; use serde_repr::{Deserialize_repr, Serialize_repr}; use std::collections::HashMap; use tsify::Tsify; use wasm_bindgen::JsValue; macro_rules! from_struct_for_jsvalue { ($type:ty) => { impl From<$type> for JsValue { fn from(value: $type) -> Self { match serde_wasm_bindgen::to_value(&value) { Ok(js_value) => js_value, Err(err) => { tracing::error!("Failed to convert User to JsValue: {:?}", err); JsValue::NULL }, } } } }; } #[derive(Tsify, Serialize, Deserialize, Default, Debug)] #[tsify(into_wasm_abi, from_wasm_abi)] pub struct Configuration { pub compression_quality: u32, pub compression_buffer_size: usize, } #[derive(Tsify, Serialize, Deserialize, Default, Debug)] #[tsify(into_wasm_abi, from_wasm_abi)] pub struct ClientAPIConfig { pub base_url: String, pub ws_addr: String, pub gotrue_url: String, pub device_id: String, pub configuration: Option, pub client_id: String, } #[derive(Tsify, Serialize, Deserialize, Default, Debug)] #[tsify(into_wasm_abi, from_wasm_abi)] pub struct ClientResponse { pub code: ErrorCode, pub message: String, } from_struct_for_jsvalue!(ClientResponse); impl From for ClientResponse { fn from(err: AppResponseError) -> Self { ClientResponse { code: err.code, message: err.message.to_string(), } } } #[derive(Tsify, Serialize, Deserialize)] #[tsify(into_wasm_abi, from_wasm_abi)] pub struct User { pub uid: String, pub uuid: String, pub email: Option, pub name: Option, pub latest_workspace_id: String, pub icon_url: Option, } from_struct_for_jsvalue!(User); impl From for User { fn from(profile: AFUserProfile) -> Self { User { uid: profile.uid.to_string(), uuid: profile.uuid.to_string(), email: profile.email, name: profile.name, latest_workspace_id: profile.latest_workspace_id.to_string(), icon_url: None, } } } #[derive(Tsify, Serialize, Deserialize)] #[tsify(into_wasm_abi, from_wasm_abi)] pub struct UserWorkspace { pub user: User, pub visiting_workspace_id: String, pub workspaces: Vec, } from_struct_for_jsvalue!(UserWorkspace); impl From for UserWorkspace { fn from(info: AFUserWorkspaceInfo) -> Self { UserWorkspace { user: User::from(info.user_profile), visiting_workspace_id: info.visiting_workspace.workspace_id.to_string(), workspaces: info.workspaces.into_iter().map(Workspace::from).collect(), } } } #[derive(Tsify, Serialize, Deserialize)] #[tsify(into_wasm_abi, from_wasm_abi)] pub struct Workspace { pub workspace_id: String, pub database_storage_id: String, pub owner_uid: String, pub owner_name: String, pub workspace_type: i32, pub workspace_name: String, pub created_at: String, pub icon: String, } from_struct_for_jsvalue!(Workspace); impl From for Workspace { fn from(workspace: AFWorkspace) -> Self { Workspace { workspace_id: workspace.workspace_id.to_string(), database_storage_id: workspace.database_storage_id.to_string(), owner_uid: workspace.owner_uid.to_string(), owner_name: workspace.owner_name, workspace_type: workspace.workspace_type, workspace_name: workspace.workspace_name, created_at: workspace.created_at.timestamp().to_string(), icon: workspace.icon, } } } #[derive(Tsify, Serialize, Deserialize, Default, Debug)] #[tsify(into_wasm_abi, from_wasm_abi)] pub struct ClientQueryCollabParams { pub workspace_id: String, pub object_id: String, #[tsify(type = "0 | 1 | 2 | 3 | 4 | 5")] pub collab_type: i32, } impl From for QueryCollabParams { fn from(value: ClientQueryCollabParams) -> QueryCollabParams { QueryCollabParams { workspace_id: value.workspace_id, inner: QueryCollab { collab_type: CollabType::from(value.collab_type), object_id: value.object_id, }, } } } #[derive(Tsify, Serialize, Deserialize, Default)] #[tsify(into_wasm_abi, from_wasm_abi)] pub struct ClientEncodeCollab { pub state_vector: Vec, pub doc_state: Vec, #[serde(default)] pub version: ClientEncoderVersion, } #[derive(Tsify, Default, Serialize_repr, Deserialize_repr)] #[repr(u8)] pub enum ClientEncoderVersion { #[default] V1 = 0, V2 = 1, } from_struct_for_jsvalue!(ClientEncodeCollab); impl From for ClientEncodeCollab { fn from(collab: EncodedCollab) -> Self { ClientEncodeCollab { state_vector: collab.state_vector.to_vec(), doc_state: collab.doc_state.to_vec(), version: ClientEncoderVersion::V1, } } } #[derive(Tsify, Serialize, Deserialize, Default, Debug)] #[tsify(into_wasm_abi, from_wasm_abi)] pub struct BatchClientQueryCollab(pub Vec); #[derive(Tsify, Serialize, Deserialize, Default, Debug)] #[tsify(into_wasm_abi, from_wasm_abi)] pub struct ClientQueryCollab { pub object_id: String, #[tsify(type = "0 | 1 | 2 | 3 | 4 | 5")] pub collab_type: i32, } from_struct_for_jsvalue!(ClientQueryCollab); impl From for QueryCollab { fn from(value: ClientQueryCollab) -> QueryCollab { QueryCollab { collab_type: CollabType::from(value.collab_type), object_id: value.object_id, } } } #[derive(Tsify, Serialize, Deserialize, Default)] #[tsify(into_wasm_abi, from_wasm_abi)] pub struct BatchClientEncodeCollab(pub HashMap); from_struct_for_jsvalue!(BatchClientEncodeCollab); impl From for BatchClientEncodeCollab { fn from(result: BatchQueryCollabResult) -> Self { let mut hash_map = HashMap::new(); result.0.into_iter().for_each(|(k, v)| match v { QueryCollabResult::Success { encode_collab_v1 } => { EncodedCollab::decode_from_bytes(&encode_collab_v1) .map(|collab| { hash_map.insert(k, ClientEncodeCollab::from(collab)); }) .unwrap_or_else(|err| { tracing::error!("Failed to decode collab: {:?}", err); }); }, QueryCollabResult::Failed { .. } => { tracing::error!("Failed to get collab: {:?}", k); }, }); BatchClientEncodeCollab(hash_map) } } #[derive(Tsify, Serialize, Deserialize, Default, Debug)] #[tsify(into_wasm_abi, from_wasm_abi)] pub struct PublishViewMeta { pub data: String, } #[derive(Tsify, Serialize, Deserialize, Default, Debug)] #[tsify(into_wasm_abi, from_wasm_abi)] pub struct PublishViewPayload { pub meta: PublishViewMeta, /// The doc_state of the encoded collab. pub data: Vec, } #[derive(Tsify, Serialize, Deserialize, Default, Debug)] #[tsify(into_wasm_abi, from_wasm_abi)] pub struct PublishInfo { pub namespace: Option, pub publish_name: String, } from_struct_for_jsvalue!(PublishViewMeta); from_struct_for_jsvalue!(PublishViewPayload); from_struct_for_jsvalue!(PublishInfo); pub fn parse_provider(provider: &str) -> AuthProvider { match provider { "google" => AuthProvider::Google, "github" => AuthProvider::Github, "discord" => AuthProvider::Discord, _ => AuthProvider::Google, } } #[derive(Tsify, Serialize, Deserialize, Default, Debug)] #[tsify(into_wasm_abi, from_wasm_abi)] pub struct OAuthURLResponse { pub url: String, } from_struct_for_jsvalue!(OAuthURLResponse);