Skip to content

Commit 5041f9f

Browse files
authored
feat: support subscribe token (#464)
* feat: support subscribe token * feat: support get collab * feat: support browser rule for get collab * fix: update collab version
1 parent 3901356 commit 5041f9f

File tree

12 files changed

+294
-56
lines changed

12 files changed

+294
-56
lines changed

.github/workflows/wasm_publish.yml

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,26 @@ on:
88
required: true
99
default: 'libs/client-api-wasm'
1010
package_name:
11-
description: 'Package name'
11+
description: 'Which package to publish'
1212
required: true
1313
default: '@appflowyinc/client-api-wasm'
14+
type: choice
15+
options:
16+
- '@appflowyinc/client-api-wasm'
1417
package_version:
1518
description: 'Package version'
1619
required: true
20+
prerelease_preid:
21+
description: 'Preid for prerelease version (e.g., alpha, beta, rc)'
22+
required: false
23+
type: choice
24+
default: ''
25+
options:
26+
- ''
27+
- 'alpha'
28+
- 'beta'
29+
- 'rc'
30+
1731
env:
1832
NODE_VERSION: '20.12.0'
1933
RUST_TOOLCHAIN: "1.75"
@@ -43,11 +57,18 @@ jobs:
4357
run: wasm-pack build
4458
working-directory: ${{ github.event.inputs.working_directory }}
4559

46-
- name: Update package.json
60+
- name: Update name
61+
working-directory: ${{ github.event.inputs.working_directory }}/pkg
4762
run: |
48-
cd ${{ github.event.inputs.working_directory }}/pkg
49-
jq '.name = "${{ github.event.inputs.package_name }}" | .version = "${{ github.event.inputs.package_version }}"' package.json > package.json.tmp
63+
jq '.name = "${{ github.event.inputs.package_name }}"' package.json > package.json.tmp
5064
mv package.json.tmp package.json
65+
- name: Update version
66+
working-directory: ${{ github.event.inputs.working_directory }}/pkg
67+
run: |
68+
npm version ${{ github.event.inputs.package_version }}
69+
if [ "${{ github.event.inputs.prerelease_preid }}" != "" ]; then
70+
npm version prerelease --preid ${{ github.event.inputs.prerelease_preid }}
71+
fi
5172
5273
- name: Configure npm for wasm-pack
5374
run: echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}" > ${{ github.event.inputs.working_directory }}/pkg/.npmrc

Cargo.lock

Lines changed: 17 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

libs/client-api-wasm/Cargo.toml

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,18 +15,23 @@ wasm-bindgen = "0.2.84"
1515
# all the `std::fmt` and `std::panicking` infrastructure, so isn't great for
1616
# code size when deploying.
1717
console_error_panic_hook = { version = "0.1.7", optional = true }
18-
serde = "1.0.197"
18+
serde = { version = "1.0.197", features = ["derive"] }
1919
serde_json = "1.0.64"
2020
client-api = { path = "../client-api" }
2121
lazy_static = "1.4.0"
2222
wasm-bindgen-futures = "0.4.20"
2323
tsify = "0.4.5"
2424
tracing.workspace = true
25+
bytes.workspace = true
2526
tracing-core = { version = "0.1.32" }
2627
tracing-wasm = "0.2.1"
2728
uuid.workspace = true
29+
database-entity.workspace = true
30+
collab-rt-entity.workspace = true
31+
collab-entity.workspace = true
32+
serde_repr = "0.1.18"
2833
wee_alloc = { version = "0.4.5", optional = true }
29-
34+
serde-wasm-bindgen = "0.6.5"
3035
[dev-dependencies]
3136
wasm-bindgen-test = "0.3.34"
3237

libs/client-api-wasm/src/entities.rs

Lines changed: 96 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,24 @@
1-
use client_api::error::ErrorCode;
1+
use client_api::entity::AFUserProfile;
2+
use client_api::error::{AppResponseError, ErrorCode};
3+
use collab_entity::CollabType;
4+
use collab_rt_entity::EncodedCollab;
5+
use database_entity::dto::{QueryCollab, QueryCollabParams};
26
use serde::{Deserialize, Serialize};
7+
use serde_repr::{Deserialize_repr, Serialize_repr};
38
use tsify::Tsify;
49
use wasm_bindgen::JsValue;
510

