浏览代码

config doc reqeust

appflowy 3 年之前
父节点
当前提交
2b4a9c2497
共有 37 个文件被更改,包括 197 次插入279 次删除
  1. 0 1
      backend/src/entities/token.rs
  2. 1 2
      backend/src/user_service/logged_user.rs
  3. 1 1
      backend/src/workspace_service/app/app.rs
  4. 2 1
      backend/tests/api/helper.rs
  5. 0 1
      rust-lib/flowy-document/Cargo.toml
  6. 1 1
      rust-lib/flowy-document/src/entities/doc/doc_create.rs
  7. 1 4
      rust-lib/flowy-document/src/entities/doc/doc_query.rs
  8. 0 14
      rust-lib/flowy-document/src/entities/doc/parser/doc_desc.rs
  9. 0 12
      rust-lib/flowy-document/src/entities/doc/parser/doc_name.rs
  10. 0 12
      rust-lib/flowy-document/src/entities/doc/parser/doc_path.rs
  11. 0 12
      rust-lib/flowy-document/src/entities/doc/parser/doc_view_id.rs
  12. 0 8
      rust-lib/flowy-document/src/entities/doc/parser/mod.rs
  13. 3 8
      rust-lib/flowy-document/src/handlers/doc_handler.rs
  14. 1 1
      rust-lib/flowy-document/src/observable/mod.rs
  15. 1 0
      rust-lib/flowy-document/src/observable/observable.rs
  16. 5 5
      rust-lib/flowy-document/src/services/doc_controller.rs
  17. 12 26
      rust-lib/flowy-document/src/services/file_manager/file.rs
  18. 9 13
      rust-lib/flowy-document/src/services/file_manager/manager.rs
  19. 1 1
      rust-lib/flowy-document/src/services/server/middleware.rs
  20. 48 7
      rust-lib/flowy-document/src/services/server/server_api.rs
  21. 4 5
      rust-lib/flowy-document/src/services/server/server_api_mock.rs
  22. 1 2
      rust-lib/flowy-document/src/sql_tables/doc/doc_sql.rs
  23. 2 3
      rust-lib/flowy-document/src/sql_tables/doc/doc_table.rs
  24. 20 9
      rust-lib/flowy-document/tests/editor/doc_test.rs
  25. 6 15
      rust-lib/flowy-document/tests/editor/helper.rs
  26. 3 0
      rust-lib/flowy-net/src/config.rs
  27. 1 1
      rust-lib/flowy-net/src/errors.rs
  28. 51 35
      rust-lib/flowy-net/src/request/request.rs
  29. 1 1
      rust-lib/flowy-sdk/src/deps_resolve/editor_deps_impl.rs
  30. 1 0
      rust-lib/flowy-sdk/src/lib.rs
  31. 0 1
      rust-lib/flowy-user/Cargo.toml
  32. 1 1
      rust-lib/flowy-user/src/observable/mod.rs
  33. 2 16
      rust-lib/flowy-user/src/services/server/server_api.rs
  34. 0 1
      rust-lib/flowy-workspace/Cargo.toml
  35. 1 1
      rust-lib/flowy-workspace/src/services/server/middleware.rs
  36. 13 50
      rust-lib/flowy-workspace/src/services/server/server_api.rs
  37. 4 8
      rust-lib/flowy-workspace/src/sql_tables/workspace/workspace_sql.rs

+ 0 - 1
backend/src/entities/token.rs

