Skip to content

Commit

Permalink
feat: support subscribe token (#464)
Browse files Browse the repository at this point in the history
* feat: support subscribe token

* feat: support get collab

* feat: support browser rule for get collab

* fix: update collab version
  • Loading branch information
qinluhe authored Apr 15, 2024
1 parent 3901356 commit 5041f9f
Show file tree
Hide file tree
Showing 12 changed files with 294 additions and 56 deletions.
29 changes: 25 additions & 4 deletions .github/workflows/wasm_publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,26 @@ on:
required: true
default: 'libs/client-api-wasm'
package_name:
description: 'Package name'
description: 'Which package to publish'
required: true
default: '@appflowyinc/client-api-wasm'
type: choice
options:
- '@appflowyinc/client-api-wasm'
package_version:
description: 'Package version'
required: true
prerelease_preid:
description: 'Preid for prerelease version (e.g., alpha, beta, rc)'
required: false
type: choice
default: ''
options:
- ''
- 'alpha'
- 'beta'
- 'rc'

env:
NODE_VERSION: '20.12.0'
RUST_TOOLCHAIN: "1.75"
Expand Down Expand Up @@ -43,11 +57,18 @@ jobs:
run: wasm-pack build
working-directory: ${{ github.event.inputs.working_directory }}

- name: Update package.json
- name: Update name
working-directory: ${{ github.event.inputs.working_directory }}/pkg
run: |
cd ${{ github.event.inputs.working_directory }}/pkg
jq '.name = "${{ github.event.inputs.package_name }}" | .version = "${{ github.event.inputs.package_version }}"' package.json > package.json.tmp
jq '.name = "${{ github.event.inputs.package_name }}"' package.json > package.json.tmp
mv package.json.tmp package.json
- name: Update version
working-directory: ${{ github.event.inputs.working_directory }}/pkg
run: |
npm version ${{ github.event.inputs.package_version }}
if [ "${{ github.event.inputs.prerelease_preid }}" != "" ]; then
npm version prerelease --preid ${{ github.event.inputs.prerelease_preid }}
fi
- name: Configure npm for wasm-pack
run: echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}" > ${{ github.event.inputs.working_directory }}/pkg/.npmrc
Expand Down
17 changes: 17 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 7 additions & 2 deletions libs/client-api-wasm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,23 @@ wasm-bindgen = "0.2.84"
# all the `std::fmt` and `std::panicking` infrastructure, so isn't great for
# code size when deploying.
console_error_panic_hook = { version = "0.1.7", optional = true }
serde = "1.0.197"
serde = { version = "1.0.197", features = ["derive"] }
serde_json = "1.0.64"
client-api = { path = "../client-api" }
lazy_static = "1.4.0"
wasm-bindgen-futures = "0.4.20"
tsify = "0.4.5"
tracing.workspace = true
bytes.workspace = true
tracing-core = { version = "0.1.32" }
tracing-wasm = "0.2.1"
uuid.workspace = true
database-entity.workspace = true
collab-rt-entity.workspace = true
collab-entity.workspace = true
serde_repr = "0.1.18"
wee_alloc = { version = "0.4.5", optional = true }

serde-wasm-bindgen = "0.6.5"
[dev-dependencies]
wasm-bindgen-test = "0.3.34"

Expand Down
98 changes: 96 additions & 2 deletions libs/client-api-wasm/src/entities.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,24 @@
use client_api::error::ErrorCode;
use client_api::entity::AFUserProfile;
use client_api::error::{AppResponseError, ErrorCode};
use collab_entity::CollabType;
use collab_rt_entity::EncodedCollab;
use database_entity::dto::{QueryCollab, QueryCollabParams};
use serde::{Deserialize, Serialize};
use serde_repr::{Deserialize_repr, Serialize_repr};
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 {
JsValue::from_str(&serde_json::to_string(&value).unwrap())
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
},
}
}
}
};
Expand Down Expand Up @@ -39,3 +50,86 @@ pub struct ClientResponse {
}

from_struct_for_jsvalue!(ClientResponse);
impl From<AppResponseError> 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<String>,
pub name: Option<String>,
pub latest_workspace_id: String,
pub icon_url: Option<String>,
}

from_struct_for_jsvalue!(User);
impl From<AFUserProfile> 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, 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 Into<QueryCollabParams> for ClientQueryCollabParams {
fn into(self) -> QueryCollabParams {
QueryCollabParams {
workspace_id: self.workspace_id,
inner: QueryCollab {
collab_type: CollabType::from(self.collab_type),
object_id: self.object_id,
},
}
}
}