611
macro_rules! from_struct_for_jsvalue {
712
($type:ty) => {
813
impl From<$type> for JsValue {
914
fn from(value: $type) -> Self {
10-
JsValue::from_str(&serde_json::to_string(&value).unwrap())
15+
match serde_wasm_bindgen::to_value(&value) {
16+
Ok(js_value) => js_value,
17+
Err(err) => {
18+
tracing::error!("Failed to convert User to JsValue: {:?}", err);
19+
JsValue::NULL
20+
},
21+
}
1122
}
1223
}
1324
};
@@ -39,3 +50,86 @@ pub struct ClientResponse {
3950
}
4051

4152
from_struct_for_jsvalue!(ClientResponse);
53+
impl From<AppResponseError> for ClientResponse {
54+
fn from(err: AppResponseError) -> Self {
55+
ClientResponse {
56+
code: err.code,
57+
message: err.message.to_string(),
58+
}
59+
}
60+
}
61+
62+
#[derive(Tsify, Serialize, Deserialize)]
63+
#[tsify(into_wasm_abi, from_wasm_abi)]
64+
pub struct User {
65+
pub uid: String,
66+
pub uuid: String,
67+
pub email: Option<String>,
68+
pub name: Option<String>,
69+
pub latest_workspace_id: String,
70+
pub icon_url: Option<String>,
71+
}
72+
73+
from_struct_for_jsvalue!(User);
74+
impl From<AFUserProfile> for User {
75+
fn from(profile: AFUserProfile) -> Self {
76+
User {
77+
uid: profile.uid.to_string(),
78+
uuid: profile.uuid.to_string(),
79+
email: profile.email,
80+
name: profile.name,
81+
latest_workspace_id: profile.latest_workspace_id.to_string(),
82+
icon_url: None,
83+
}
84+
}
85+
}
86+
87+
#[derive(Tsify, Serialize, Deserialize, Default, Debug)]
88+
#[tsify(into_wasm_abi, from_wasm_abi)]
89+
pub struct ClientQueryCollabParams {
90+
pub workspace_id: String,
91+
pub object_id: String,
92+
#[tsify(type = "0 | 1 | 2 | 3 | 4 | 5")]
93+
pub collab_type: i32,
94+
}
95+
96+
impl Into<QueryCollabParams> for ClientQueryCollabParams {
97+
fn into(self) -> QueryCollabParams {
98+
QueryCollabParams {
99+
workspace_id: self.workspace_id,
100+
inner: QueryCollab {
101+
collab_type: CollabType::from(self.collab_type),
102+
object_id: self.object_id,
103+
},
104+
}
105+
}
106+
}
107+
108+
#[derive(Tsify, Serialize, Deserialize, Default)]
109+
#[tsify(into_wasm_abi, from_wasm_abi)]
110+
pub struct ClientEncodeCollab {
111+
pub state_vector: Vec<u8>,
112+
pub doc_state: Vec<u8>,
113+
#[serde(default)]
114+
pub version: ClientEncoderVersion,
115+
}
116+
117+
#[derive(Tsify, Default, Serialize_repr, Deserialize_repr)]
118+
#[repr(u8)]
119+
pub enum ClientEncoderVersion {
120+
#[default]
121+
V1 = 0,
122+
V2 = 1,
123+
}
124+
125+
from_struct_for_jsvalue!(ClientEncodeCollab);
126+
127+
impl From<EncodedCollab> for ClientEncodeCollab {
128+
fn from(collab: EncodedCollab) -> Self {
129+
ClientEncodeCollab {
130+
state_vector: collab.state_vector.to_vec(),
131+
doc_state: collab.doc_state.to_vec(),
132+
version: ClientEncoderVersion::V1,
133+
}
134+
}
135+
}

libs/client-api-wasm/src/lib.rs

Lines changed: 75 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
pub mod entities;
2-
use crate::entities::{ClientAPIConfig, ClientResponse};
2+
3+
use crate::entities::*;
4+
use client_api::entity::QueryCollabParams;
5+
use client_api::notify::TokenState;
36
use client_api::{Client, ClientConfiguration};
7+
use std::sync::Arc;
8+
use tracing;
49
use wasm_bindgen::prelude::*;
510

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

35+
#[wasm_bindgen(js_namespace = window)]
36+
fn refresh_token(token: &str);
37+
38+
#[wasm_bindgen(js_namespace = window)]
39+
fn invalid_token();
3040
}
3141

3242
#[wasm_bindgen]
3343
pub struct ClientAPI {
34-
client: Client,
44+
client: Arc<Client>,
3545
}
3646