@@ -77,7 +77,6 @@ impl Token {
 use actix_web::{dev::Payload, FromRequest, HttpRequest};
 use flowy_net::config::HEADER_TOKEN;
 use futures::future::{ready, Ready};
-use std::convert::TryInto;
 
 impl FromRequest for Token {
     type Config = ();

+ 1 - 2
backend/src/user_service/logged_user.rs

@@ -46,9 +46,8 @@ impl LoggedUser {
 }
 
 use actix_web::{dev::Payload, FromRequest, HttpRequest};
-use flowy_net::config::HEADER_TOKEN;
+
 use futures::future::{ready, Ready};
-use std::convert::TryInto;
 
 impl FromRequest for LoggedUser {
     type Config = ();

+ 1 - 1
backend/src/workspace_service/app/app.rs

@@ -18,7 +18,7 @@ use flowy_workspace::{
         app::parser::{AppDesc, AppName},
         workspace::parser::WorkspaceId,
     },
-    protobuf::{CreateAppParams, QueryAppParams, RepeatedApp, RepeatedView, UpdateAppParams},
+    protobuf::{CreateAppParams, QueryAppParams, RepeatedView, UpdateAppParams},
 };
 use protobuf::Message;
 use sqlx::{postgres::PgArguments, PgPool, Postgres};

+ 2 - 1
backend/tests/api/helper.rs

@@ -146,7 +146,7 @@ pub async fn spawn_app() -> TestApp {
 
     let _ = tokio::spawn(async {
         let _ = application.run_until_stopped();
-        drop_test_database(database_name).await;
+        // drop_test_database(database_name).await;
     });
 
     TestApp {
@@ -181,6 +181,7 @@ async fn configure_database(config: &DatabaseSettings) -> PgPool {
     connection_pool
 }
 
+#[allow(dead_code)]
 async fn drop_test_database(database_name: String) {
     // https://stackoverflow.com/questions/36502401/postgres-drop-database-error-pq-cannot-drop-the-currently-open-database?rq=1
     let configuration = {

+ 0 - 1
rust-lib/flowy-document/Cargo.toml

@@ -9,7 +9,6 @@ edition = "2018"
 [dependencies]
 derive_more = {version = "0.99", features = ["display"]}
 flowy-dispatch = { path = "../flowy-dispatch" }
-flowy-log = { path = "../flowy-log" }
 flowy-derive = { path = "../flowy-derive" }
 flowy-database = { path = "../flowy-database" }
 flowy-infra = { path = "../flowy-infra" }

+ 1 - 1
rust-lib/flowy-document/src/entities/doc/doc_create.rs

@@ -27,7 +27,7 @@ impl TryInto<CreateDocParams> for CreateDocRequest {
     type Error = DocError;
 
     fn try_into(self) -> Result<CreateDocParams, Self::Error> {
-        let id = DocViewId::parse(self.id)
+        let id = DocId::parse(self.id)
             .map_err(|e| ErrorBuilder::new(ErrorCode::DocIdInvalid).msg(e).build())?
             .0;
 

+ 1 - 4
rust-lib/flowy-document/src/entities/doc/doc_query.rs

@@ -1,7 +1,4 @@
-use crate::{
-    entities::doc::parser::{DocId, DocPath},
-    errors::*,
-};
+use crate::{entities::doc::parser::DocId, errors::*};
 use flowy_derive::ProtoBuf;
 use std::convert::TryInto;
 

+ 0 - 14
rust-lib/flowy-document/src/entities/doc/parser/doc_desc.rs

@@ -1,14 +0,0 @@
-use unicode_segmentation::UnicodeSegmentation;
-
-#[derive(Debug)]
-pub struct DocDesc(pub String);
-
-impl DocDesc {
-    pub fn parse(s: String) -> Result<DocDesc, String> {
-        if s.graphemes(true).count() > 1000 {
-            return Err(format!("Doc desc too long"));
-        }
-
-        Ok(Self(s))
-    }
-}

+ 0 - 12
rust-lib/flowy-document/src/entities/doc/parser/doc_name.rs

@@ -1,12 +0,0 @@
-#[derive(Debug)]
-pub struct DocName(pub String);
-
-impl DocName {
-    pub fn parse(s: String) -> Result<DocName, String> {
-        if s.trim().is_empty() {
-            return Err(format!("Doc name can not be empty or whitespace"));
-        }
-
-        Ok(Self(s))
-    }
-}

+ 0 - 12
rust-lib/flowy-document/src/entities/doc/parser/doc_path.rs

@@ -1,12 +0,0 @@
-#[derive(Debug)]
-pub struct DocPath(pub String);
-
-impl DocPath {
-    pub fn parse(s: String) -> Result<DocPath, String> {
-        if s.trim().is_empty() {
-            return Err(format!("Doc path can not be empty or whitespace"));
-        }
-
-        Ok(Self(s))
-    }
-}

+ 0 - 12
rust-lib/flowy-document/src/entities/doc/parser/doc_view_id.rs

@@ -1,12 +0,0 @@
-#[derive(Debug)]
-pub struct DocViewId(pub String);
-
-impl DocViewId {
-    pub fn parse(s: String) -> Result<DocViewId, String> {
-        if s.trim().is_empty() {
-            return Err(format!("Doc view id can not be empty or whitespace"));
-        }
-
-        Ok(Self(s))
-    }
-}

+ 0 - 8
rust-lib/flowy-document/src/entities/doc/parser/mod.rs

@@ -1,11 +1,3 @@
-mod doc_desc;
 mod doc_id;
-mod doc_name;
-mod doc_path;
-mod doc_view_id;
 
-pub use doc_desc::*;
 pub use doc_id::*;
-pub use doc_name::*;
-pub use doc_path::*;
-pub use doc_view_id::*;

+ 3 - 8
rust-lib/flowy-document/src/handlers/doc_handler.rs

@@ -1,11 +1,6 @@
-use crate::{
-    entities::doc::*,
-    errors::DocError,
-    services::{doc_controller::DocController, file_manager::FileManager},
-};
+use crate::{entities::doc::*, errors::DocError, services::doc_controller::DocController};
 use flowy_dispatch::prelude::*;
-use std::{convert::TryInto, path::Path};
-use tokio::sync::RwLock;
+use std::convert::TryInto;
 
 #[tracing::instrument(skip(data, controller))]
 pub async fn create_doc_handler(data: Data<CreateDocRequest>, controller: Unit<DocController>) -> DataResult<Doc, DocError> {
@@ -23,7 +18,7 @@ pub async fn read_doc_handler(data: Data<QueryDocRequest>, controller: Unit<DocC
 
 #[tracing::instrument(skip(data, controller))]
 pub async fn update_doc_handler(data: Data<UpdateDocRequest>, controller: Unit<DocController>) -> Result<(), DocError> {
-    let mut params: UpdateDocParams = data.into_inner().try_into()?;
+    let params: UpdateDocParams = data.into_inner().try_into()?;
     let _ = controller.update_doc(params).await?;
     Ok(())
 }

+ 1 - 1
rust-lib/flowy-document/src/observable/mod.rs

@@ -1,3 +1,3 @@
 mod observable;
 
-pub use observable::*;
+pub(crate) use observable::*;

+ 1 - 0
rust-lib/flowy-document/src/observable/observable.rs

@@ -10,4 +10,5 @@ impl std::convert::Into<i32> for DocObservable {
     fn into(self) -> i32 { self as i32 }
 }
 
+#[allow(dead_code)]
 pub(crate) fn observable(id: &str, ty: DocObservable) -> ObservableBuilder { ObservableBuilder::new(id, ty, OBSERVABLE_CATEGORY) }

+ 5 - 5
rust-lib/flowy-document/src/services/doc_controller.rs

@@ -62,14 +62,14 @@ impl DocController {
 }
 
 impl DocController {
-    #[tracing::instrument(level = "debug", skip(self), err)]
+    #[tracing::instrument(skip(self), err)]
     async fn create_doc_on_server(&self, params: CreateDocParams) -> Result<Doc, DocError> {
         let token = self.user.token()?;
         let doc = self.server.create_doc(&token, params).await?;
         Ok(doc)
     }
 
-    #[tracing::instrument(level = "debug", skip(self, params), err)]
+    #[tracing::instrument(level = "debug", skip(self), err)]
     fn update_doc_on_server(&self, params: UpdateDocParams) -> Result<(), DocError> {
         let token = self.user.token()?;
         let server = self.server.clone();
@@ -85,13 +85,13 @@ impl DocController {
         Ok(())
     }
 
-    #[tracing::instrument(level = "debug", skip(self, params), err)]
+    #[tracing::instrument(level = "debug", skip(self), err)]
     fn read_doc_on_server(&self, params: QueryDocParams) -> Result<(), DocError> {
         let token = self.user.token()?;
         let server = self.server.clone();
         tokio::spawn(async move {
             // Opti: handle the error and retry?
-            let doc = server.read_doc(&token, params).await?;
+            let _doc = server.read_doc(&token, params).await?;
             // save to disk
             // notify
 
@@ -100,7 +100,7 @@ impl DocController {
         Ok(())
     }
 
-    #[tracing::instrument(level = "debug", skip(self, params), err)]
+    #[tracing::instrument(level = "debug", skip(self), err)]
     fn delete_doc_on_server(&self, params: QueryDocParams) -> Result<(), DocError> {
         let token = self.user.token()?;
         let server = self.server.clone();

+ 12 - 26
rust-lib/flowy-document/src/services/file_manager/file.rs

@@ -48,15 +48,14 @@ pub struct FileInfo {
     pub encoding: CharacterEncoding,
 }
 
+#[allow(dead_code)]
 pub(crate) fn try_load_file<P>(path: P) -> Result<(String, FileInfo), FileError>
 where
     P: AsRef<Path>,
 {
-    let mut f =
-        File::open(path.as_ref()).map_err(|e| FileError::Io(e, path.as_ref().to_owned()))?;
+    let mut f = File::open(path.as_ref()).map_err(|e| FileError::Io(e, path.as_ref().to_owned()))?;
     let mut bytes = Vec::new();
-    f.read_to_end(&mut bytes)
-        .map_err(|e| FileError::Io(e, path.as_ref().to_owned()))?;
+    f.read_to_end(&mut bytes).map_err(|e| FileError::Io(e, path.as_ref().to_owned()))?;
 
     let encoding = CharacterEncoding::guess(&bytes);
     let s = try_decode(bytes, encoding, path.as_ref())?;
@@ -69,12 +68,8 @@ where
     Ok((s, info))
 }
 
-pub(crate) fn try_save(
-    path: &Path,
-    text: &str,
-    encoding: CharacterEncoding,
-    _file_info: Option<&FileInfo>,
-) -> io::Result<()> {
+#[allow(dead_code)]
+pub(crate) fn try_save(path: &Path, text: &str, encoding: CharacterEncoding, _file_info: Option<&FileInfo>) -> io::Result<()> {
     let tmp_extension = path.extension().map_or_else(
         || OsString::from("swp"),
         |ext| {
@@ -97,20 +92,14 @@ pub(crate) fn try_save(
     Ok(())
 }
 
-pub(crate) fn try_decode(
-    bytes: Vec<u8>,
-    encoding: CharacterEncoding,
-    path: &Path,
-) -> Result<String, FileError> {
+#[allow(dead_code)]
+pub(crate) fn try_decode(bytes: Vec<u8>, encoding: CharacterEncoding, path: &Path) -> Result<String, FileError> {
     match encoding {
-        CharacterEncoding::Utf8 => {
-            Ok(String::from(str::from_utf8(&bytes).map_err(|_e| {
-                FileError::UnknownEncoding(path.to_owned())
-            })?))
-        },
+        CharacterEncoding::Utf8 => Ok(String::from(
+            str::from_utf8(&bytes).map_err(|_e| FileError::UnknownEncoding(path.to_owned()))?,
+        )),
         CharacterEncoding::Utf8WithBom => {
-            let s = String::from_utf8(bytes)
-                .map_err(|_e| FileError::UnknownEncoding(path.to_owned()))?;
+            let s = String::from_utf8(bytes).map_err(|_e| FileError::UnknownEncoding(path.to_owned()))?;
             Ok(String::from(&s[UTF8_BOM.len()..]))
         },
     }
@@ -123,8 +112,5 @@ pub(crate) fn create_dir_if_not_exist(dir: &str) -> Result<(), io::Error> {
 }
 
 pub(crate) fn get_modified_time<P: AsRef<Path>>(path: P) -> Option<SystemTime> {
-    File::open(path)
-        .and_then(|f| f.metadata())
-        .and_then(|meta| meta.modified())
-        .ok()
+    File::open(path).and_then(|f| f.metadata()).and_then(|meta| meta.modified()).ok()
 }

+ 9 - 13
rust-lib/flowy-document/src/services/file_manager/manager.rs

@@ -20,6 +20,7 @@ impl FileManager {
         }
     }
 
+    #[allow(dead_code)]
     pub(crate) fn open<T>(&mut self, path: &Path, id: T) -> Result<String, FileError>
     where
         T: Into<FileId>,
@@ -35,6 +36,7 @@ impl FileManager {
         Ok(s)
     }
 
+    #[allow(dead_code)]
     pub(crate) fn save<T>(&mut self, path: &Path, text: &String, id: T) -> Result<(), FileError>
     where
         T: Into<FileId>,
@@ -58,12 +60,8 @@ impl FileManager {
         }
     }
 
-    pub(crate) fn create_file(
-        &mut self,
-        id: &str,
-        dir: &str,
-        text: &str,
-    ) -> Result<PathBuf, FileError> {
+    #[allow(dead_code)]
+    pub(crate) fn create_file(&mut self, id: &str, dir: &str, text: &str) -> Result<PathBuf, FileError> {
         let path = PathBuf::from(format!("{}/{}", dir, id));
         let file_id: FileId = id.to_owned().into();
         log::info!("Create doc at: {:?}", path);
@@ -75,9 +73,7 @@ impl FileManager {
     pub(crate) fn get_info(&self, id: &FileId) -> Option<&FileInfo> { self.file_info.get(id) }
 
     #[allow(dead_code)]
-    pub(crate) fn get_file_id(&self, path: &Path) -> Option<FileId> {
-        self.open_files.get(path).cloned()
-    }
+    pub(crate) fn get_file_id(&self, path: &Path) -> Option<FileId> { self.open_files.get(path).cloned() }
 
     #[allow(dead_code)]
     pub fn check_file(&mut self, path: &Path, id: &FileId) -> bool {
@@ -91,9 +87,9 @@ impl FileManager {
         false
     }
 
+    #[allow(dead_code)]
     fn save_new(&mut self, path: &Path, text: &str, id: &FileId) -> Result<(), FileError> {
-        try_save(path, text, CharacterEncoding::Utf8, self.get_info(id))
-            .map_err(|e| FileError::Io(e, path.to_owned()))?;
+        try_save(path, text, CharacterEncoding::Utf8, self.get_info(id)).map_err(|e| FileError::Io(e, path.to_owned()))?;
         let info = FileInfo {
             encoding: CharacterEncoding::Utf8,
             path: path.to_owned(),
@@ -105,6 +101,7 @@ impl FileManager {
         Ok(())
     }
 
+    #[allow(dead_code)]
     fn save_existing(&mut self, path: &Path, text: &String, id: &FileId) -> Result<(), FileError> {
         let prev_path = self.file_info[id].path.clone();
         if prev_path != path {
@@ -114,8 +111,7 @@ impl FileManager {
             return Err(FileError::HasChanged(path.to_owned()));
         } else {
             let encoding = self.file_info[&id].encoding;
-            try_save(path, text, encoding, self.get_info(id))
-                .map_err(|e| FileError::Io(e, path.to_owned()))?;
+            try_save(path, text, encoding, self.get_info(id)).map_err(|e| FileError::Io(e, path.to_owned()))?;
             self.file_info.get_mut(&id).unwrap().modified_time = get_modified_time(path);
         }
         Ok(())

+ 1 - 1
rust-lib/flowy-document/src/services/server/middleware.rs

@@ -15,7 +15,7 @@ impl ResponseMiddleware for DocMiddleware {
 
                 match token {
                     None => {},
-                    Some(token) => {
+                    Some(_token) => {
                         // let error =
                         // WorkspaceError::new(ErrorCode::UserUnauthorized, "");
                         // observable(token,

+ 48 - 7
rust-lib/flowy-document/src/services/server/server_api.rs

@@ -4,18 +4,30 @@ use crate::{
     services::server::DocumentServerAPI,
 };
 use flowy_infra::future::ResultFuture;
-use flowy_net::{config::HEADER_TOKEN, request::HttpRequestBuilder};
+use flowy_net::{config::*, request::HttpRequestBuilder};
 
 pub struct DocServer {}
 
 impl DocumentServerAPI for DocServer {
-    fn create_doc(&self, token: &str, params: CreateDocParams) -> ResultFuture<Doc, DocError> { unimplemented!() }
+    fn create_doc(&self, token: &str, params: CreateDocParams) -> ResultFuture<Doc, DocError> {
+        let token = token.to_owned();
+        ResultFuture::new(async move { create_doc_request(&token, params, DOC_URL.as_ref()).await })
+    }
 
-    fn read_doc(&self, token: &str, params: QueryDocParams) -> ResultFuture<Option<Doc>, DocError> { unimplemented!() }
+    fn read_doc(&self, token: &str, params: QueryDocParams) -> ResultFuture<Option<Doc>, DocError> {
+        let token = token.to_owned();
+        ResultFuture::new(async move { read_doc_request(&token, params, DOC_URL.as_ref()).await })
+    }
 
-    fn update_doc(&self, token: &str, params: UpdateDocParams) -> ResultFuture<(), DocError> { unimplemented!() }
+    fn update_doc(&self, token: &str, params: UpdateDocParams) -> ResultFuture<(), DocError> {
+        let token = token.to_owned();
+        ResultFuture::new(async move { update_doc_request(&token, params, DOC_URL.as_ref()).await })
+    }
 
-    fn delete_doc(&self, token: &str, params: QueryDocParams) -> ResultFuture<(), DocError> { unimplemented!() }
+    fn delete_doc(&self, token: &str, params: QueryDocParams) -> ResultFuture<(), DocError> {
+        let token = token.to_owned();
+        ResultFuture::new(async move { delete_doc_request(&token, params, DOC_URL.as_ref()).await })
+    }
 }
 
 pub(crate) fn request_builder() -> HttpRequestBuilder { HttpRequestBuilder::new().middleware(super::middleware::MIDDLEWARE.clone()) }
@@ -25,9 +37,38 @@ pub async fn create_doc_request(token: &str, params: CreateDocParams, url: &str)
         .post(&url.to_owned())
         .header(HEADER_TOKEN, token)
         .protobuf(params)?
-        .send()
-        .await?
         .response()
         .await?;
     Ok(doc)
 }
+
+pub async fn read_doc_request(token: &str, params: QueryDocParams, url: &str) -> Result<Option<Doc>, DocError> {
+    let doc = request_builder()
+        .get(&url.to_owned())
+        .header(HEADER_TOKEN, token)
+        .protobuf(params)?
+        .option_response()
+        .await?;
+
+    Ok(doc)
+}
+
+pub async fn update_doc_request(token: &str, params: UpdateDocParams, url: &str) -> Result<(), DocError> {
+    let _ = request_builder()
+        .patch(&url.to_owned())
+        .header(HEADER_TOKEN, token)
+        .protobuf(params)?
+        .send()
+        .await?;
+    Ok(())
+}
+
+pub async fn delete_doc_request(token: &str, params: QueryDocParams, url: &str) -> Result<(), DocError> {
+    let _ = request_builder()
+        .delete(url)
+        .header(HEADER_TOKEN, token)
+        .protobuf(params)?
+        .send()
+        .await?;
+    Ok(())
+}

+ 4 - 5
rust-lib/flowy-document/src/services/server/server_api_mock.rs

@@ -3,15 +3,14 @@ use crate::{
     errors::DocError,
     services::server::DocumentServerAPI,
 };
-use flowy_infra::{future::ResultFuture, uuid};
+use flowy_infra::future::ResultFuture;
 pub struct DocServerMock {}
 
 impl DocumentServerAPI for DocServerMock {
-    fn create_doc(&self, _token: &str, _params: CreateDocParams) -> ResultFuture<Doc, DocError> {
-        let uuid = uuid();
+    fn create_doc(&self, _token: &str, params: CreateDocParams) -> ResultFuture<Doc, DocError> {
         let doc = Doc {
-            id: uuid,
-            data: "".to_string(),
+            id: params.id,
+            data: params.data,
         };
 
         ResultFuture::new(async { Ok(doc) })

+ 1 - 2
rust-lib/flowy-document/src/sql_tables/doc/doc_sql.rs

@@ -1,6 +1,5 @@
 use crate::{
     errors::DocError,
-    module::DocumentDatabase,
     sql_tables::doc::{DocTable, DocTableChangeset},
 };
 use flowy_database::{
@@ -8,7 +7,7 @@ use flowy_database::{
     schema::{doc_table, doc_table::dsl},
     SqliteConnection,
 };
-use std::sync::Arc;
+
 pub struct DocTableSql {}
 
 impl DocTableSql {

+ 2 - 3
rust-lib/flowy-document/src/sql_tables/doc/doc_table.rs

@@ -1,6 +1,5 @@
-use crate::entities::doc::{CreateDocParams, Doc, UpdateDocParams};
+use crate::entities::doc::{Doc, UpdateDocParams};
 use flowy_database::schema::doc_table;
-use flowy_infra::timestamp;
 
 #[derive(PartialEq, Clone, Debug, Queryable, Identifiable, Insertable, Associations)]
 #[table_name = "doc_table"]
@@ -14,7 +13,7 @@ impl DocTable {
     pub fn new(doc: Doc) -> Self {
         Self {
             id: doc.id,
-            data: "".to_owned(),
+            data: doc.data,
             version: 0,
         }
     }

+ 20 - 9
rust-lib/flowy-document/tests/editor/doc_test.rs

@@ -2,24 +2,35 @@ use crate::helper::*;
 use flowy_test::FlowyEnv;
 
 #[test]
-fn file_create_test() {
+fn doc_create_test() {
     let sdk = FlowyEnv::setup().sdk;
-    let doc_desc = create_doc(&sdk, "hello world", "flutter ❤️ rust", "123");
-    dbg!(&doc_desc);
+    let doc = create_doc(&sdk, "flutter ❤️ rust");
+    dbg!(&doc);
 
-    let doc = read_doc_data(&sdk, &doc_desc.id, &doc_desc.path);
-    assert_eq!(doc.text, "123".to_owned());
+    let doc = read_doc_data(&sdk, &doc.id);
+    assert_eq!(doc.data, "flutter ❤️ rust".to_owned());
 }
 
 #[test]
-fn file_update_text_test() {
+fn doc_update_test() {
     let sdk = FlowyEnv::setup().sdk;
-    let doc_desc = create_doc(&sdk, "hello world", "flutter ❤️ rust", "");
+    let doc_desc = create_doc(&sdk, "flutter ❤️ rust");
     dbg!(&doc_desc);
 
     let content = "😁😁😁😁😁😁😁😁😁😁".to_owned();
     save_doc(&sdk, &doc_desc, &content);
 
-    let doc = read_doc_data(&sdk, &doc_desc.id, &doc_desc.path);
-    assert_eq!(doc.text, content);
+    let doc = read_doc_data(&sdk, &doc_desc.id);
+    assert_eq!(doc.data, content);
+}
+
+#[test]
+fn doc_update_big_data_test() {
+    let sdk = FlowyEnv::setup().sdk;
+    let doc_desc = create_doc(&sdk, "");
+    let content = "flutter ❤️ rust".repeat(1000000);
+    save_doc(&sdk, &doc_desc, &content);
+
+    let doc = read_doc_data(&sdk, &doc_desc.id);
+    assert_eq!(doc.data, content);
 }

+ 6 - 15
rust-lib/flowy-document/tests/editor/helper.rs

@@ -4,11 +4,9 @@ use flowy_document::{entities::doc::*, event::EditorEvent::*};
 use flowy_infra::uuid;
 use flowy_test::prelude::*;
 
-pub fn create_doc(sdk: &FlowyTestSDK, name: &str, desc: &str, text: &str) -> Doc {
+pub fn create_doc(sdk: &FlowyTestSDK, text: &str) -> Doc {
     let request = CreateDocRequest {
         id: uuid(),
-        name: name.to_owned(),
-        desc: desc.to_owned(),
         data: text.to_owned(),
     };
 
@@ -20,11 +18,9 @@ pub fn create_doc(sdk: &FlowyTestSDK, name: &str, desc: &str, text: &str) -> Doc
     doc
 }
 
-pub fn save_doc(sdk: &FlowyTestSDK, desc: &Doc, content: &str) {
+pub fn save_doc(sdk: &FlowyTestSDK, doc: &Doc, content: &str) {
     let request = UpdateDocRequest {
-        id: desc.id.clone(),
-        name: Some(desc.name.clone()),
-        desc: Some(desc.desc.clone()),
+        id: doc.id.clone(),
         data: Some(content.to_owned()),
     };
 
@@ -46,17 +42,12 @@ pub fn save_doc(sdk: &FlowyTestSDK, desc: &Doc, content: &str) {
 //     doc
 // }
 
-pub(crate) fn read_doc_data(sdk: &FlowyTestSDK, doc_id: &str, path: &str) -> DocData {
-    let request = QueryDocDataRequest {
+pub(crate) fn read_doc_data(sdk: &FlowyTestSDK, doc_id: &str) -> Doc {
+    let request = QueryDocRequest {
         doc_id: doc_id.to_string(),
-        path: path.to_string(),
     };
 
-    let doc = DocTest::new(sdk.clone())
-        .event(ReadDocData)
-        .request(request)
-        .sync_send()
-        .parse::<DocData>();
+    let doc = DocTest::new(sdk.clone()).event(ReadDoc).request(request).sync_send().parse::<Doc>();
 
     doc
 }

+ 3 - 0
rust-lib/flowy-net/src/config.rs

@@ -14,4 +14,7 @@ lazy_static! {
     pub static ref WORKSPACE_URL: String = format!("{}/api/workspace", HOST);
     pub static ref APP_URL: String = format!("{}/api/app", HOST);
     pub static ref VIEW_URL: String = format!("{}/api/view", HOST);
+
+    //
+    pub static ref DOC_URL: String = format!("{}/api/doc", HOST);
 }

+ 1 - 1
rust-lib/flowy-net/src/errors.rs

@@ -42,7 +42,7 @@ impl ServerError {
         self
     }
 
-    pub fn is_not_found(&self) -> bool { self.code == ErrorCode::RecordNotFound }
+    pub fn is_record_not_found(&self) -> bool { self.code == ErrorCode::RecordNotFound }
 
     pub fn is_unauthorized(&self) -> bool { self.code == ErrorCode::UserUnauthorized }
 }

+ 51 - 35
rust-lib/flowy-net/src/request/request.rs

@@ -1,17 +1,8 @@
-use crate::{
-    config::HEADER_TOKEN,
-    errors::{ErrorCode, ServerError},
-    response::FlowyResponse,
-};
+use crate::{config::HEADER_TOKEN, errors::ServerError, response::FlowyResponse};
 use bytes::Bytes;
-use hyper::{http, http::HeaderValue};
+use hyper::http;
 use protobuf::ProtobufError;
-use reqwest::{
-    header::{HeaderMap, ToStrError},
-    Client,
-    Method,
-    Response,
-};
+use reqwest::{header::HeaderMap, Client, Method, Response};
 use std::{
     convert::{TryFrom, TryInto},
     sync::Arc,
@@ -94,7 +85,50 @@ impl HttpRequestBuilder {
         Ok(self)
     }
 
-    pub async fn send(mut self) -> Result<Self, ServerError> {
+    pub async fn send(self) -> Result<(), ServerError> {
+        let _ = self.inner_send().await?;
+        Ok(())
+    }
+
+    pub async fn response<T>(self) -> Result<T, ServerError>
+    where
+        T: TryFrom<Bytes, Error = ProtobufError>,
+    {
+        let builder = self.inner_send().await?;
+        match builder.response {
+            None => Err(unexpected_empty_payload(&builder.url)),
+            Some(data) => Ok(T::try_from(data)?),
+        }
+    }
+
+    pub async fn option_response<T>(self) -> Result<Option<T>, ServerError>
+    where
+        T: TryFrom<Bytes, Error = ProtobufError>,
+    {
+        let result = self.inner_send().await;
+        match result {
+            Ok(builder) => match builder.response {
+                None => Err(unexpected_empty_payload(&builder.url)),
+                Some(data) => Ok(Some(T::try_from(data)?)),
+            },
+            Err(error) => match error.is_record_not_found() {
+                true => Ok(None),
+                false => Err(error),
+            },
+        }
+    }
+
+    fn token(&self) -> Option<String> {
+        match self.headers.get(HEADER_TOKEN) {
+            None => None,
+            Some(header) => match header.to_str() {
+                Ok(val) => Some(val.to_owned()),
+                Err(_) => None,
+            },
+        }
+    }
+
+    async fn inner_send(mut self) -> Result<Self, ServerError> {
         let (tx, rx) = oneshot::channel::<Result<Response, _>>();
         let url = self.url.clone();
         let body = self.body.take();
@@ -132,29 +166,11 @@ impl HttpRequestBuilder {
             Some(error) => Err(error),
         }
     }
+}
 
-    pub async fn response<T2>(self) -> Result<T2, ServerError>
-    where
-        T2: TryFrom<Bytes, Error = ProtobufError>,
-    {
-        match self.response {
-            None => {
-                let msg = format!("Request: {} receives unexpected empty body", self.url);
-                Err(ServerError::payload_none().context(msg))
-            },
-            Some(data) => Ok(T2::try_from(data)?),
-        }
-    }
-
-    fn token(&self) -> Option<String> {
-        match self.headers.get(HEADER_TOKEN) {
-            None => None,
-            Some(header) => match header.to_str() {
-                Ok(val) => Some(val.to_owned()),
-                Err(_) => None,
-            },
-        }
-    }
+fn unexpected_empty_payload(url: &str) -> ServerError {
+    let msg = format!("Request: {} receives unexpected empty payload", url);
+    ServerError::payload_none().context(msg)
 }
 
 async fn flowy_response_from(original: Response) -> Result<FlowyResponse, ServerError> {

+ 1 - 1
rust-lib/flowy-sdk/src/deps_resolve/editor_deps_impl.rs

@@ -27,7 +27,7 @@ impl DocumentUser for EditorUserImpl {
         let dir = self
             .user_session
             .user_dir()
-            .map_err(|e| ErrorBuilder::new(ErrorCode::EditorUserNotLoginYet).error(e).build())?;
+            .map_err(|e| ErrorBuilder::new(ErrorCode::UserUnauthorized).error(e).build())?;
 
         let doc_dir = format!("{}/doc", dir);
         if !Path::new(&doc_dir).exists() {

+ 1 - 0
rust-lib/flowy-sdk/src/lib.rs

@@ -38,6 +38,7 @@ fn crate_log_filter(level: Option<String>) -> String {
     filters.push(format!("flowy_sdk={}", level));
     filters.push(format!("flowy_workspace={}", level));
     filters.push(format!("flowy_user={}", level));
+    filters.push(format!("flowy_document={}", level));
     filters.push(format!("flowy_observable={}", level));
     filters.push(format!("info"));
     filters.join(",")

+ 0 - 1
rust-lib/flowy-user/Cargo.toml

@@ -8,7 +8,6 @@ edition = "2018"
 [dependencies]
 derive_more = {version = "0.99", features = ["display"]}
 flowy-dispatch = { path = "../flowy-dispatch" }
-flowy-log = { path = "../flowy-log" }
 flowy-derive = { path = "../flowy-derive" }
 flowy-database = { path = "../flowy-database" }
 flowy-sqlite = { path = "../flowy-sqlite" }

+ 1 - 1
rust-lib/flowy-user/src/observable/mod.rs

@@ -1,2 +1,2 @@
 mod observable;
-pub use observable::*;
+pub(crate) use observable::*;

+ 2 - 16
rust-lib/flowy-user/src/services/server/server_api.rs

@@ -72,24 +72,12 @@ impl ResponseMiddleware for Middleware {
 pub(crate) fn request_builder() -> HttpRequestBuilder { HttpRequestBuilder::new().middleware(MIDDLEWARE.clone()) }
 
 pub async fn user_sign_up_request(params: SignUpParams, url: &str) -> Result<SignUpResponse, UserError> {
-    let response = request_builder()
-        .post(&url.to_owned())
-        .protobuf(params)?
-        .send()
-        .await?
-        .response()
-        .await?;
+    let response = request_builder().post(&url.to_owned()).protobuf(params)?.response().await?;
     Ok(response)
 }
 
 pub async fn user_sign_in_request(params: SignInParams, url: &str) -> Result<SignInResponse, UserError> {
-    let response = request_builder()
-        .post(&url.to_owned())
-        .protobuf(params)?
-        .send()
-        .await?
-        .response()
-        .await?;
+    let response = request_builder().post(&url.to_owned()).protobuf(params)?.response().await?;
     Ok(response)
 }
 
@@ -102,8 +90,6 @@ pub async fn get_user_profile_request(token: &str, url: &str) -> Result<UserProf
     let user_profile = request_builder()
         .get(&url.to_owned())
         .header(HEADER_TOKEN, token)
-        .send()
-        .await?
         .response()
         .await?;
     Ok(user_profile)

+ 0 - 1
rust-lib/flowy-workspace/Cargo.toml

@@ -7,7 +7,6 @@ edition = "2018"
 
 [dependencies]
 flowy-dispatch = { path = "../flowy-dispatch" }
-flowy-log = { path = "../flowy-log" }
 flowy-derive = { path = "../flowy-derive" }
 flowy-database = { path = "../flowy-database" }
 flowy-sqlite = { path = "../flowy-sqlite" }

+ 1 - 1
rust-lib/flowy-workspace/src/services/server/middleware.rs

@@ -10,7 +10,7 @@ use crate::{
 };
 use flowy_net::{request::ResponseMiddleware, response::FlowyResponse};
 
-struct WorkspaceMiddleware {}
+pub(crate) struct WorkspaceMiddleware {}
 impl ResponseMiddleware for WorkspaceMiddleware {
     fn receive_response(&self, token: &Option<String>, response: &FlowyResponse) {
         if let Some(error) = &response.error {

+ 13 - 50
rust-lib/flowy-workspace/src/services/server/server_api.rs

@@ -15,12 +15,7 @@ use crate::{
     services::server::WorkspaceServerAPI,
 };
 use flowy_infra::future::ResultFuture;
-use flowy_net::{
-    config::*,
-    request::{HttpRequestBuilder, ResponseMiddleware},
-    response::FlowyResponse,
-};
-use std::sync::Arc;
+use flowy_net::{config::*, request::HttpRequestBuilder};
 
 pub struct WorkspaceServer {}
 
@@ -92,27 +87,20 @@ pub async fn create_workspace_request(token: &str, params: CreateWorkspaceParams
         .post(&url.to_owned())
         .header(HEADER_TOKEN, token)
         .protobuf(params)?
-        .send()
-        .await?
         .response()
         .await?;
     Ok(workspace)
 }
 
 pub async fn read_workspaces_request(token: &str, params: QueryWorkspaceParams, url: &str) -> Result<RepeatedWorkspace, WorkspaceError> {
-    let result = request_builder()
+    let repeated_workspace = request_builder()
         .get(&url.to_owned())
         .header(HEADER_TOKEN, token)
         .protobuf(params)?
-        .send()
-        .await?
         .response::<RepeatedWorkspace>()
-        .await;
+        .await?;
 
-    match result {
-        Ok(repeated_workspace) => Ok(repeated_workspace),
-        Err(e) => Err(e.into()),
-    }
+    Ok(repeated_workspace)
 }
 
 pub async fn update_workspace_request(token: &str, params: UpdateWorkspaceParams, url: &str) -> Result<(), WorkspaceError> {
@@ -141,31 +129,20 @@ pub async fn create_app_request(token: &str, params: CreateAppParams, url: &str)
         .post(&url.to_owned())
         .header(HEADER_TOKEN, token)
         .protobuf(params)?
-        .send()
-        .await?
         .response()
         .await?;
     Ok(app)
 }
 
 pub async fn read_app_request(token: &str, params: QueryAppParams, url: &str) -> Result<Option<App>, WorkspaceError> {
-    let result = request_builder()
+    let app = request_builder()
         .get(&url.to_owned())
         .header(HEADER_TOKEN, token)
         .protobuf(params)?
-        .send()
-        .await;
-
-    match result {
-        Ok(builder) => Ok(Some(builder.response::<App>().await?)),
-        Err(e) => {
-            if e.is_not_found() {
-                Ok(None)
-            } else {
-                Err(e.into())
-            }
-        },
-    }
+        .option_response()
+        .await?;
+
+    Ok(app)
 }
 
 pub async fn update_app_request(token: &str, params: UpdateAppParams, url: &str) -> Result<(), WorkspaceError> {
@@ -194,34 +171,20 @@ pub async fn create_view_request(token: &str, params: CreateViewParams, url: &st
         .post(&url.to_owned())
         .header(HEADER_TOKEN, token)
         .protobuf(params)?
-        .send()
-        .await?
         .response()
         .await?;
     Ok(view)
 }
 
 pub async fn read_view_request(token: &str, params: QueryViewParams, url: &str) -> Result<Option<View>, WorkspaceError> {
-    let result = request_builder()
+    let view = request_builder()
         .get(&url.to_owned())
         .header(HEADER_TOKEN, token)
         .protobuf(params)?
-        .send()
-        .await;
+        .option_response()
+        .await?;
 
-    match result {
-        Ok(builder) => {
-            let view = builder.response::<View>().await?;
-            Ok(Some(view))
-        },
-        Err(e) => {
-            if e.is_not_found() {
-                Ok(None)
-            } else {
-                Err(e.into())
-            }
-        },
-    }
+    Ok(view)
 }
 
 pub async fn update_view_request(token: &str, params: UpdateViewParams, url: &str) -> Result<(), WorkspaceError> {

+ 4 - 8
rust-lib/flowy-workspace/src/sql_tables/workspace/workspace_sql.rs

@@ -59,14 +59,10 @@ impl WorkspaceTableSql {
         workspace_id: &str,
         conn: &SqliteConnection,
     ) -> Result<Vec<AppTable>, WorkspaceError> {
-        let apps = conn.immediate_transaction::<_, WorkspaceError, _>(|| {
-            let workspace_table: WorkspaceTable = dsl::workspace_table
-                .filter(workspace_table::id.eq(workspace_id))
-                .first::<WorkspaceTable>(conn)?;
-            let apps = AppTable::belonging_to(&workspace_table).load::<AppTable>(conn)?;
-            Ok(apps)
-        })?;
-
+        let workspace_table: WorkspaceTable = dsl::workspace_table
+            .filter(workspace_table::id.eq(workspace_id))
+            .first::<WorkspaceTable>(conn)?;
+        let apps = AppTable::belonging_to(&workspace_table).load::<AppTable>(conn)?;
         Ok(apps)
     }
 }