#[derive(Tsify, Serialize, Deserialize, Default)]
#[tsify(into_wasm_abi, from_wasm_abi)]
pub struct ClientEncodeCollab {
pub state_vector: Vec<u8>,
pub doc_state: Vec<u8>,
#[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<EncodedCollab> 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,
}
}
}
117 changes: 75 additions & 42 deletions libs/client-api-wasm/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
pub mod entities;
use crate::entities::{ClientAPIConfig, ClientResponse};

use crate::entities::*;
use client_api::entity::QueryCollabParams;
use client_api::notify::TokenState;
use client_api::{Client, ClientConfiguration};
use std::sync::Arc;
use tracing;
use wasm_bindgen::prelude::*;

#[cfg(feature = "enable_wee_alloc")]
Expand All @@ -27,11 +32,16 @@ extern "C" {
#[wasm_bindgen(js_namespace = console)]
fn trace(msg: &str);

#[wasm_bindgen(js_namespace = window)]
fn refresh_token(token: &str);

#[wasm_bindgen(js_namespace = window)]
fn invalid_token();
}

#[wasm_bindgen]
pub struct ClientAPI {
client: Client,
client: Arc<Client>,
}

#[wasm_bindgen]
Expand All @@ -55,54 +65,77 @@ impl ClientAPI {
configuration,
config.client_id.as_str(),
);

tracing::debug!("Client API initialized, config: {:?}", config);
ClientAPI { client }
ClientAPI {
client: Arc::new(client),
}
}

// pub async fn get_user(&self) -> ClientResponse {
// if let Err(err) = self.client.get_profile().await {
// log::error!("Get user failed: {:?}", err);
// return ClientResponse<bool> {
// code: ClientErrorCode::from(err.code),
// message: err.message.to_string(),
// data: None
// }
// }
//
// log::info!("Get user success");
// ClientResponse {
// code: ClientErrorCode::Ok,
// message: "Get user success".to_string(),
// }
// }

pub async fn sign_up_email_verified(
&self,
email: &str,
password: &str,
) -> Result<bool, ClientResponse> {
if let Err(err) = self.client.sign_up(email, password).await {
return Err(ClientResponse {
code: err.code,
message: err.message.to_string(),
});
pub fn subscribe(&self) {
let mut rx = self.client.subscribe_token_state();
let client = self.client.clone();

wasm_bindgen_futures::spawn_local(async move {
while let Ok(state) = rx.recv().await {
match state {
TokenState::Refresh => {
if let Ok(token) = client.get_token() {
refresh_token(token.as_str());
} else {
invalid_token();
}
},
TokenState::Invalid => {
invalid_token();
},
}
}
});
}
pub async fn login(&self, email: &str, password: &str) -> Result<(), ClientResponse> {
match self.client.sign_in_password(email, password).await {
Ok(_) => Ok(()),
Err(err) => Err(ClientResponse::from(err)),
}
}

Ok(true)
pub async fn sign_up(&self, email: &str, password: &str) -> Result<(), ClientResponse> {
match self.client.sign_up(email, password).await {
Ok(_) => Ok(()),
Err(err) => Err(ClientResponse::from(err)),
}
}

pub async fn sign_in_password(
&self,
email: &str,
password: &str,
) -> Result<bool, ClientResponse> {
if let Err(err) = self.client.sign_in_password(email, password).await {
return Err(ClientResponse {
code: err.code,
message: err.message.to_string(),
});
pub async fn logout(&self) -> Result<(), ClientResponse> {
match self.client.sign_out().await {
Ok(_) => Ok(()),
Err(err) => Err(ClientResponse::from(err)),
}
}

Ok(true)
pub async fn get_user(&self) -> Result<User, ClientResponse> {
match self.client.get_profile().await {
Ok(profile) => Ok(User::from(profile)),
Err(err) => Err(ClientResponse::from(err)),
}
}

pub fn restore_token(&self, token: &str) -> Result<(), ClientResponse> {
match self.client.restore_token(token) {
Ok(_) => Ok(()),
Err(err) => Err(ClientResponse::from(err)),
}
}

pub async fn get_collab(
&self,
params: ClientQueryCollabParams,
) -> Result<ClientEncodeCollab, ClientResponse> {
tracing::debug!("get_collab: {:?}", params);
match self.client.get_collab(params.into()).await {
Ok(data) => Ok(ClientEncodeCollab::from(data)),
Err(err) => Err(ClientResponse::from(err)),
}
}
}
2 changes: 1 addition & 1 deletion libs/client-api/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ features = ["tungstenite"]
wasm-bindgen-futures = "0.4.40"
getrandom = { version = "0.2", features = ["js"]}
tokio = { workspace = true, features = ["sync"]}
again = "0.1.2"
again = { version = "0.1.2" }

[features]
collab-sync = ["collab", "yrs"]
Expand Down
Loading

0 comments on commit 5041f9f

Please sign in to comment.