3747
#[wasm_bindgen]
@@ -55,54 +65,77 @@ impl ClientAPI {
5565
configuration,
5666
config.client_id.as_str(),
5767
);
68+
5869
tracing::debug!("Client API initialized, config: {:?}", config);
59-
ClientAPI { client }
70+
ClientAPI {
71+
client: Arc::new(client),
72+
}
6073
}
6174

62-
// pub async fn get_user(&self) -> ClientResponse {
63-
// if let Err(err) = self.client.get_profile().await {
64-
// log::error!("Get user failed: {:?}", err);
65-
// return ClientResponse<bool> {
66-
// code: ClientErrorCode::from(err.code),
67-
// message: err.message.to_string(),
68-
// data: None
69-
// }
70-
// }
71-
//
72-
// log::info!("Get user success");
73-
// ClientResponse {
74-
// code: ClientErrorCode::Ok,
75-
// message: "Get user success".to_string(),
76-
// }
77-
// }
78-
79-
pub async fn sign_up_email_verified(
80-
&self,
81-
email: &str,
82-
password: &str,
83-
) -> Result<bool, ClientResponse> {
84-
if let Err(err) = self.client.sign_up(email, password).await {
85-
return Err(ClientResponse {
86-
code: err.code,
87-
message: err.message.to_string(),
88-
});
75+
pub fn subscribe(&self) {
76+
let mut rx = self.client.subscribe_token_state();
77+
let client = self.client.clone();
78+
79+
wasm_bindgen_futures::spawn_local(async move {
80+
while let Ok(state) = rx.recv().await {
81+
match state {
82+
TokenState::Refresh => {
83+
if let Ok(token) = client.get_token() {
84+
refresh_token(token.as_str());
85+
} else {
86+
invalid_token();
87+
}
88+
},
89+
TokenState::Invalid => {
90+
invalid_token();
91+
},
92+
}
93+
}
94+
});
95+
}
96+
pub async fn login(&self, email: &str, password: &str) -> Result<(), ClientResponse> {
97+
match self.client.sign_in_password(email, password).await {
98+
Ok(_) => Ok(()),
99+
Err(err) => Err(ClientResponse::from(err)),
89100
}
101+
}
90102

91-
Ok(true)
103+
pub async fn sign_up(&self, email: &str, password: &str) -> Result<(), ClientResponse> {
104+
match self.client.sign_up(email, password).await {
105+
Ok(_) => Ok(()),
106+
Err(err) => Err(ClientResponse::from(err)),
107+
}
92108
}
93109

94-
pub async fn sign_in_password(
95-
&self,
96-
email: &str,
97-
password: &str,
98-
) -> Result<bool, ClientResponse> {
99-
if let Err(err) = self.client.sign_in_password(email, password).await {
100-
return Err(ClientResponse {
101-
code: err.code,
102-
message: err.message.to_string(),
103-
});
110+
pub async fn logout(&self) -> Result<(), ClientResponse> {
111+
match self.client.sign_out().await {
112+
Ok(_) => Ok(()),
113+
Err(err) => Err(ClientResponse::from(err)),
104114
}
115+
}
105116

106-
Ok(true)
117+
pub async fn get_user(&self) -> Result<User, ClientResponse> {
118+
match self.client.get_profile().await {
119+
Ok(profile) => Ok(User::from(profile)),
120+
Err(err) => Err(ClientResponse::from(err)),
121+
}
122+
}
123+
124+
pub fn restore_token(&self, token: &str) -> Result<(), ClientResponse> {
125+
match self.client.restore_token(token) {
126+
Ok(_) => Ok(()),
127+
Err(err) => Err(ClientResponse::from(err)),
128+
}
129+
}
130+
131+
pub async fn get_collab(
132+
&self,
133+
params: ClientQueryCollabParams,
134+
) -> Result<ClientEncodeCollab, ClientResponse> {
135+
tracing::debug!("get_collab: {:?}", params);
136+
match self.client.get_collab(params.into()).await {
137+
Ok(data) => Ok(ClientEncodeCollab::from(data)),
138+
Err(err) => Err(ClientResponse::from(err)),
139+
}
107140
}
108141
}

libs/client-api/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ features = ["tungstenite"]
5959
wasm-bindgen-futures = "0.4.40"
6060
getrandom = { version = "0.2", features = ["js"]}
6161
tokio = { workspace = true, features = ["sync"]}
62-
again = "0.1.2"
62+
again = { version = "0.1.2" }
6363

6464
[features]
6565
collab-sync = ["collab", "yrs"]

0 commit comments

Comments
 (0)