浏览代码

refactor flowy-document & config server api

appflowy 3 年之前
父节点
当前提交
a5a07944dc
共有 67 个文件被更改,包括 1439 次插入1389 次删除
  1. 1 1
      app_flowy/lib/workspace/presentation/home/home_screen.dart
  2. 64 106
      app_flowy/packages/flowy_sdk/lib/protobuf/flowy-document/doc_create.pb.dart
  3. 15 18
      app_flowy/packages/flowy_sdk/lib/protobuf/flowy-document/doc_create.pbjson.dart
  4. 87 67
      app_flowy/packages/flowy_sdk/lib/protobuf/flowy-document/doc_modify.pb.dart
  5. 17 7
      app_flowy/packages/flowy_sdk/lib/protobuf/flowy-document/doc_modify.pbjson.dart
  6. 13 27
      app_flowy/packages/flowy_sdk/lib/protobuf/flowy-document/doc_query.pb.dart
  7. 5 6
      app_flowy/packages/flowy_sdk/lib/protobuf/flowy-document/doc_query.pbjson.dart
  8. 4 4
      app_flowy/packages/flowy_sdk/lib/protobuf/flowy-document/errors.pb.dart
  9. 13 23
      app_flowy/packages/flowy_sdk/lib/protobuf/flowy-document/errors.pbenum.dart
  10. 11 16
      app_flowy/packages/flowy_sdk/lib/protobuf/flowy-document/errors.pbjson.dart
  11. 4 4
      app_flowy/packages/flowy_sdk/lib/protobuf/flowy-document/event.pbenum.dart
  12. 3 3
      app_flowy/packages/flowy_sdk/lib/protobuf/flowy-document/event.pbjson.dart
  13. 11 0
      app_flowy/packages/flowy_sdk/lib/protobuf/flowy-document/observable.pb.dart
  14. 24 0
      app_flowy/packages/flowy_sdk/lib/protobuf/flowy-document/observable.pbenum.dart
  15. 20 0
      app_flowy/packages/flowy_sdk/lib/protobuf/flowy-document/observable.pbjson.dart
  16. 9 0
      app_flowy/packages/flowy_sdk/lib/protobuf/flowy-document/observable.pbserver.dart
  17. 1 0
      app_flowy/packages/flowy_sdk/lib/protobuf/flowy-document/protobuf.dart
  18. 1 5
      rust-lib/flowy-database/migrations/2021-07-22-234458_flowy-editor/up.sql
  19. 1 5
      rust-lib/flowy-database/src/schema.rs
  20. 5 4
      rust-lib/flowy-derive/src/derive_cache/derive_cache.rs
  21. 8 1
      rust-lib/flowy-document/Cargo.toml
  22. 1 1
      rust-lib/flowy-document/Flowy.toml
  23. 11 44
      rust-lib/flowy-document/src/entities/doc/doc_create.rs
  24. 9 48
      rust-lib/flowy-document/src/entities/doc/doc_modify.rs
  25. 4 44
      rust-lib/flowy-document/src/entities/doc/doc_query.rs
  26. 39 34
      rust-lib/flowy-document/src/errors.rs
  27. 7 7
      rust-lib/flowy-document/src/event.rs
  28. 14 58
      rust-lib/flowy-document/src/handlers/doc_handler.rs
  29. 1 0
      rust-lib/flowy-document/src/lib.rs
  30. 9 6
      rust-lib/flowy-document/src/module.rs
  31. 3 0
      rust-lib/flowy-document/src/observable/mod.rs
  32. 13 0
      rust-lib/flowy-document/src/observable/observable.rs
  33. 167 303
      rust-lib/flowy-document/src/protobuf/model/doc_create.rs
  34. 261 182
      rust-lib/flowy-document/src/protobuf/model/doc_modify.rs
  35. 30 75
      rust-lib/flowy-document/src/protobuf/model/doc_query.rs
  36. 51 79
      rust-lib/flowy-document/src/protobuf/model/errors.rs
  37. 19 19
      rust-lib/flowy-document/src/protobuf/model/event.rs
  38. 3 0
      rust-lib/flowy-document/src/protobuf/model/mod.rs
  39. 92 0
      rust-lib/flowy-document/src/protobuf/model/observable.rs
  40. 6 9
      rust-lib/flowy-document/src/protobuf/proto/doc_create.proto
  41. 5 3
      rust-lib/flowy-document/src/protobuf/proto/doc_modify.proto
  42. 1 2
      rust-lib/flowy-document/src/protobuf/proto/doc_query.proto
  43. 6 11
      rust-lib/flowy-document/src/protobuf/proto/errors.proto
  44. 2 2
      rust-lib/flowy-document/src/protobuf/proto/event.proto
  45. 5 0
      rust-lib/flowy-document/src/protobuf/proto/observable.proto
  46. 95 19
      rust-lib/flowy-document/src/services/doc_controller.rs
  47. 1 0
      rust-lib/flowy-document/src/services/mod.rs
  48. 29 0
      rust-lib/flowy-document/src/services/server/middleware.rs
  49. 32 0
      rust-lib/flowy-document/src/services/server/mod.rs
  50. 33 0
      rust-lib/flowy-document/src/services/server/server_api.rs
  51. 27 0
      rust-lib/flowy-document/src/services/server/server_api_mock.rs
  52. 13 15
      rust-lib/flowy-document/src/sql_tables/doc/doc_sql.rs
  53. 11 24
      rust-lib/flowy-document/src/sql_tables/doc/doc_table.rs
  54. 5 5
      rust-lib/flowy-document/tests/editor/helper.rs
  55. 3 3
      rust-lib/flowy-net/src/errors.rs
  56. 1 1
      rust-lib/flowy-sdk/Cargo.toml
  57. 15 3
      rust-lib/flowy-sdk/src/deps_resolve/editor_deps_impl.rs
  58. 1 1
      rust-lib/flowy-user/src/errors.rs
  59. 1 1
      rust-lib/flowy-workspace/src/errors.rs
  60. 1 1
      rust-lib/flowy-workspace/src/observable/mod.rs
  61. 0 7
      rust-lib/flowy-workspace/src/observable/observable.rs
  62. 35 27
      rust-lib/flowy-workspace/src/services/app_controller.rs
  63. 30 0
      rust-lib/flowy-workspace/src/services/server/middleware.rs
  64. 3 1
      rust-lib/flowy-workspace/src/services/server/mod.rs
  65. 1 28
      rust-lib/flowy-workspace/src/services/server/server_api.rs
  66. 6 6
      rust-lib/flowy-workspace/src/services/view_controller.rs
  67. 20 23
      rust-lib/flowy-workspace/src/services/workspace_controller.rs

+ 1 - 1
app_flowy/lib/workspace/presentation/home/home_screen.dart

@@ -35,7 +35,7 @@ class HomeScreen extends StatelessWidget {
             state.map(
               loading: (_) {},
               unauthorized: (unauthorized) {
-                //
+                // TODO: push to login screen when user token was invalid
               },
             );
           },

+ 64 - 106
app_flowy/packages/flowy_sdk/lib/protobuf/flowy-document/doc_create.pb.dart

@@ -12,31 +12,21 @@ import 'package:protobuf/protobuf.dart' as $pb;
 class CreateDocRequest extends $pb.GeneratedMessage {
   static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'CreateDocRequest', createEmptyInstance: create)
     ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'id')
-    ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'name')
-    ..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'desc')
-    ..aOS(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'text')
+    ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'data')
     ..hasRequiredFields = false
   ;
 
   CreateDocRequest._() : super();
   factory CreateDocRequest({
     $core.String? id,
-    $core.String? name,
-    $core.String? desc,
-    $core.String? text,
+    $core.String? data,
   }) {
     final _result = create();
     if (id != null) {
       _result.id = id;
     }
-    if (name != null) {
-      _result.name = name;
-    }
-    if (desc != null) {
-      _result.desc = desc;
-    }
-    if (text != null) {
-      _result.text = text;
+    if (data != null) {
+      _result.data = data;
     }
     return _result;
   }
@@ -71,84 +61,56 @@ class CreateDocRequest extends $pb.GeneratedMessage {
   void clearId() => clearField(1);
 
   @$pb.TagNumber(2)
-  $core.String get name => $_getSZ(1);
+  $core.String get data => $_getSZ(1);
   @$pb.TagNumber(2)
-  set name($core.String v) { $_setString(1, v); }
+  set data($core.String v) { $_setString(1, v); }
   @$pb.TagNumber(2)
-  $core.bool hasName() => $_has(1);
+  $core.bool hasData() => $_has(1);
   @$pb.TagNumber(2)
-  void clearName() => clearField(2);
-
-  @$pb.TagNumber(3)
-  $core.String get desc => $_getSZ(2);
-  @$pb.TagNumber(3)
-  set desc($core.String v) { $_setString(2, v); }
-  @$pb.TagNumber(3)
-  $core.bool hasDesc() => $_has(2);
-  @$pb.TagNumber(3)
-  void clearDesc() => clearField(3);
-
-  @$pb.TagNumber(4)
-  $core.String get text => $_getSZ(3);
-  @$pb.TagNumber(4)
-  set text($core.String v) { $_setString(3, v); }
-  @$pb.TagNumber(4)
-  $core.bool hasText() => $_has(3);
-  @$pb.TagNumber(4)
-  void clearText() => clearField(4);
+  void clearData() => clearField(2);
 }
 
-class DocInfo extends $pb.GeneratedMessage {
-  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'DocInfo', createEmptyInstance: create)
+class CreateDocParams extends $pb.GeneratedMessage {
+  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'CreateDocParams', createEmptyInstance: create)
     ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'id')
-    ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'name')
-    ..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'desc')
-    ..aOS(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'path')
+    ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'data')
     ..hasRequiredFields = false
   ;
 
-  DocInfo._() : super();
-  factory DocInfo({
+  CreateDocParams._() : super();
+  factory CreateDocParams({
     $core.String? id,
-    $core.String? name,
-    $core.String? desc,
-    $core.String? path,
+    $core.String? data,
   }) {
     final _result = create();
     if (id != null) {
       _result.id = id;
     }
-    if (name != null) {
-      _result.name = name;
-    }
-    if (desc != null) {
-      _result.desc = desc;
-    }
-    if (path != null) {
-      _result.path = path;
+    if (data != null) {
+      _result.data = data;
     }
     return _result;
   }
-  factory DocInfo.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
-  factory DocInfo.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
+  factory CreateDocParams.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
+  factory CreateDocParams.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
   @$core.Deprecated(
   'Using this can add significant overhead to your binary. '
   'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
   'Will be removed in next major version')
-  DocInfo clone() => DocInfo()..mergeFromMessage(this);
+  CreateDocParams clone() => CreateDocParams()..mergeFromMessage(this);
   @$core.Deprecated(
   'Using this can add significant overhead to your binary. '
   'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
   'Will be removed in next major version')
-  DocInfo copyWith(void Function(DocInfo) updates) => super.copyWith((message) => updates(message as DocInfo)) as DocInfo; // ignore: deprecated_member_use
+  CreateDocParams copyWith(void Function(CreateDocParams) updates) => super.copyWith((message) => updates(message as CreateDocParams)) as CreateDocParams; // ignore: deprecated_member_use
   $pb.BuilderInfo get info_ => _i;
   @$core.pragma('dart2js:noInline')
-  static DocInfo create() => DocInfo._();
-  DocInfo createEmptyInstance() => create();
-  static $pb.PbList<DocInfo> createRepeated() => $pb.PbList<DocInfo>();
+  static CreateDocParams create() => CreateDocParams._();
+  CreateDocParams createEmptyInstance() => create();
+  static $pb.PbList<CreateDocParams> createRepeated() => $pb.PbList<CreateDocParams>();
   @$core.pragma('dart2js:noInline')
-  static DocInfo getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<DocInfo>(create);
-  static DocInfo? _defaultInstance;
+  static CreateDocParams getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<CreateDocParams>(create);
+  static CreateDocParams? _defaultInstance;
 
   @$pb.TagNumber(1)
   $core.String get id => $_getSZ(0);
@@ -160,77 +122,73 @@ class DocInfo extends $pb.GeneratedMessage {
   void clearId() => clearField(1);
 
   @$pb.TagNumber(2)
-  $core.String get name => $_getSZ(1);
+  $core.String get data => $_getSZ(1);
   @$pb.TagNumber(2)
-  set name($core.String v) { $_setString(1, v); }
+  set data($core.String v) { $_setString(1, v); }
   @$pb.TagNumber(2)
-  $core.bool hasName() => $_has(1);
+  $core.bool hasData() => $_has(1);
   @$pb.TagNumber(2)
-  void clearName() => clearField(2);
-
-  @$pb.TagNumber(3)
-  $core.String get desc => $_getSZ(2);
-  @$pb.TagNumber(3)
-  set desc($core.String v) { $_setString(2, v); }
-  @$pb.TagNumber(3)
-  $core.bool hasDesc() => $_has(2);
-  @$pb.TagNumber(3)
-  void clearDesc() => clearField(3);
-
-  @$pb.TagNumber(4)
-  $core.String get path => $_getSZ(3);
-  @$pb.TagNumber(4)
-  set path($core.String v) { $_setString(3, v); }
-  @$pb.TagNumber(4)
-  $core.bool hasPath() => $_has(3);
-  @$pb.TagNumber(4)
-  void clearPath() => clearField(4);
+  void clearData() => clearField(2);
 }
 
-class DocData extends $pb.GeneratedMessage {
-  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'DocData', createEmptyInstance: create)
-    ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'text')
+class Doc extends $pb.GeneratedMessage {
+  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'Doc', createEmptyInstance: create)
+    ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'id')
+    ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'data')
     ..hasRequiredFields = false
   ;
 
-  DocData._() : super();
-  factory DocData({
-    $core.String? text,
+  Doc._() : super();
+  factory Doc({
+    $core.String? id,
+    $core.String? data,
   }) {
     final _result = create();
-    if (text != null) {
-      _result.text = text;
+    if (id != null) {
+      _result.id = id;
+    }
+    if (data != null) {
+      _result.data = data;
     }
     return _result;
   }
-  factory DocData.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
-  factory DocData.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
+  factory Doc.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
+  factory Doc.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
   @$core.Deprecated(
   'Using this can add significant overhead to your binary. '
   'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
   'Will be removed in next major version')
-  DocData clone() => DocData()..mergeFromMessage(this);
+  Doc clone() => Doc()..mergeFromMessage(this);
   @$core.Deprecated(
   'Using this can add significant overhead to your binary. '
   'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
   'Will be removed in next major version')
-  DocData copyWith(void Function(DocData) updates) => super.copyWith((message) => updates(message as DocData)) as DocData; // ignore: deprecated_member_use
+  Doc copyWith(void Function(Doc) updates) => super.copyWith((message) => updates(message as Doc)) as Doc; // ignore: deprecated_member_use
   $pb.BuilderInfo get info_ => _i;
   @$core.pragma('dart2js:noInline')
-  static DocData create() => DocData._();
-  DocData createEmptyInstance() => create();
-  static $pb.PbList<DocData> createRepeated() => $pb.PbList<DocData>();
+  static Doc create() => Doc._();
+  Doc createEmptyInstance() => create();
+  static $pb.PbList<Doc> createRepeated() => $pb.PbList<Doc>();
   @$core.pragma('dart2js:noInline')
-  static DocData getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<DocData>(create);
-  static DocData? _defaultInstance;
+  static Doc getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<Doc>(create);
+  static Doc? _defaultInstance;
 
   @$pb.TagNumber(1)
-  $core.String get text => $_getSZ(0);
+  $core.String get id => $_getSZ(0);
   @$pb.TagNumber(1)
-  set text($core.String v) { $_setString(0, v); }
+  set id($core.String v) { $_setString(0, v); }
   @$pb.TagNumber(1)
-  $core.bool hasText() => $_has(0);
+  $core.bool hasId() => $_has(0);
   @$pb.TagNumber(1)
-  void clearText() => clearField(1);
+  void clearId() => clearField(1);
+
+  @$pb.TagNumber(2)
+  $core.String get data => $_getSZ(1);
+  @$pb.TagNumber(2)
+  set data($core.String v) { $_setString(1, v); }
+  @$pb.TagNumber(2)
+  $core.bool hasData() => $_has(1);
+  @$pb.TagNumber(2)
+  void clearData() => clearField(2);
 }
 

+ 15 - 18
app_flowy/packages/flowy_sdk/lib/protobuf/flowy-document/doc_create.pbjson.dart

@@ -13,34 +13,31 @@ const CreateDocRequest$json = const {
   '1': 'CreateDocRequest',
   '2': const [
     const {'1': 'id', '3': 1, '4': 1, '5': 9, '10': 'id'},
-    const {'1': 'name', '3': 2, '4': 1, '5': 9, '10': 'name'},
-    const {'1': 'desc', '3': 3, '4': 1, '5': 9, '10': 'desc'},
-    const {'1': 'text', '3': 4, '4': 1, '5': 9, '10': 'text'},
+    const {'1': 'data', '3': 2, '4': 1, '5': 9, '10': 'data'},
   ],
 };
 
 /// Descriptor for `CreateDocRequest`. Decode as a `google.protobuf.DescriptorProto`.
-final $typed_data.Uint8List createDocRequestDescriptor = $convert.base64Decode('ChBDcmVhdGVEb2NSZXF1ZXN0Eg4KAmlkGAEgASgJUgJpZBISCgRuYW1lGAIgASgJUgRuYW1lEhIKBGRlc2MYAyABKAlSBGRlc2MSEgoEdGV4dBgEIAEoCVIEdGV4dA==');
-@$core.Deprecated('Use docInfoDescriptor instead')
-const DocInfo$json = const {
-  '1': 'DocInfo',
+final $typed_data.Uint8List createDocRequestDescriptor = $convert.base64Decode('ChBDcmVhdGVEb2NSZXF1ZXN0Eg4KAmlkGAEgASgJUgJpZBISCgRkYXRhGAIgASgJUgRkYXRh');
+@$core.Deprecated('Use createDocParamsDescriptor instead')
+const CreateDocParams$json = const {
+  '1': 'CreateDocParams',
   '2': const [
     const {'1': 'id', '3': 1, '4': 1, '5': 9, '10': 'id'},
-    const {'1': 'name', '3': 2, '4': 1, '5': 9, '10': 'name'},
-    const {'1': 'desc', '3': 3, '4': 1, '5': 9, '10': 'desc'},
-    const {'1': 'path', '3': 4, '4': 1, '5': 9, '10': 'path'},
+    const {'1': 'data', '3': 2, '4': 1, '5': 9, '10': 'data'},
   ],
 };
 
-/// Descriptor for `DocInfo`. Decode as a `google.protobuf.DescriptorProto`.
-final $typed_data.Uint8List docInfoDescriptor = $convert.base64Decode('CgdEb2NJbmZvEg4KAmlkGAEgASgJUgJpZBISCgRuYW1lGAIgASgJUgRuYW1lEhIKBGRlc2MYAyABKAlSBGRlc2MSEgoEcGF0aBgEIAEoCVIEcGF0aA==');
-@$core.Deprecated('Use docDataDescriptor instead')
-const DocData$json = const {
-  '1': 'DocData',
+/// Descriptor for `CreateDocParams`. Decode as a `google.protobuf.DescriptorProto`.
+final $typed_data.Uint8List createDocParamsDescriptor = $convert.base64Decode('Cg9DcmVhdGVEb2NQYXJhbXMSDgoCaWQYASABKAlSAmlkEhIKBGRhdGEYAiABKAlSBGRhdGE=');
+@$core.Deprecated('Use docDescriptor instead')
+const Doc$json = const {
+  '1': 'Doc',
   '2': const [
-    const {'1': 'text', '3': 1, '4': 1, '5': 9, '10': 'text'},
+    const {'1': 'id', '3': 1, '4': 1, '5': 9, '10': 'id'},
+    const {'1': 'data', '3': 2, '4': 1, '5': 9, '10': 'data'},
   ],
 };
 
-/// Descriptor for `DocData`. Decode as a `google.protobuf.DescriptorProto`.
-final $typed_data.Uint8List docDataDescriptor = $convert.base64Decode('CgdEb2NEYXRhEhIKBHRleHQYASABKAlSBHRleHQ=');
+/// Descriptor for `Doc`. Decode as a `google.protobuf.DescriptorProto`.
+final $typed_data.Uint8List docDescriptor = $convert.base64Decode('CgNEb2MSDgoCaWQYASABKAlSAmlkEhIKBGRhdGEYAiABKAlSBGRhdGE=');

+ 87 - 67
app_flowy/packages/flowy_sdk/lib/protobuf/flowy-document/doc_modify.pb.dart

@@ -9,64 +9,34 @@ import 'dart:core' as $core;
 
 import 'package:protobuf/protobuf.dart' as $pb;
 
-enum UpdateDocRequest_OneOfName {
-  name, 
-  notSet
-}
-
-enum UpdateDocRequest_OneOfDesc {
-  desc, 
-  notSet
-}
-
-enum UpdateDocRequest_OneOfText {
-  text, 
+enum UpdateDocRequest_OneOfData {
+  data, 
   notSet
 }
 
 class UpdateDocRequest extends $pb.GeneratedMessage {
-  static const $core.Map<$core.int, UpdateDocRequest_OneOfName> _UpdateDocRequest_OneOfNameByTag = {
-    2 : UpdateDocRequest_OneOfName.name,
-    0 : UpdateDocRequest_OneOfName.notSet
-  };
-  static const $core.Map<$core.int, UpdateDocRequest_OneOfDesc> _UpdateDocRequest_OneOfDescByTag = {
-    3 : UpdateDocRequest_OneOfDesc.desc,
-    0 : UpdateDocRequest_OneOfDesc.notSet
-  };
-  static const $core.Map<$core.int, UpdateDocRequest_OneOfText> _UpdateDocRequest_OneOfTextByTag = {
-    4 : UpdateDocRequest_OneOfText.text,
-    0 : UpdateDocRequest_OneOfText.notSet
+  static const $core.Map<$core.int, UpdateDocRequest_OneOfData> _UpdateDocRequest_OneOfDataByTag = {
+    2 : UpdateDocRequest_OneOfData.data,
+    0 : UpdateDocRequest_OneOfData.notSet
   };
   static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'UpdateDocRequest', createEmptyInstance: create)
     ..oo(0, [2])
-    ..oo(1, [3])
-    ..oo(2, [4])
     ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'id')
-    ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'name')
-    ..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'desc')
-    ..aOS(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'text')
+    ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'data')
     ..hasRequiredFields = false
   ;
 
   UpdateDocRequest._() : super();
   factory UpdateDocRequest({
     $core.String? id,
-    $core.String? name,
-    $core.String? desc,
-    $core.String? text,
+    $core.String? data,
   }) {
     final _result = create();
     if (id != null) {
       _result.id = id;
     }
-    if (name != null) {
-      _result.name = name;
-    }
-    if (desc != null) {
-      _result.desc = desc;
-    }
-    if (text != null) {
-      _result.text = text;
+    if (data != null) {
+      _result.data = data;
     }
     return _result;
   }
@@ -91,14 +61,8 @@ class UpdateDocRequest extends $pb.GeneratedMessage {
   static UpdateDocRequest getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<UpdateDocRequest>(create);
   static UpdateDocRequest? _defaultInstance;
 
-  UpdateDocRequest_OneOfName whichOneOfName() => _UpdateDocRequest_OneOfNameByTag[$_whichOneof(0)]!;
-  void clearOneOfName() => clearField($_whichOneof(0));
-
-  UpdateDocRequest_OneOfDesc whichOneOfDesc() => _UpdateDocRequest_OneOfDescByTag[$_whichOneof(1)]!;
-  void clearOneOfDesc() => clearField($_whichOneof(1));
-
-  UpdateDocRequest_OneOfText whichOneOfText() => _UpdateDocRequest_OneOfTextByTag[$_whichOneof(2)]!;
-  void clearOneOfText() => clearField($_whichOneof(2));
+  UpdateDocRequest_OneOfData whichOneOfData() => _UpdateDocRequest_OneOfDataByTag[$_whichOneof(0)]!;
+  void clearOneOfData() => clearField($_whichOneof(0));
 
   @$pb.TagNumber(1)
   $core.String get id => $_getSZ(0);
@@ -110,30 +74,86 @@ class UpdateDocRequest extends $pb.GeneratedMessage {
   void clearId() => clearField(1);
 
   @$pb.TagNumber(2)
-  $core.String get name => $_getSZ(1);
+  $core.String get data => $_getSZ(1);
   @$pb.TagNumber(2)
-  set name($core.String v) { $_setString(1, v); }
+  set data($core.String v) { $_setString(1, v); }
   @$pb.TagNumber(2)
-  $core.bool hasName() => $_has(1);
+  $core.bool hasData() => $_has(1);
   @$pb.TagNumber(2)
-  void clearName() => clearField(2);
+  void clearData() => clearField(2);
+}
+
+enum UpdateDocParams_OneOfData {
+  data, 
+  notSet
+}
+
+class UpdateDocParams extends $pb.GeneratedMessage {
+  static const $core.Map<$core.int, UpdateDocParams_OneOfData> _UpdateDocParams_OneOfDataByTag = {
+    2 : UpdateDocParams_OneOfData.data,
+    0 : UpdateDocParams_OneOfData.notSet
+  };
+  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'UpdateDocParams', createEmptyInstance: create)
+    ..oo(0, [2])
+    ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'id')
+    ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'data')
+    ..hasRequiredFields = false
+  ;
+
+  UpdateDocParams._() : super();
+  factory UpdateDocParams({
+    $core.String? id,
+    $core.String? data,
+  }) {
+    final _result = create();
+    if (id != null) {
+      _result.id = id;
+    }
+    if (data != null) {
+      _result.data = data;
+    }
+    return _result;
+  }
+  factory UpdateDocParams.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
+  factory UpdateDocParams.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
+  @$core.Deprecated(
+  'Using this can add significant overhead to your binary. '
+  'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
+  'Will be removed in next major version')
+  UpdateDocParams clone() => UpdateDocParams()..mergeFromMessage(this);
+  @$core.Deprecated(
+  'Using this can add significant overhead to your binary. '
+  'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
+  'Will be removed in next major version')
+  UpdateDocParams copyWith(void Function(UpdateDocParams) updates) => super.copyWith((message) => updates(message as UpdateDocParams)) as UpdateDocParams; // ignore: deprecated_member_use
+  $pb.BuilderInfo get info_ => _i;
+  @$core.pragma('dart2js:noInline')
+  static UpdateDocParams create() => UpdateDocParams._();
+  UpdateDocParams createEmptyInstance() => create();
+  static $pb.PbList<UpdateDocParams> createRepeated() => $pb.PbList<UpdateDocParams>();
+  @$core.pragma('dart2js:noInline')
+  static UpdateDocParams getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<UpdateDocParams>(create);
+  static UpdateDocParams? _defaultInstance;
+
+  UpdateDocParams_OneOfData whichOneOfData() => _UpdateDocParams_OneOfDataByTag[$_whichOneof(0)]!;
+  void clearOneOfData() => clearField($_whichOneof(0));
 
-  @$pb.TagNumber(3)
-  $core.String get desc => $_getSZ(2);
-  @$pb.TagNumber(3)
-  set desc($core.String v) { $_setString(2, v); }
-  @$pb.TagNumber(3)
-  $core.bool hasDesc() => $_has(2);
-  @$pb.TagNumber(3)
-  void clearDesc() => clearField(3);
+  @$pb.TagNumber(1)
+  $core.String get id => $_getSZ(0);
+  @$pb.TagNumber(1)
+  set id($core.String v) { $_setString(0, v); }
+  @$pb.TagNumber(1)
+  $core.bool hasId() => $_has(0);
+  @$pb.TagNumber(1)
+  void clearId() => clearField(1);
 
-  @$pb.TagNumber(4)
-  $core.String get text => $_getSZ(3);
-  @$pb.TagNumber(4)
-  set text($core.String v) { $_setString(3, v); }
-  @$pb.TagNumber(4)
-  $core.bool hasText() => $_has(3);
-  @$pb.TagNumber(4)
-  void clearText() => clearField(4);
+  @$pb.TagNumber(2)
+  $core.String get data => $_getSZ(1);
+  @$pb.TagNumber(2)
+  set data($core.String v) { $_setString(1, v); }
+  @$pb.TagNumber(2)
+  $core.bool hasData() => $_has(1);
+  @$pb.TagNumber(2)
+  void clearData() => clearField(2);
 }
 

+ 17 - 7
app_flowy/packages/flowy_sdk/lib/protobuf/flowy-document/doc_modify.pbjson.dart

@@ -13,16 +13,26 @@ const UpdateDocRequest$json = const {
   '1': 'UpdateDocRequest',
   '2': const [
     const {'1': 'id', '3': 1, '4': 1, '5': 9, '10': 'id'},
-    const {'1': 'name', '3': 2, '4': 1, '5': 9, '9': 0, '10': 'name'},
-    const {'1': 'desc', '3': 3, '4': 1, '5': 9, '9': 1, '10': 'desc'},
-    const {'1': 'text', '3': 4, '4': 1, '5': 9, '9': 2, '10': 'text'},
+    const {'1': 'data', '3': 2, '4': 1, '5': 9, '9': 0, '10': 'data'},
   ],
   '8': const [
-    const {'1': 'one_of_name'},
-    const {'1': 'one_of_desc'},
-    const {'1': 'one_of_text'},
+    const {'1': 'one_of_data'},
   ],
 };
 
 /// Descriptor for `UpdateDocRequest`. Decode as a `google.protobuf.DescriptorProto`.
-final $typed_data.Uint8List updateDocRequestDescriptor = $convert.base64Decode('ChBVcGRhdGVEb2NSZXF1ZXN0Eg4KAmlkGAEgASgJUgJpZBIUCgRuYW1lGAIgASgJSABSBG5hbWUSFAoEZGVzYxgDIAEoCUgBUgRkZXNjEhQKBHRleHQYBCABKAlIAlIEdGV4dEINCgtvbmVfb2ZfbmFtZUINCgtvbmVfb2ZfZGVzY0INCgtvbmVfb2ZfdGV4dA==');
+final $typed_data.Uint8List updateDocRequestDescriptor = $convert.base64Decode('ChBVcGRhdGVEb2NSZXF1ZXN0Eg4KAmlkGAEgASgJUgJpZBIUCgRkYXRhGAIgASgJSABSBGRhdGFCDQoLb25lX29mX2RhdGE=');
+@$core.Deprecated('Use updateDocParamsDescriptor instead')
+const UpdateDocParams$json = const {
+  '1': 'UpdateDocParams',
+  '2': const [
+    const {'1': 'id', '3': 1, '4': 1, '5': 9, '10': 'id'},
+    const {'1': 'data', '3': 2, '4': 1, '5': 9, '9': 0, '10': 'data'},
+  ],
+  '8': const [
+    const {'1': 'one_of_data'},
+  ],
+};
+
+/// Descriptor for `UpdateDocParams`. Decode as a `google.protobuf.DescriptorProto`.
+final $typed_data.Uint8List updateDocParamsDescriptor = $convert.base64Decode('Cg9VcGRhdGVEb2NQYXJhbXMSDgoCaWQYASABKAlSAmlkEhQKBGRhdGEYAiABKAlIAFIEZGF0YUINCgtvbmVfb2ZfZGF0YQ==');

+ 13 - 27
app_flowy/packages/flowy_sdk/lib/protobuf/flowy-document/doc_query.pb.dart

@@ -56,47 +56,42 @@ class QueryDocRequest extends $pb.GeneratedMessage {
   void clearDocId() => clearField(1);
 }
 
-class QueryDocDataRequest extends $pb.GeneratedMessage {
-  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'QueryDocDataRequest', createEmptyInstance: create)
+class QueryDocParams extends $pb.GeneratedMessage {
+  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'QueryDocParams', createEmptyInstance: create)
     ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'docId')
-    ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'path')
     ..hasRequiredFields = false
   ;
 
-  QueryDocDataRequest._() : super();
-  factory QueryDocDataRequest({
+  QueryDocParams._() : super();
+  factory QueryDocParams({
     $core.String? docId,
-    $core.String? path,
   }) {
     final _result = create();
     if (docId != null) {
       _result.docId = docId;
     }
-    if (path != null) {
-      _result.path = path;
-    }
     return _result;
   }
-  factory QueryDocDataRequest.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
-  factory QueryDocDataRequest.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
+  factory QueryDocParams.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
+  factory QueryDocParams.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
   @$core.Deprecated(
   'Using this can add significant overhead to your binary. '
   'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
   'Will be removed in next major version')
-  QueryDocDataRequest clone() => QueryDocDataRequest()..mergeFromMessage(this);
+  QueryDocParams clone() => QueryDocParams()..mergeFromMessage(this);
   @$core.Deprecated(
   'Using this can add significant overhead to your binary. '
   'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
   'Will be removed in next major version')
-  QueryDocDataRequest copyWith(void Function(QueryDocDataRequest) updates) => super.copyWith((message) => updates(message as QueryDocDataRequest)) as QueryDocDataRequest; // ignore: deprecated_member_use
+  QueryDocParams copyWith(void Function(QueryDocParams) updates) => super.copyWith((message) => updates(message as QueryDocParams)) as QueryDocParams; // ignore: deprecated_member_use
   $pb.BuilderInfo get info_ => _i;
   @$core.pragma('dart2js:noInline')
-  static QueryDocDataRequest create() => QueryDocDataRequest._();
-  QueryDocDataRequest createEmptyInstance() => create();
-  static $pb.PbList<QueryDocDataRequest> createRepeated() => $pb.PbList<QueryDocDataRequest>();
+  static QueryDocParams create() => QueryDocParams._();
+  QueryDocParams createEmptyInstance() => create();
+  static $pb.PbList<QueryDocParams> createRepeated() => $pb.PbList<QueryDocParams>();
   @$core.pragma('dart2js:noInline')
-  static QueryDocDataRequest getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<QueryDocDataRequest>(create);
-  static QueryDocDataRequest? _defaultInstance;
+  static QueryDocParams getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<QueryDocParams>(create);
+  static QueryDocParams? _defaultInstance;
 
   @$pb.TagNumber(1)
   $core.String get docId => $_getSZ(0);
@@ -106,14 +101,5 @@ class QueryDocDataRequest extends $pb.GeneratedMessage {
   $core.bool hasDocId() => $_has(0);
   @$pb.TagNumber(1)
   void clearDocId() => clearField(1);
-
-  @$pb.TagNumber(2)
-  $core.String get path => $_getSZ(1);
-  @$pb.TagNumber(2)
-  set path($core.String v) { $_setString(1, v); }
-  @$pb.TagNumber(2)
-  $core.bool hasPath() => $_has(1);
-  @$pb.TagNumber(2)
-  void clearPath() => clearField(2);
 }
 

+ 5 - 6
app_flowy/packages/flowy_sdk/lib/protobuf/flowy-document/doc_query.pbjson.dart

@@ -18,14 +18,13 @@ const QueryDocRequest$json = const {
 
 /// Descriptor for `QueryDocRequest`. Decode as a `google.protobuf.DescriptorProto`.
 final $typed_data.Uint8List queryDocRequestDescriptor = $convert.base64Decode('Cg9RdWVyeURvY1JlcXVlc3QSFQoGZG9jX2lkGAEgASgJUgVkb2NJZA==');
-@$core.Deprecated('Use queryDocDataRequestDescriptor instead')
-const QueryDocDataRequest$json = const {
-  '1': 'QueryDocDataRequest',
+@$core.Deprecated('Use queryDocParamsDescriptor instead')
+const QueryDocParams$json = const {
+  '1': 'QueryDocParams',
   '2': const [
     const {'1': 'doc_id', '3': 1, '4': 1, '5': 9, '10': 'docId'},
-    const {'1': 'path', '3': 2, '4': 1, '5': 9, '10': 'path'},
   ],
 };
 
-/// Descriptor for `QueryDocDataRequest`. Decode as a `google.protobuf.DescriptorProto`.
-final $typed_data.Uint8List queryDocDataRequestDescriptor = $convert.base64Decode('ChNRdWVyeURvY0RhdGFSZXF1ZXN0EhUKBmRvY19pZBgBIAEoCVIFZG9jSWQSEgoEcGF0aBgCIAEoCVIEcGF0aA==');
+/// Descriptor for `QueryDocParams`. Decode as a `google.protobuf.DescriptorProto`.
+final $typed_data.Uint8List queryDocParamsDescriptor = $convert.base64Decode('Cg5RdWVyeURvY1BhcmFtcxIVCgZkb2NfaWQYASABKAlSBWRvY0lk');

+ 4 - 4
app_flowy/packages/flowy_sdk/lib/protobuf/flowy-document/errors.pb.dart

@@ -15,14 +15,14 @@ export 'errors.pbenum.dart';
 
 class DocError extends $pb.GeneratedMessage {
   static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'DocError', createEmptyInstance: create)
-    ..e<DocErrorCode>(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'code', $pb.PbFieldType.OE, defaultOrMaker: DocErrorCode.Unknown, valueOf: DocErrorCode.valueOf, enumValues: DocErrorCode.values)
+    ..e<ErrorCode>(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'code', $pb.PbFieldType.OE, defaultOrMaker: ErrorCode.DocIdInvalid, valueOf: ErrorCode.valueOf, enumValues: ErrorCode.values)
     ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'msg')
     ..hasRequiredFields = false
   ;
 
   DocError._() : super();
   factory DocError({
-    DocErrorCode? code,
+    ErrorCode? code,
     $core.String? msg,
   }) {
     final _result = create();
@@ -56,9 +56,9 @@ class DocError extends $pb.GeneratedMessage {
   static DocError? _defaultInstance;
 
   @$pb.TagNumber(1)
-  DocErrorCode get code => $_getN(0);
+  ErrorCode get code => $_getN(0);
   @$pb.TagNumber(1)
-  set code(DocErrorCode v) { setField(1, v); }
+  set code(ErrorCode v) { setField(1, v); }
   @$pb.TagNumber(1)
   $core.bool hasCode() => $_has(0);
   @$pb.TagNumber(1)

+ 13 - 23
app_flowy/packages/flowy_sdk/lib/protobuf/flowy-document/errors.pbenum.dart

@@ -9,32 +9,22 @@
 import 'dart:core' as $core;
 import 'package:protobuf/protobuf.dart' as $pb;
 
-class DocErrorCode extends $pb.ProtobufEnum {
-  static const DocErrorCode Unknown = DocErrorCode._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Unknown');
-  static const DocErrorCode EditorDBInternalError = DocErrorCode._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'EditorDBInternalError');
-  static const DocErrorCode EditorDBConnFailed = DocErrorCode._(2, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'EditorDBConnFailed');
-  static const DocErrorCode DocNameInvalid = DocErrorCode._(10, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DocNameInvalid');
-  static const DocErrorCode DocViewIdInvalid = DocErrorCode._(11, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DocViewIdInvalid');
-  static const DocErrorCode DocDescTooLong = DocErrorCode._(12, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DocDescTooLong');
-  static const DocErrorCode DocOpenFileError = DocErrorCode._(13, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DocOpenFileError');
-  static const DocErrorCode DocFilePathInvalid = DocErrorCode._(14, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DocFilePathInvalid');
-  static const DocErrorCode EditorUserNotLoginYet = DocErrorCode._(100, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'EditorUserNotLoginYet');
+class ErrorCode extends $pb.ProtobufEnum {
+  static const ErrorCode DocIdInvalid = ErrorCode._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DocIdInvalid');
+  static const ErrorCode DocNotfound = ErrorCode._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DocNotfound');
+  static const ErrorCode UserUnauthorized = ErrorCode._(999, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserUnauthorized');
+  static const ErrorCode InternalError = ErrorCode._(1000, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'InternalError');
 
-  static const $core.List<DocErrorCode> values = <DocErrorCode> [
-    Unknown,
-    EditorDBInternalError,
-    EditorDBConnFailed,
-    DocNameInvalid,
-    DocViewIdInvalid,
-    DocDescTooLong,
-    DocOpenFileError,
-    DocFilePathInvalid,
-    EditorUserNotLoginYet,
+  static const $core.List<ErrorCode> values = <ErrorCode> [
+    DocIdInvalid,
+    DocNotfound,
+    UserUnauthorized,
+    InternalError,
   ];
 
-  static final $core.Map<$core.int, DocErrorCode> _byValue = $pb.ProtobufEnum.initByValue(values);
-  static DocErrorCode? valueOf($core.int value) => _byValue[value];
+  static final $core.Map<$core.int, ErrorCode> _byValue = $pb.ProtobufEnum.initByValue(values);
+  static ErrorCode? valueOf($core.int value) => _byValue[value];
 
-  const DocErrorCode._($core.int v, $core.String n) : super(v, n);
+  const ErrorCode._($core.int v, $core.String n) : super(v, n);
 }
 

+ 11 - 16
app_flowy/packages/flowy_sdk/lib/protobuf/flowy-document/errors.pbjson.dart

@@ -8,32 +8,27 @@
 import 'dart:core' as $core;
 import 'dart:convert' as $convert;
 import 'dart:typed_data' as $typed_data;
-@$core.Deprecated('Use docErrorCodeDescriptor instead')
-const DocErrorCode$json = const {
-  '1': 'DocErrorCode',
+@$core.Deprecated('Use errorCodeDescriptor instead')
+const ErrorCode$json = const {
+  '1': 'ErrorCode',
   '2': const [
-    const {'1': 'Unknown', '2': 0},
-    const {'1': 'EditorDBInternalError', '2': 1},
-    const {'1': 'EditorDBConnFailed', '2': 2},
-    const {'1': 'DocNameInvalid', '2': 10},
-    const {'1': 'DocViewIdInvalid', '2': 11},
-    const {'1': 'DocDescTooLong', '2': 12},
-    const {'1': 'DocOpenFileError', '2': 13},
-    const {'1': 'DocFilePathInvalid', '2': 14},
-    const {'1': 'EditorUserNotLoginYet', '2': 100},
+    const {'1': 'DocIdInvalid', '2': 0},
+    const {'1': 'DocNotfound', '2': 1},
+    const {'1': 'UserUnauthorized', '2': 999},
+    const {'1': 'InternalError', '2': 1000},
   ],
 };
 
-/// Descriptor for `DocErrorCode`. Decode as a `google.protobuf.EnumDescriptorProto`.
-final $typed_data.Uint8List docErrorCodeDescriptor = $convert.base64Decode('CgxEb2NFcnJvckNvZGUSCwoHVW5rbm93bhAAEhkKFUVkaXRvckRCSW50ZXJuYWxFcnJvchABEhYKEkVkaXRvckRCQ29ubkZhaWxlZBACEhIKDkRvY05hbWVJbnZhbGlkEAoSFAoQRG9jVmlld0lkSW52YWxpZBALEhIKDkRvY0Rlc2NUb29Mb25nEAwSFAoQRG9jT3BlbkZpbGVFcnJvchANEhYKEkRvY0ZpbGVQYXRoSW52YWxpZBAOEhkKFUVkaXRvclVzZXJOb3RMb2dpbllldBBk');
+/// Descriptor for `ErrorCode`. Decode as a `google.protobuf.EnumDescriptorProto`.
+final $typed_data.Uint8List errorCodeDescriptor = $convert.base64Decode('CglFcnJvckNvZGUSEAoMRG9jSWRJbnZhbGlkEAASDwoLRG9jTm90Zm91bmQQARIVChBVc2VyVW5hdXRob3JpemVkEOcHEhIKDUludGVybmFsRXJyb3IQ6Ac=');
 @$core.Deprecated('Use docErrorDescriptor instead')
 const DocError$json = const {
   '1': 'DocError',
   '2': const [
-    const {'1': 'code', '3': 1, '4': 1, '5': 14, '6': '.DocErrorCode', '10': 'code'},
+    const {'1': 'code', '3': 1, '4': 1, '5': 14, '6': '.ErrorCode', '10': 'code'},
     const {'1': 'msg', '3': 2, '4': 1, '5': 9, '10': 'msg'},
   ],
 };
 
 /// Descriptor for `DocError`. Decode as a `google.protobuf.DescriptorProto`.
-final $typed_data.Uint8List docErrorDescriptor = $convert.base64Decode('CghEb2NFcnJvchIhCgRjb2RlGAEgASgOMg0uRG9jRXJyb3JDb2RlUgRjb2RlEhAKA21zZxgCIAEoCVIDbXNn');
+final $typed_data.Uint8List docErrorDescriptor = $convert.base64Decode('CghEb2NFcnJvchIeCgRjb2RlGAEgASgOMgouRXJyb3JDb2RlUgRjb2RlEhAKA21zZxgCIAEoCVIDbXNn');

+ 4 - 4
app_flowy/packages/flowy_sdk/lib/protobuf/flowy-document/event.pbenum.dart

@@ -12,14 +12,14 @@ import 'package:protobuf/protobuf.dart' as $pb;
 class EditorEvent extends $pb.ProtobufEnum {
   static const EditorEvent CreateDoc = EditorEvent._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CreateDoc');
   static const EditorEvent UpdateDoc = EditorEvent._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UpdateDoc');
-  static const EditorEvent ReadDocInfo = EditorEvent._(2, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ReadDocInfo');
-  static const EditorEvent ReadDocData = EditorEvent._(3, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ReadDocData');
+  static const EditorEvent ReadDoc = EditorEvent._(2, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ReadDoc');
+  static const EditorEvent DeleteDoc = EditorEvent._(3, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DeleteDoc');
 
   static const $core.List<EditorEvent> values = <EditorEvent> [
     CreateDoc,
     UpdateDoc,
-    ReadDocInfo,
-    ReadDocData,
+    ReadDoc,
+    DeleteDoc,
   ];
 
   static final $core.Map<$core.int, EditorEvent> _byValue = $pb.ProtobufEnum.initByValue(values);

+ 3 - 3
app_flowy/packages/flowy_sdk/lib/protobuf/flowy-document/event.pbjson.dart

@@ -14,10 +14,10 @@ const EditorEvent$json = const {
   '2': const [
     const {'1': 'CreateDoc', '2': 0},
     const {'1': 'UpdateDoc', '2': 1},
-    const {'1': 'ReadDocInfo', '2': 2},
-    const {'1': 'ReadDocData', '2': 3},
+    const {'1': 'ReadDoc', '2': 2},
+    const {'1': 'DeleteDoc', '2': 3},
   ],
 };
 
 /// Descriptor for `EditorEvent`. Decode as a `google.protobuf.EnumDescriptorProto`.
-final $typed_data.Uint8List editorEventDescriptor = $convert.base64Decode('CgtFZGl0b3JFdmVudBINCglDcmVhdGVEb2MQABINCglVcGRhdGVEb2MQARIPCgtSZWFkRG9jSW5mbxACEg8KC1JlYWREb2NEYXRhEAM=');
+final $typed_data.Uint8List editorEventDescriptor = $convert.base64Decode('CgtFZGl0b3JFdmVudBINCglDcmVhdGVEb2MQABINCglVcGRhdGVEb2MQARILCgdSZWFkRG9jEAISDQoJRGVsZXRlRG9jEAM=');

+ 11 - 0
app_flowy/packages/flowy_sdk/lib/protobuf/flowy-document/observable.pb.dart

@@ -0,0 +1,11 @@
+///
+//  Generated code. Do not modify.
+//  source: observable.proto
+//
+// @dart = 2.12
+// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields
+
+import 'dart:core' as $core;
+
+export 'observable.pbenum.dart';
+

+ 24 - 0
app_flowy/packages/flowy_sdk/lib/protobuf/flowy-document/observable.pbenum.dart

@@ -0,0 +1,24 @@
+///
+//  Generated code. Do not modify.
+//  source: observable.proto
+//
+// @dart = 2.12
+// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields
+
+// ignore_for_file: UNDEFINED_SHOWN_NAME
+import 'dart:core' as $core;
+import 'package:protobuf/protobuf.dart' as $pb;
+
+class DocObservable extends $pb.ProtobufEnum {
+  static const DocObservable UserCreateDoc = DocObservable._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserCreateDoc');
+
+  static const $core.List<DocObservable> values = <DocObservable> [
+    UserCreateDoc,
+  ];
+
+  static final $core.Map<$core.int, DocObservable> _byValue = $pb.ProtobufEnum.initByValue(values);
+  static DocObservable? valueOf($core.int value) => _byValue[value];
+
+  const DocObservable._($core.int v, $core.String n) : super(v, n);
+}
+

+ 20 - 0
app_flowy/packages/flowy_sdk/lib/protobuf/flowy-document/observable.pbjson.dart

@@ -0,0 +1,20 @@
+///
+//  Generated code. Do not modify.
+//  source: observable.proto
+//
+// @dart = 2.12
+// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields,deprecated_member_use_from_same_package
+
+import 'dart:core' as $core;
+import 'dart:convert' as $convert;
+import 'dart:typed_data' as $typed_data;
+@$core.Deprecated('Use docObservableDescriptor instead')
+const DocObservable$json = const {
+  '1': 'DocObservable',
+  '2': const [
+    const {'1': 'UserCreateDoc', '2': 0},
+  ],
+};
+
+/// Descriptor for `DocObservable`. Decode as a `google.protobuf.EnumDescriptorProto`.
+final $typed_data.Uint8List docObservableDescriptor = $convert.base64Decode('Cg1Eb2NPYnNlcnZhYmxlEhEKDVVzZXJDcmVhdGVEb2MQAA==');

+ 9 - 0
app_flowy/packages/flowy_sdk/lib/protobuf/flowy-document/observable.pbserver.dart

@@ -0,0 +1,9 @@
+///
+//  Generated code. Do not modify.
+//  source: observable.proto
+//
+// @dart = 2.12
+// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields,deprecated_member_use_from_same_package
+
+export 'observable.pb.dart';
+

+ 1 - 0
app_flowy/packages/flowy_sdk/lib/protobuf/flowy-document/protobuf.dart

@@ -1,6 +1,7 @@
 // Auto-generated, do not edit 
 export './doc_modify.pb.dart';
 export './doc_create.pb.dart';
+export './observable.pb.dart';
 export './errors.pb.dart';
 export './event.pb.dart';
 export './doc_query.pb.dart';

+ 1 - 5
rust-lib/flowy-database/migrations/2021-07-22-234458_flowy-editor/up.sql

@@ -1,10 +1,6 @@
 -- Your SQL goes here
 CREATE TABLE doc_table (
     id TEXT NOT NULL PRIMARY KEY,
-    name TEXT NOT NULL DEFAULT '',
-    desc TEXT NOT NULL DEFAULT '',
-    path TEXT NOT NULL DEFAULT '',
-    modified_time BIGINT NOT NULL DEFAULT 0,
-    create_time BIGINT NOT NULL DEFAULT 0,
+    data TEXT NOT NULL DEFAULT '',
     version BIGINT NOT NULL DEFAULT 0
 );

+ 1 - 5
rust-lib/flowy-database/src/schema.rs

@@ -16,11 +16,7 @@ table! {
 table! {
     doc_table (id) {
         id -> Text,
-        name -> Text,
-        desc -> Text,
-        path -> Text,
-        modified_time -> BigInt,
-        create_time -> BigInt,
+        data -> Text,
         version -> BigInt,
     }
 }

+ 5 - 4
rust-lib/flowy-derive/src/derive_cache/derive_cache.rs

@@ -51,11 +51,12 @@ pub fn category_from_str(type_str: &str) -> TypeCategory {
         | "RepeatedView"
         | "WorkspaceError"
         | "CreateDocRequest"
-        | "DocInfo"
-        | "DocData"
+        | "CreateDocParams"
+        | "Doc"
         | "QueryDocRequest"
-        | "QueryDocDataRequest"
+        | "QueryDocParams"
         | "UpdateDocRequest"
+        | "UpdateDocParams"
         | "DocError"
         | "FFIRequest"
         | "FFIResponse"
@@ -76,7 +77,7 @@ pub fn category_from_str(type_str: &str) -> TypeCategory {
         | "ErrorCode"
         | "WorkspaceObservable"
         | "EditorEvent"
-        | "DocErrorCode"
+        | "DocObservable"
         | "FFIStatusCode"
         | "UserStatus"
         | "UserEvent"

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

@@ -1,3 +1,4 @@
+
 [package]
 name = "flowy-document"
 version = "0.1.0"
@@ -12,6 +13,9 @@ flowy-log = { path = "../flowy-log" }
 flowy-derive = { path = "../flowy-derive" }
 flowy-database = { path = "../flowy-database" }
 flowy-infra = { path = "../flowy-infra" }
+flowy-observable = { path = "../flowy-observable" }
+flowy-net = { path = "../flowy-net", features = ["flowy_request"] }
+
 diesel = {version = "1.4.7", features = ["sqlite"]}
 diesel_derives = {version = "1.4.1", features = ["sqlite"]}
 protobuf = {version = "2.18.0"}
@@ -25,4 +29,7 @@ strum = "0.21"
 strum_macros = "0.21"
 
 [dev-dependencies]
-flowy-test = { path = "../flowy-test" }
+flowy-test = { path = "../flowy-test" }
+
+[features]
+http_server = []

+ 1 - 1
rust-lib/flowy-document/Flowy.toml

@@ -1,3 +1,3 @@
 
-proto_crates = ["src/entities", "src/event.rs", "src/errors.rs"]
+proto_crates = ["src/entities", "src/event.rs", "src/errors.rs", "src/observable"]
 event_files = ["src/event.rs"]

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

@@ -11,68 +11,35 @@ pub struct CreateDocRequest {
     pub id: String,
 
     #[pb(index = 2)]
-    pub name: String,
-
-    #[pb(index = 3)]
-    pub desc: String,
-
-    #[pb(index = 4)]
-    pub text: String,
+    pub data: String,
 }
 
+#[derive(ProtoBuf, Default, Debug, Clone)]
 pub struct CreateDocParams {
+    #[pb(index = 1)]
     pub id: String,
-    pub name: String,
-    pub desc: String,
-    pub text: String,
+
+    #[pb(index = 2)]
+    pub data: String,
 }
 
 impl TryInto<CreateDocParams> for CreateDocRequest {
     type Error = DocError;
 
     fn try_into(self) -> Result<CreateDocParams, Self::Error> {
-        let name = DocName::parse(self.name)
-            .map_err(|e| {
-                ErrorBuilder::new(DocErrorCode::DocNameInvalid)
-                    .msg(e)
-                    .build()
-            })?
-            .0;
-
         let id = DocViewId::parse(self.id)
-            .map_err(|e| {
-                ErrorBuilder::new(DocErrorCode::DocViewIdInvalid)
-                    .msg(e)
-                    .build()
-            })?
+            .map_err(|e| ErrorBuilder::new(ErrorCode::DocIdInvalid).msg(e).build())?
             .0;
 
-        Ok(CreateDocParams {
-            id,
-            name,
-            desc: self.desc,
-            text: self.text,
-        })
+        Ok(CreateDocParams { id, data: self.data })
     }
 }
 
-#[derive(ProtoBuf, Default, Debug)]
-pub struct DocInfo {
+#[derive(ProtoBuf, Default, Debug, Clone)]
+pub struct Doc {
     #[pb(index = 1)]
     pub id: String,
 
     #[pb(index = 2)]
-    pub name: String,
-
-    #[pb(index = 3)]
-    pub desc: String,
-
-    #[pb(index = 4)]
-    pub path: String,
-}
-
-#[derive(ProtoBuf, Default, Debug)]
-pub struct DocData {
-    #[pb(index = 1)]
-    pub text: String,
+    pub data: String,
 }

+ 9 - 48
rust-lib/flowy-document/src/entities/doc/doc_modify.rs

@@ -8,20 +8,16 @@ pub struct UpdateDocRequest {
     pub id: String,
 
     #[pb(index = 2, one_of)]
-    pub name: Option<String>,
-
-    #[pb(index = 3, one_of)]
-    pub desc: Option<String>,
-
-    #[pb(index = 4, one_of)]
-    pub text: Option<String>,
+    pub data: Option<String>,
 }
 
-pub(crate) struct UpdateDocParams {
+#[derive(ProtoBuf, Default, Debug, Clone)]
+pub struct UpdateDocParams {
+    #[pb(index = 1)]
     pub(crate) id: String,
-    pub(crate) name: Option<String>,
-    pub(crate) desc: Option<String>,
-    pub(crate) text: Option<String>,
+
+    #[pb(index = 2, one_of)]
+    pub(crate) data: Option<String>,
 }
 
 impl TryInto<UpdateDocParams> for UpdateDocRequest {
@@ -29,44 +25,9 @@ impl TryInto<UpdateDocParams> for UpdateDocRequest {
 
     fn try_into(self) -> Result<UpdateDocParams, Self::Error> {
         let id = DocId::parse(self.id)
-            .map_err(|e| {
-                ErrorBuilder::new(DocErrorCode::DocViewIdInvalid)
-                    .msg(e)
-                    .build()
-            })?
+            .map_err(|e| ErrorBuilder::new(ErrorCode::DocIdInvalid).msg(e).build())?
             .0;
 
-        let name = match self.name {
-            None => None,
-            Some(name) => Some(
-                DocName::parse(name)
-                    .map_err(|e| {
-                        ErrorBuilder::new(DocErrorCode::DocNameInvalid)
-                            .msg(e)
-                            .build()
-                    })?
-                    .0,
-            ),
-        };
-
-        let desc = match self.desc {
-            None => None,
-            Some(desc) => Some(
-                DocDesc::parse(desc)
-                    .map_err(|e| {
-                        ErrorBuilder::new(DocErrorCode::DocDescTooLong)
-                            .msg(e)
-                            .build()
-                    })?
-                    .0,
-            ),
-        };
-
-        Ok(UpdateDocParams {
-            id,
-            name,
-            desc,
-            text: self.text,
-        })
+        Ok(UpdateDocParams { id, data: self.data })
     }
 }

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

@@ -11,7 +11,9 @@ pub struct QueryDocRequest {
     pub doc_id: String,
 }
 
-pub(crate) struct QueryDocParams {
+#[derive(ProtoBuf, Default, Debug, Clone)]
+pub struct QueryDocParams {
+    #[pb(index = 1)]
     pub doc_id: String,
 }
 
@@ -20,51 +22,9 @@ impl TryInto<QueryDocParams> for QueryDocRequest {
 
     fn try_into(self) -> Result<QueryDocParams, Self::Error> {
         let doc_id = DocId::parse(self.doc_id)
-            .map_err(|e| {
-                ErrorBuilder::new(DocErrorCode::DocViewIdInvalid)
-                    .msg(e)
-                    .build()
-            })?
+            .map_err(|e| ErrorBuilder::new(ErrorCode::DocIdInvalid).msg(e).build())?
             .0;
 
         Ok(QueryDocParams { doc_id })
     }
 }
-
-#[derive(Default, ProtoBuf)]
-pub struct QueryDocDataRequest {
-    #[pb(index = 1)]
-    pub doc_id: String,
-
-    #[pb(index = 2)]
-    pub path: String,
-}
-
-pub(crate) struct QueryDocDataParams {
-    pub doc_id: String,
-    pub path: String,
-}
-
-impl TryInto<QueryDocDataParams> for QueryDocDataRequest {
-    type Error = DocError;
-
-    fn try_into(self) -> Result<QueryDocDataParams, Self::Error> {
-        let doc_id = DocId::parse(self.doc_id)
-            .map_err(|e| {
-                ErrorBuilder::new(DocErrorCode::DocViewIdInvalid)
-                    .msg(e)
-                    .build()
-            })?
-            .0;
-
-        let path = DocPath::parse(self.path)
-            .map_err(|e| {
-                ErrorBuilder::new(DocErrorCode::DocFilePathInvalid)
-                    .msg(e)
-                    .build()
-            })?
-            .0;
-
-        Ok(QueryDocDataParams { doc_id, path })
-    }
-}

+ 39 - 34
rust-lib/flowy-document/src/errors.rs

@@ -3,61 +3,63 @@ use bytes::Bytes;
 use derive_more::Display;
 use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
 use flowy_dispatch::prelude::{EventResponse, ResponseBuilder};
-use std::convert::TryInto;
+use flowy_net::errors::ServerError;
+use std::{convert::TryInto, fmt};
 
 #[derive(Debug, Default, Clone, ProtoBuf)]
 pub struct DocError {
     #[pb(index = 1)]
-    pub code: DocErrorCode,
+    pub code: ErrorCode,
 
     #[pb(index = 2)]
     pub msg: String,
 }
 
 impl DocError {
-    fn new(code: DocErrorCode, msg: &str) -> Self { Self { code, msg: msg.to_owned() } }
+    fn new(code: ErrorCode, msg: &str) -> Self { Self { code, msg: msg.to_owned() } }
 }
 
 #[derive(Debug, Clone, ProtoBuf_Enum, Display, PartialEq, Eq)]
-pub enum DocErrorCode {
-    #[display(fmt = "Unknown")]
-    Unknown            = 0,
+pub enum ErrorCode {
+    #[display(fmt = "DocIdInvalid")]
+    DocIdInvalid     = 0,
 
-    #[display(fmt = "EditorDBInternalError")]
-    EditorDBInternalError = 1,
+    #[display(fmt = "DocNotfound")]
+    DocNotfound      = 1,
 
-    #[display(fmt = "EditorDBConnFailed")]
-    EditorDBConnFailed = 2,
+    #[display(fmt = "UserUnauthorized")]
+    UserUnauthorized = 999,
 
-    #[display(fmt = "DocNameInvalid")]
-    DocNameInvalid     = 10,
-
-    #[display(fmt = "DocViewIdInvalid")]
-    DocViewIdInvalid   = 11,
-
-    #[display(fmt = "DocDescTooLong")]
-    DocDescTooLong     = 12,
-
-    #[display(fmt = "DocOpenFileError")]
-    DocOpenFileError   = 13,
-
-    #[display(fmt = "DocFilePathInvalid")]
-    DocFilePathInvalid = 14,
-
-    #[display(fmt = "EditorUserNotLoginYet")]
-    EditorUserNotLoginYet = 100,
+    #[display(fmt = "InternalError")]
+    InternalError    = 1000,
 }
 
-impl std::default::Default for DocErrorCode {
-    fn default() -> Self { DocErrorCode::Unknown }
+impl std::default::Default for ErrorCode {
+    fn default() -> Self { ErrorCode::InternalError }
 }
 
 impl std::convert::From<flowy_database::Error> for DocError {
-    fn from(error: flowy_database::Error) -> Self { ErrorBuilder::new(DocErrorCode::EditorDBInternalError).error(error).build() }
+    fn from(error: flowy_database::Error) -> Self { ErrorBuilder::new(ErrorCode::InternalError).error(error).build() }
 }
 
 impl std::convert::From<FileError> for DocError {
-    fn from(error: FileError) -> Self { ErrorBuilder::new(DocErrorCode::DocOpenFileError).error(error).build() }
+    fn from(error: FileError) -> Self { ErrorBuilder::new(ErrorCode::InternalError).error(error).build() }
+}
+
+impl std::convert::From<flowy_net::errors::ServerError> for DocError {
+    fn from(error: ServerError) -> Self {
+        let code = server_error_to_doc_error(error.code);
+        ErrorBuilder::new(code).error(error.msg).build()
+    }
+}
+
+use flowy_net::errors::ErrorCode as ServerErrorCode;
+fn server_error_to_doc_error(code: ServerErrorCode) -> ErrorCode {
+    match code {
+        ServerErrorCode::UserUnauthorized => ErrorCode::UserUnauthorized,
+        ServerErrorCode::RecordNotFound => ErrorCode::DocNotfound,
+        _ => ErrorCode::InternalError,
+    }
 }
 
 impl flowy_dispatch::Error for DocError {
@@ -67,8 +69,11 @@ impl flowy_dispatch::Error for DocError {
     }
 }
 
-pub type ErrorBuilder = flowy_infra::errors::Builder<DocErrorCode, DocError>;
+impl fmt::Display for DocError {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{:?}: {}", &self.code, &self.msg) }
+}
 
-impl flowy_infra::errors::Build<DocErrorCode> for DocError {
-    fn build(code: DocErrorCode, msg: String) -> Self { DocError::new(code, &msg) }
+pub type ErrorBuilder = flowy_infra::errors::Builder<ErrorCode, DocError>;
+impl flowy_infra::errors::Build<ErrorCode> for DocError {
+    fn build(code: ErrorCode, msg: String) -> Self { DocError::new(code, &msg) }
 }

+ 7 - 7
rust-lib/flowy-document/src/event.rs

@@ -4,15 +4,15 @@ use strum_macros::Display;
 #[derive(Clone, Copy, PartialEq, Eq, Debug, Display, Hash, ProtoBuf_Enum, Flowy_Event)]
 #[event_err = "DocError"]
 pub enum EditorEvent {
-    #[event(input = "CreateDocRequest", output = "DocInfo")]
-    CreateDoc   = 0,
+    #[event(input = "CreateDocRequest", output = "Doc")]
+    CreateDoc = 0,
 
     #[event(input = "UpdateDocRequest")]
-    UpdateDoc   = 1,
+    UpdateDoc = 1,
 
-    #[event(input = "QueryDocRequest", output = "DocInfo")]
-    ReadDocInfo = 2,
+    #[event(input = "QueryDocRequest", output = "Doc")]
+    ReadDoc   = 2,
 
-    #[event(input = "QueryDocDataRequest", output = "DocData")]
-    ReadDocData = 3,
+    #[event(input = "QueryDocRequest")]
+    DeleteDoc = 3,
 }

+ 14 - 58
rust-lib/flowy-document/src/handlers/doc_handler.rs

@@ -7,73 +7,29 @@ use flowy_dispatch::prelude::*;
 use std::{convert::TryInto, path::Path};
 use tokio::sync::RwLock;
 
-#[tracing::instrument(name = "create_doc", skip(data, controller, manager))]
-pub async fn create_doc(
-    data: Data<CreateDocRequest>,
-    controller: Unit<DocController>,
-    manager: Unit<RwLock<FileManager>>,
-) -> DataResult<DocInfo, DocError> {
+#[tracing::instrument(skip(data, controller))]
+pub async fn create_doc_handler(data: Data<CreateDocRequest>, controller: Unit<DocController>) -> DataResult<Doc, DocError> {
     let params: CreateDocParams = data.into_inner().try_into()?;
-    let dir = manager.read().await.user.user_doc_dir()?;
-    let path = manager
-        .write()
-        .await
-        .create_file(&params.id, &dir, &params.text)?;
-    let doc_desc = controller
-        .create_doc(params, path.to_str().unwrap())
-        .await?;
+    let doc_desc = controller.create_doc(params).await?;
     data_result(doc_desc)
 }
 
-#[tracing::instrument(name = "read_doc", skip(data, controller, manager))]
-pub async fn read_doc(
-    data: Data<QueryDocRequest>,
-    controller: Unit<DocController>,
-    manager: Unit<RwLock<FileManager>>,
-) -> DataResult<DocInfo, DocError> {
+#[tracing::instrument(skip(data, controller))]
+pub async fn read_doc_handler(data: Data<QueryDocRequest>, controller: Unit<DocController>) -> DataResult<Doc, DocError> {
     let params: QueryDocParams = data.into_inner().try_into()?;
-    let doc_info = controller.read_doc(&params.doc_id).await?;
-    let _ = manager
-        .write()
-        .await
-        .open(Path::new(&doc_info.path), doc_info.id.clone())?;
-
+    let doc_info = controller.read_doc(params).await?;
     data_result(doc_info)
 }
 
-#[tracing::instrument(name = "read_doc_data", skip(data, manager))]
-pub async fn read_doc_data(
-    data: Data<QueryDocDataRequest>,
-    manager: Unit<RwLock<FileManager>>,
-) -> DataResult<DocData, DocError> {
-    let params: QueryDocDataParams = data.into_inner().try_into()?;
-    let text = manager
-        .write()
-        .await
-        .open(Path::new(&params.path), params.doc_id)?;
-
-    data_result(DocData { text })
-}
-
-pub async fn update_doc(
-    data: Data<UpdateDocRequest>,
-    controller: Unit<DocController>,
-    manager: Unit<RwLock<FileManager>>,
-) -> Result<(), DocError> {
+#[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 _ = controller.update_doc(params).await?;
+    Ok(())
+}
 
-    if let Some(s) = params.text.take() {
-        let doc_desc = controller.read_doc(&params.id).await?;
-        manager
-            .write()
-            .await
-            .save(Path::new(&doc_desc.path), &s, params.id.clone())
-            .unwrap();
-    }
-
-    if params.name.is_some() || params.desc.is_some() {
-        let _ = controller.update_doc(params).await?;
-    }
-
+pub async fn delete_doc_handler(data: Data<QueryDocRequest>, controller: Unit<DocController>) -> Result<(), DocError> {
+    let params: QueryDocParams = data.into_inner().try_into()?;
+    let _ = controller.delete_doc(params).await?;
     Ok(())
 }

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

@@ -3,6 +3,7 @@ pub mod errors;
 pub mod event;
 mod handlers;
 pub mod module;
+mod observable;
 mod protobuf;
 mod services;
 mod sql_tables;

+ 9 - 6
rust-lib/flowy-document/src/module.rs

@@ -2,7 +2,7 @@ use crate::{
     errors::DocError,
     event::EditorEvent,
     handlers::*,
-    services::{doc_controller::DocController, file_manager::FileManager},
+    services::{doc_controller::DocController, file_manager::FileManager, server::construct_doc_server},
 };
 use flowy_database::DBConnection;
 use flowy_dispatch::prelude::*;
@@ -15,18 +15,21 @@ pub trait DocumentDatabase: Send + Sync {
 
 pub trait DocumentUser: Send + Sync {
     fn user_doc_dir(&self) -> Result<String, DocError>;
+    fn user_id(&self) -> Result<String, DocError>;
+    fn token(&self) -> Result<String, DocError>;
 }
 
 pub fn create(database: Arc<dyn DocumentDatabase>, user: Arc<dyn DocumentUser>) -> Module {
+    let server = construct_doc_server();
     let file_manager = RwLock::new(FileManager::new(user.clone()));
-    let doc_controller = DocController::new(database);
+    let doc_controller = DocController::new(database, server.clone(), user.clone());
 
     Module::new()
         .name("flowy-document")
         .data(file_manager)
         .data(doc_controller)
-        .event(EditorEvent::CreateDoc, create_doc)
-        .event(EditorEvent::UpdateDoc, update_doc)
-        .event(EditorEvent::ReadDocInfo, read_doc)
-        .event(EditorEvent::ReadDocData, read_doc_data)
+        .event(EditorEvent::CreateDoc, create_doc_handler)
+        .event(EditorEvent::UpdateDoc, update_doc_handler)
+        .event(EditorEvent::ReadDoc, read_doc_handler)
+        .event(EditorEvent::DeleteDoc, delete_doc_handler)
 }

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

@@ -0,0 +1,3 @@
+mod observable;
+
+pub use observable::*;

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

@@ -0,0 +1,13 @@
+use flowy_derive::ProtoBuf_Enum;
+use flowy_observable::ObservableBuilder;
+const OBSERVABLE_CATEGORY: &'static str = "Doc";
+#[derive(ProtoBuf_Enum, Debug)]
+pub(crate) enum DocObservable {
+    UserCreateDoc = 0,
+}
+
+impl std::convert::Into<i32> for DocObservable {
+    fn into(self) -> i32 { self as i32 }
+}
+
+pub(crate) fn observable(id: &str, ty: DocObservable) -> ObservableBuilder { ObservableBuilder::new(id, ty, OBSERVABLE_CATEGORY) }

+ 167 - 303
rust-lib/flowy-document/src/protobuf/model/doc_create.rs

@@ -27,9 +27,7 @@
 pub struct CreateDocRequest {
     // message fields
     pub id: ::std::string::String,
-    pub name: ::std::string::String,
-    pub desc: ::std::string::String,
-    pub text: ::std::string::String,
+    pub data: ::std::string::String,
     // special fields
     pub unknown_fields: ::protobuf::UnknownFields,
     pub cached_size: ::protobuf::CachedSize,
@@ -72,82 +70,30 @@ impl CreateDocRequest {
         ::std::mem::replace(&mut self.id, ::std::string::String::new())
     }
 
-    // string name = 2;
+    // string data = 2;
 
 
-    pub fn get_name(&self) -> &str {
-        &self.name
+    pub fn get_data(&self) -> &str {
+        &self.data
     }
-    pub fn clear_name(&mut self) {
-        self.name.clear();
+    pub fn clear_data(&mut self) {
+        self.data.clear();
     }
 
     // Param is passed by value, moved
-    pub fn set_name(&mut self, v: ::std::string::String) {
-        self.name = v;
+    pub fn set_data(&mut self, v: ::std::string::String) {
+        self.data = v;
     }
 
     // Mutable pointer to the field.
     // If field is not initialized, it is initialized with default value first.
-    pub fn mut_name(&mut self) -> &mut ::std::string::String {
-        &mut self.name
+    pub fn mut_data(&mut self) -> &mut ::std::string::String {
+        &mut self.data
     }
 
     // Take field
-    pub fn take_name(&mut self) -> ::std::string::String {
-        ::std::mem::replace(&mut self.name, ::std::string::String::new())
-    }
-
-    // string desc = 3;
-
-
-    pub fn get_desc(&self) -> &str {
-        &self.desc
-    }
-    pub fn clear_desc(&mut self) {
-        self.desc.clear();
-    }
-
-    // Param is passed by value, moved
-    pub fn set_desc(&mut self, v: ::std::string::String) {
-        self.desc = v;
-    }
-
-    // Mutable pointer to the field.
-    // If field is not initialized, it is initialized with default value first.
-    pub fn mut_desc(&mut self) -> &mut ::std::string::String {
-        &mut self.desc
-    }
-
-    // Take field
-    pub fn take_desc(&mut self) -> ::std::string::String {
-        ::std::mem::replace(&mut self.desc, ::std::string::String::new())
-    }
-
-    // string text = 4;
-
-
-    pub fn get_text(&self) -> &str {
-        &self.text
-    }
-    pub fn clear_text(&mut self) {
-        self.text.clear();
-    }
-
-    // Param is passed by value, moved
-    pub fn set_text(&mut self, v: ::std::string::String) {
-        self.text = v;
-    }
-
-    // Mutable pointer to the field.
-    // If field is not initialized, it is initialized with default value first.
-    pub fn mut_text(&mut self) -> &mut ::std::string::String {
-        &mut self.text
-    }
-
-    // Take field
-    pub fn take_text(&mut self) -> ::std::string::String {
-        ::std::mem::replace(&mut self.text, ::std::string::String::new())
+    pub fn take_data(&mut self) -> ::std::string::String {
+        ::std::mem::replace(&mut self.data, ::std::string::String::new())
     }
 }
 
@@ -164,13 +110,7 @@ impl ::protobuf::Message for CreateDocRequest {
                     ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.id)?;
                 },
                 2 => {
-                    ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.name)?;
-                },
-                3 => {
-                    ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.desc)?;
-                },
-                4 => {
-                    ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.text)?;
+                    ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.data)?;
                 },
                 _ => {
                     ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?;
@@ -187,14 +127,8 @@ impl ::protobuf::Message for CreateDocRequest {
         if !self.id.is_empty() {
             my_size += ::protobuf::rt::string_size(1, &self.id);
         }
-        if !self.name.is_empty() {
-            my_size += ::protobuf::rt::string_size(2, &self.name);
-        }
-        if !self.desc.is_empty() {
-            my_size += ::protobuf::rt::string_size(3, &self.desc);
-        }
-        if !self.text.is_empty() {
-            my_size += ::protobuf::rt::string_size(4, &self.text);
+        if !self.data.is_empty() {
+            my_size += ::protobuf::rt::string_size(2, &self.data);
         }
         my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields());
         self.cached_size.set(my_size);
@@ -205,14 +139,8 @@ impl ::protobuf::Message for CreateDocRequest {
         if !self.id.is_empty() {
             os.write_string(1, &self.id)?;
         }
-        if !self.name.is_empty() {
-            os.write_string(2, &self.name)?;
-        }
-        if !self.desc.is_empty() {
-            os.write_string(3, &self.desc)?;
-        }
-        if !self.text.is_empty() {
-            os.write_string(4, &self.text)?;
+        if !self.data.is_empty() {
+            os.write_string(2, &self.data)?;
         }
         os.write_unknown_fields(self.get_unknown_fields())?;
         ::std::result::Result::Ok(())
@@ -258,19 +186,9 @@ impl ::protobuf::Message for CreateDocRequest {
                 |m: &mut CreateDocRequest| { &mut m.id },
             ));
             fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>(
-                "name",
-                |m: &CreateDocRequest| { &m.name },
-                |m: &mut CreateDocRequest| { &mut m.name },
-            ));
-            fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>(
-                "desc",
-                |m: &CreateDocRequest| { &m.desc },
-                |m: &mut CreateDocRequest| { &mut m.desc },
-            ));
-            fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>(
-                "text",
-                |m: &CreateDocRequest| { &m.text },
-                |m: &mut CreateDocRequest| { &mut m.text },
+                "data",
+                |m: &CreateDocRequest| { &m.data },
+                |m: &mut CreateDocRequest| { &mut m.data },
             ));
             ::protobuf::reflect::MessageDescriptor::new_pb_name::<CreateDocRequest>(
                 "CreateDocRequest",
@@ -289,9 +207,7 @@ impl ::protobuf::Message for CreateDocRequest {
 impl ::protobuf::Clear for CreateDocRequest {
     fn clear(&mut self) {
         self.id.clear();
-        self.name.clear();
-        self.desc.clear();
-        self.text.clear();
+        self.data.clear();
         self.unknown_fields.clear();
     }
 }
@@ -309,25 +225,23 @@ impl ::protobuf::reflect::ProtobufValue for CreateDocRequest {
 }
 
 #[derive(PartialEq,Clone,Default)]
-pub struct DocInfo {
+pub struct CreateDocParams {
     // message fields
     pub id: ::std::string::String,
-    pub name: ::std::string::String,
-    pub desc: ::std::string::String,
-    pub path: ::std::string::String,
+    pub data: ::std::string::String,
     // special fields
     pub unknown_fields: ::protobuf::UnknownFields,
     pub cached_size: ::protobuf::CachedSize,
 }
 
-impl<'a> ::std::default::Default for &'a DocInfo {
-    fn default() -> &'a DocInfo {
-        <DocInfo as ::protobuf::Message>::default_instance()
+impl<'a> ::std::default::Default for &'a CreateDocParams {
+    fn default() -> &'a CreateDocParams {
+        <CreateDocParams as ::protobuf::Message>::default_instance()
     }
 }
 
-impl DocInfo {
-    pub fn new() -> DocInfo {
+impl CreateDocParams {
+    pub fn new() -> CreateDocParams {
         ::std::default::Default::default()
     }
 
@@ -357,86 +271,34 @@ impl DocInfo {
         ::std::mem::replace(&mut self.id, ::std::string::String::new())
     }
 
-    // string name = 2;
-
-
-    pub fn get_name(&self) -> &str {
-        &self.name
-    }
-    pub fn clear_name(&mut self) {
-        self.name.clear();
-    }
-
-    // Param is passed by value, moved
-    pub fn set_name(&mut self, v: ::std::string::String) {
-        self.name = v;
-    }
-
-    // Mutable pointer to the field.
-    // If field is not initialized, it is initialized with default value first.
-    pub fn mut_name(&mut self) -> &mut ::std::string::String {
-        &mut self.name
-    }
-
-    // Take field
-    pub fn take_name(&mut self) -> ::std::string::String {
-        ::std::mem::replace(&mut self.name, ::std::string::String::new())
-    }
-
-    // string desc = 3;
-
-
-    pub fn get_desc(&self) -> &str {
-        &self.desc
-    }
-    pub fn clear_desc(&mut self) {
-        self.desc.clear();
-    }
-
-    // Param is passed by value, moved
-    pub fn set_desc(&mut self, v: ::std::string::String) {
-        self.desc = v;
-    }
+    // string data = 2;
 
-    // Mutable pointer to the field.
-    // If field is not initialized, it is initialized with default value first.
-    pub fn mut_desc(&mut self) -> &mut ::std::string::String {
-        &mut self.desc
-    }
 
-    // Take field
-    pub fn take_desc(&mut self) -> ::std::string::String {
-        ::std::mem::replace(&mut self.desc, ::std::string::String::new())
+    pub fn get_data(&self) -> &str {
+        &self.data
     }
-
-    // string path = 4;
-
-
-    pub fn get_path(&self) -> &str {
-        &self.path
-    }
-    pub fn clear_path(&mut self) {
-        self.path.clear();
+    pub fn clear_data(&mut self) {
+        self.data.clear();
     }
 
     // Param is passed by value, moved
-    pub fn set_path(&mut self, v: ::std::string::String) {
-        self.path = v;
+    pub fn set_data(&mut self, v: ::std::string::String) {
+        self.data = v;
     }
 
     // Mutable pointer to the field.
     // If field is not initialized, it is initialized with default value first.
-    pub fn mut_path(&mut self) -> &mut ::std::string::String {
-        &mut self.path
+    pub fn mut_data(&mut self) -> &mut ::std::string::String {
+        &mut self.data
     }
 
     // Take field
-    pub fn take_path(&mut self) -> ::std::string::String {
-        ::std::mem::replace(&mut self.path, ::std::string::String::new())
+    pub fn take_data(&mut self) -> ::std::string::String {
+        ::std::mem::replace(&mut self.data, ::std::string::String::new())
     }
 }
 
-impl ::protobuf::Message for DocInfo {
+impl ::protobuf::Message for CreateDocParams {
     fn is_initialized(&self) -> bool {
         true
     }
@@ -449,13 +311,7 @@ impl ::protobuf::Message for DocInfo {
                     ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.id)?;
                 },
                 2 => {
-                    ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.name)?;
-                },
-                3 => {
-                    ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.desc)?;
-                },
-                4 => {
-                    ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.path)?;
+                    ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.data)?;
                 },
                 _ => {
                     ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?;
@@ -472,14 +328,8 @@ impl ::protobuf::Message for DocInfo {
         if !self.id.is_empty() {
             my_size += ::protobuf::rt::string_size(1, &self.id);
         }
-        if !self.name.is_empty() {
-            my_size += ::protobuf::rt::string_size(2, &self.name);
-        }
-        if !self.desc.is_empty() {
-            my_size += ::protobuf::rt::string_size(3, &self.desc);
-        }
-        if !self.path.is_empty() {
-            my_size += ::protobuf::rt::string_size(4, &self.path);
+        if !self.data.is_empty() {
+            my_size += ::protobuf::rt::string_size(2, &self.data);
         }
         my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields());
         self.cached_size.set(my_size);
@@ -490,14 +340,8 @@ impl ::protobuf::Message for DocInfo {
         if !self.id.is_empty() {
             os.write_string(1, &self.id)?;
         }
-        if !self.name.is_empty() {
-            os.write_string(2, &self.name)?;
-        }
-        if !self.desc.is_empty() {
-            os.write_string(3, &self.desc)?;
-        }
-        if !self.path.is_empty() {
-            os.write_string(4, &self.path)?;
+        if !self.data.is_empty() {
+            os.write_string(2, &self.data)?;
         }
         os.write_unknown_fields(self.get_unknown_fields())?;
         ::std::result::Result::Ok(())
@@ -529,8 +373,8 @@ impl ::protobuf::Message for DocInfo {
         Self::descriptor_static()
     }
 
-    fn new() -> DocInfo {
-        DocInfo::new()
+    fn new() -> CreateDocParams {
+        CreateDocParams::new()
     }
 
     fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor {
@@ -539,108 +383,123 @@ impl ::protobuf::Message for DocInfo {
             let mut fields = ::std::vec::Vec::new();
             fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>(
                 "id",
-                |m: &DocInfo| { &m.id },
-                |m: &mut DocInfo| { &mut m.id },
-            ));
-            fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>(
-                "name",
-                |m: &DocInfo| { &m.name },
-                |m: &mut DocInfo| { &mut m.name },
-            ));
-            fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>(
-                "desc",
-                |m: &DocInfo| { &m.desc },
-                |m: &mut DocInfo| { &mut m.desc },
+                |m: &CreateDocParams| { &m.id },
+                |m: &mut CreateDocParams| { &mut m.id },
             ));
             fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>(
-                "path",
-                |m: &DocInfo| { &m.path },
-                |m: &mut DocInfo| { &mut m.path },
+                "data",
+                |m: &CreateDocParams| { &m.data },
+                |m: &mut CreateDocParams| { &mut m.data },
             ));
-            ::protobuf::reflect::MessageDescriptor::new_pb_name::<DocInfo>(
-                "DocInfo",
+            ::protobuf::reflect::MessageDescriptor::new_pb_name::<CreateDocParams>(
+                "CreateDocParams",
                 fields,
                 file_descriptor_proto()
             )
         })
     }
 
-    fn default_instance() -> &'static DocInfo {
-        static instance: ::protobuf::rt::LazyV2<DocInfo> = ::protobuf::rt::LazyV2::INIT;
-        instance.get(DocInfo::new)
+    fn default_instance() -> &'static CreateDocParams {
+        static instance: ::protobuf::rt::LazyV2<CreateDocParams> = ::protobuf::rt::LazyV2::INIT;
+        instance.get(CreateDocParams::new)
     }
 }
 
-impl ::protobuf::Clear for DocInfo {
+impl ::protobuf::Clear for CreateDocParams {
     fn clear(&mut self) {
         self.id.clear();
-        self.name.clear();
-        self.desc.clear();
-        self.path.clear();
+        self.data.clear();
         self.unknown_fields.clear();
     }
 }
 
-impl ::std::fmt::Debug for DocInfo {
+impl ::std::fmt::Debug for CreateDocParams {
     fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
         ::protobuf::text_format::fmt(self, f)
     }
 }
 
-impl ::protobuf::reflect::ProtobufValue for DocInfo {
+impl ::protobuf::reflect::ProtobufValue for CreateDocParams {
     fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef {
         ::protobuf::reflect::ReflectValueRef::Message(self)
     }
 }
 
 #[derive(PartialEq,Clone,Default)]
-pub struct DocData {
+pub struct Doc {
     // message fields
-    pub text: ::std::string::String,
+    pub id: ::std::string::String,
+    pub data: ::std::string::String,
     // special fields
     pub unknown_fields: ::protobuf::UnknownFields,
     pub cached_size: ::protobuf::CachedSize,
 }
 
-impl<'a> ::std::default::Default for &'a DocData {
-    fn default() -> &'a DocData {
-        <DocData as ::protobuf::Message>::default_instance()
+impl<'a> ::std::default::Default for &'a Doc {
+    fn default() -> &'a Doc {
+        <Doc as ::protobuf::Message>::default_instance()
     }
 }
 
-impl DocData {
-    pub fn new() -> DocData {
+impl Doc {
+    pub fn new() -> Doc {
         ::std::default::Default::default()
     }
 
-    // string text = 1;
+    // string id = 1;
+
+
+    pub fn get_id(&self) -> &str {
+        &self.id
+    }
+    pub fn clear_id(&mut self) {
+        self.id.clear();
+    }
+
+    // Param is passed by value, moved
+    pub fn set_id(&mut self, v: ::std::string::String) {
+        self.id = v;
+    }
+
+    // Mutable pointer to the field.
+    // If field is not initialized, it is initialized with default value first.
+    pub fn mut_id(&mut self) -> &mut ::std::string::String {
+        &mut self.id
+    }
+
+    // Take field
+    pub fn take_id(&mut self) -> ::std::string::String {
+        ::std::mem::replace(&mut self.id, ::std::string::String::new())
+    }
+
+    // string data = 2;
 
 
-    pub fn get_text(&self) -> &str {
-        &self.text
+    pub fn get_data(&self) -> &str {
+        &self.data
     }
-    pub fn clear_text(&mut self) {
-        self.text.clear();
+    pub fn clear_data(&mut self) {
+        self.data.clear();
     }
 
     // Param is passed by value, moved
-    pub fn set_text(&mut self, v: ::std::string::String) {
-        self.text = v;
+    pub fn set_data(&mut self, v: ::std::string::String) {
+        self.data = v;
     }
 
     // Mutable pointer to the field.
     // If field is not initialized, it is initialized with default value first.
-    pub fn mut_text(&mut self) -> &mut ::std::string::String {
-        &mut self.text
+    pub fn mut_data(&mut self) -> &mut ::std::string::String {
+        &mut self.data
     }
 
     // Take field
-    pub fn take_text(&mut self) -> ::std::string::String {
-        ::std::mem::replace(&mut self.text, ::std::string::String::new())
+    pub fn take_data(&mut self) -> ::std::string::String {
+        ::std::mem::replace(&mut self.data, ::std::string::String::new())
     }
 }
 
-impl ::protobuf::Message for DocData {
+impl ::protobuf::Message for Doc {
     fn is_initialized(&self) -> bool {
         true
     }
@@ -650,7 +509,10 @@ impl ::protobuf::Message for DocData {
             let (field_number, wire_type) = is.read_tag_unpack()?;
             match field_number {
                 1 => {
-                    ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.text)?;
+                    ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.id)?;
+                },
+                2 => {
+                    ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.data)?;
                 },
                 _ => {
                     ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?;
@@ -664,8 +526,11 @@ impl ::protobuf::Message for DocData {
     #[allow(unused_variables)]
     fn compute_size(&self) -> u32 {
         let mut my_size = 0;
-        if !self.text.is_empty() {
-            my_size += ::protobuf::rt::string_size(1, &self.text);
+        if !self.id.is_empty() {
+            my_size += ::protobuf::rt::string_size(1, &self.id);
+        }
+        if !self.data.is_empty() {
+            my_size += ::protobuf::rt::string_size(2, &self.data);
         }
         my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields());
         self.cached_size.set(my_size);
@@ -673,8 +538,11 @@ impl ::protobuf::Message for DocData {
     }
 
     fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::ProtobufResult<()> {
-        if !self.text.is_empty() {
-            os.write_string(1, &self.text)?;
+        if !self.id.is_empty() {
+            os.write_string(1, &self.id)?;
+        }
+        if !self.data.is_empty() {
+            os.write_string(2, &self.data)?;
         }
         os.write_unknown_fields(self.get_unknown_fields())?;
         ::std::result::Result::Ok(())
@@ -706,8 +574,8 @@ impl ::protobuf::Message for DocData {
         Self::descriptor_static()
     }
 
-    fn new() -> DocData {
-        DocData::new()
+    fn new() -> Doc {
+        Doc::new()
     }
 
     fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor {
@@ -715,80 +583,76 @@ impl ::protobuf::Message for DocData {
         descriptor.get(|| {
             let mut fields = ::std::vec::Vec::new();
             fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>(
-                "text",
-                |m: &DocData| { &m.text },
-                |m: &mut DocData| { &mut m.text },
+                "id",
+                |m: &Doc| { &m.id },
+                |m: &mut Doc| { &mut m.id },
             ));
-            ::protobuf::reflect::MessageDescriptor::new_pb_name::<DocData>(
-                "DocData",
+            fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>(
+                "data",
+                |m: &Doc| { &m.data },
+                |m: &mut Doc| { &mut m.data },
+            ));
+            ::protobuf::reflect::MessageDescriptor::new_pb_name::<Doc>(
+                "Doc",
                 fields,
                 file_descriptor_proto()
             )
         })
     }
 
-    fn default_instance() -> &'static DocData {
-        static instance: ::protobuf::rt::LazyV2<DocData> = ::protobuf::rt::LazyV2::INIT;
-        instance.get(DocData::new)
+    fn default_instance() -> &'static Doc {
+        static instance: ::protobuf::rt::LazyV2<Doc> = ::protobuf::rt::LazyV2::INIT;
+        instance.get(Doc::new)
     }
 }
 
-impl ::protobuf::Clear for DocData {
+impl ::protobuf::Clear for Doc {
     fn clear(&mut self) {
-        self.text.clear();
+        self.id.clear();
+        self.data.clear();
         self.unknown_fields.clear();
     }
 }
 
-impl ::std::fmt::Debug for DocData {
+impl ::std::fmt::Debug for Doc {
     fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
         ::protobuf::text_format::fmt(self, f)
     }
 }
 
-impl ::protobuf::reflect::ProtobufValue for DocData {
+impl ::protobuf::reflect::ProtobufValue for Doc {
     fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef {
         ::protobuf::reflect::ReflectValueRef::Message(self)
     }
 }
 
 static file_descriptor_proto_data: &'static [u8] = b"\
-    \n\x10doc_create.proto\"^\n\x10CreateDocRequest\x12\x0e\n\x02id\x18\x01\
-    \x20\x01(\tR\x02id\x12\x12\n\x04name\x18\x02\x20\x01(\tR\x04name\x12\x12\
-    \n\x04desc\x18\x03\x20\x01(\tR\x04desc\x12\x12\n\x04text\x18\x04\x20\x01\
-    (\tR\x04text\"U\n\x07DocInfo\x12\x0e\n\x02id\x18\x01\x20\x01(\tR\x02id\
-    \x12\x12\n\x04name\x18\x02\x20\x01(\tR\x04name\x12\x12\n\x04desc\x18\x03\
-    \x20\x01(\tR\x04desc\x12\x12\n\x04path\x18\x04\x20\x01(\tR\x04path\"\x1d\
-    \n\x07DocData\x12\x12\n\x04text\x18\x01\x20\x01(\tR\x04textJ\xc9\x04\n\
-    \x06\x12\x04\0\0\x10\x01\n\x08\n\x01\x0c\x12\x03\0\0\x12\n\n\n\x02\x04\0\
-    \x12\x04\x02\0\x07\x01\n\n\n\x03\x04\0\x01\x12\x03\x02\x08\x18\n\x0b\n\
-    \x04\x04\0\x02\0\x12\x03\x03\x04\x12\n\x0c\n\x05\x04\0\x02\0\x05\x12\x03\
-    \x03\x04\n\n\x0c\n\x05\x04\0\x02\0\x01\x12\x03\x03\x0b\r\n\x0c\n\x05\x04\
-    \0\x02\0\x03\x12\x03\x03\x10\x11\n\x0b\n\x04\x04\0\x02\x01\x12\x03\x04\
-    \x04\x14\n\x0c\n\x05\x04\0\x02\x01\x05\x12\x03\x04\x04\n\n\x0c\n\x05\x04\
-    \0\x02\x01\x01\x12\x03\x04\x0b\x0f\n\x0c\n\x05\x04\0\x02\x01\x03\x12\x03\
-    \x04\x12\x13\n\x0b\n\x04\x04\0\x02\x02\x12\x03\x05\x04\x14\n\x0c\n\x05\
-    \x04\0\x02\x02\x05\x12\x03\x05\x04\n\n\x0c\n\x05\x04\0\x02\x02\x01\x12\
-    \x03\x05\x0b\x0f\n\x0c\n\x05\x04\0\x02\x02\x03\x12\x03\x05\x12\x13\n\x0b\
-    \n\x04\x04\0\x02\x03\x12\x03\x06\x04\x14\n\x0c\n\x05\x04\0\x02\x03\x05\
-    \x12\x03\x06\x04\n\n\x0c\n\x05\x04\0\x02\x03\x01\x12\x03\x06\x0b\x0f\n\
-    \x0c\n\x05\x04\0\x02\x03\x03\x12\x03\x06\x12\x13\n\n\n\x02\x04\x01\x12\
-    \x04\x08\0\r\x01\n\n\n\x03\x04\x01\x01\x12\x03\x08\x08\x0f\n\x0b\n\x04\
-    \x04\x01\x02\0\x12\x03\t\x04\x12\n\x0c\n\x05\x04\x01\x02\0\x05\x12\x03\t\
-    \x04\n\n\x0c\n\x05\x04\x01\x02\0\x01\x12\x03\t\x0b\r\n\x0c\n\x05\x04\x01\
-    \x02\0\x03\x12\x03\t\x10\x11\n\x0b\n\x04\x04\x01\x02\x01\x12\x03\n\x04\
-    \x14\n\x0c\n\x05\x04\x01\x02\x01\x05\x12\x03\n\x04\n\n\x0c\n\x05\x04\x01\
-    \x02\x01\x01\x12\x03\n\x0b\x0f\n\x0c\n\x05\x04\x01\x02\x01\x03\x12\x03\n\
-    \x12\x13\n\x0b\n\x04\x04\x01\x02\x02\x12\x03\x0b\x04\x14\n\x0c\n\x05\x04\
-    \x01\x02\x02\x05\x12\x03\x0b\x04\n\n\x0c\n\x05\x04\x01\x02\x02\x01\x12\
-    \x03\x0b\x0b\x0f\n\x0c\n\x05\x04\x01\x02\x02\x03\x12\x03\x0b\x12\x13\n\
-    \x0b\n\x04\x04\x01\x02\x03\x12\x03\x0c\x04\x14\n\x0c\n\x05\x04\x01\x02\
-    \x03\x05\x12\x03\x0c\x04\n\n\x0c\n\x05\x04\x01\x02\x03\x01\x12\x03\x0c\
-    \x0b\x0f\n\x0c\n\x05\x04\x01\x02\x03\x03\x12\x03\x0c\x12\x13\n\n\n\x02\
-    \x04\x02\x12\x04\x0e\0\x10\x01\n\n\n\x03\x04\x02\x01\x12\x03\x0e\x08\x0f\
-    \n\x0b\n\x04\x04\x02\x02\0\x12\x03\x0f\x04\x14\n\x0c\n\x05\x04\x02\x02\0\
-    \x05\x12\x03\x0f\x04\n\n\x0c\n\x05\x04\x02\x02\0\x01\x12\x03\x0f\x0b\x0f\
-    \n\x0c\n\x05\x04\x02\x02\0\x03\x12\x03\x0f\x12\x13b\x06proto3\
+    \n\x10doc_create.proto\"6\n\x10CreateDocRequest\x12\x0e\n\x02id\x18\x01\
+    \x20\x01(\tR\x02id\x12\x12\n\x04data\x18\x02\x20\x01(\tR\x04data\"5\n\
+    \x0fCreateDocParams\x12\x0e\n\x02id\x18\x01\x20\x01(\tR\x02id\x12\x12\n\
+    \x04data\x18\x02\x20\x01(\tR\x04data\")\n\x03Doc\x12\x0e\n\x02id\x18\x01\
+    \x20\x01(\tR\x02id\x12\x12\n\x04data\x18\x02\x20\x01(\tR\x04dataJ\xa4\
+    \x03\n\x06\x12\x04\0\0\r\x01\n\x08\n\x01\x0c\x12\x03\0\0\x12\n\n\n\x02\
+    \x04\0\x12\x04\x02\0\x05\x01\n\n\n\x03\x04\0\x01\x12\x03\x02\x08\x18\n\
+    \x0b\n\x04\x04\0\x02\0\x12\x03\x03\x04\x12\n\x0c\n\x05\x04\0\x02\0\x05\
+    \x12\x03\x03\x04\n\n\x0c\n\x05\x04\0\x02\0\x01\x12\x03\x03\x0b\r\n\x0c\n\
+    \x05\x04\0\x02\0\x03\x12\x03\x03\x10\x11\n\x0b\n\x04\x04\0\x02\x01\x12\
+    \x03\x04\x04\x14\n\x0c\n\x05\x04\0\x02\x01\x05\x12\x03\x04\x04\n\n\x0c\n\
+    \x05\x04\0\x02\x01\x01\x12\x03\x04\x0b\x0f\n\x0c\n\x05\x04\0\x02\x01\x03\
+    \x12\x03\x04\x12\x13\n\n\n\x02\x04\x01\x12\x04\x06\0\t\x01\n\n\n\x03\x04\
+    \x01\x01\x12\x03\x06\x08\x17\n\x0b\n\x04\x04\x01\x02\0\x12\x03\x07\x04\
+    \x12\n\x0c\n\x05\x04\x01\x02\0\x05\x12\x03\x07\x04\n\n\x0c\n\x05\x04\x01\
+    \x02\0\x01\x12\x03\x07\x0b\r\n\x0c\n\x05\x04\x01\x02\0\x03\x12\x03\x07\
+    \x10\x11\n\x0b\n\x04\x04\x01\x02\x01\x12\x03\x08\x04\x14\n\x0c\n\x05\x04\
+    \x01\x02\x01\x05\x12\x03\x08\x04\n\n\x0c\n\x05\x04\x01\x02\x01\x01\x12\
+    \x03\x08\x0b\x0f\n\x0c\n\x05\x04\x01\x02\x01\x03\x12\x03\x08\x12\x13\n\n\
+    \n\x02\x04\x02\x12\x04\n\0\r\x01\n\n\n\x03\x04\x02\x01\x12\x03\n\x08\x0b\
+    \n\x0b\n\x04\x04\x02\x02\0\x12\x03\x0b\x04\x12\n\x0c\n\x05\x04\x02\x02\0\
+    \x05\x12\x03\x0b\x04\n\n\x0c\n\x05\x04\x02\x02\0\x01\x12\x03\x0b\x0b\r\n\
+    \x0c\n\x05\x04\x02\x02\0\x03\x12\x03\x0b\x10\x11\n\x0b\n\x04\x04\x02\x02\
+    \x01\x12\x03\x0c\x04\x14\n\x0c\n\x05\x04\x02\x02\x01\x05\x12\x03\x0c\x04\
+    \n\n\x0c\n\x05\x04\x02\x02\x01\x01\x12\x03\x0c\x0b\x0f\n\x0c\n\x05\x04\
+    \x02\x02\x01\x03\x12\x03\x0c\x12\x13b\x06proto3\
 ";
 
 static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;

+ 261 - 182
rust-lib/flowy-document/src/protobuf/model/doc_modify.rs

@@ -28,9 +28,7 @@ pub struct UpdateDocRequest {
     // message fields
     pub id: ::std::string::String,
     // message oneof groups
-    pub one_of_name: ::std::option::Option<UpdateDocRequest_oneof_one_of_name>,
-    pub one_of_desc: ::std::option::Option<UpdateDocRequest_oneof_one_of_desc>,
-    pub one_of_text: ::std::option::Option<UpdateDocRequest_oneof_one_of_text>,
+    pub one_of_data: ::std::option::Option<UpdateDocRequest_oneof_one_of_data>,
     // special fields
     pub unknown_fields: ::protobuf::UnknownFields,
     pub cached_size: ::protobuf::CachedSize,
@@ -43,18 +41,8 @@ impl<'a> ::std::default::Default for &'a UpdateDocRequest {
 }
 
 #[derive(Clone,PartialEq,Debug)]
-pub enum UpdateDocRequest_oneof_one_of_name {
-    name(::std::string::String),
-}
-
-#[derive(Clone,PartialEq,Debug)]
-pub enum UpdateDocRequest_oneof_one_of_desc {
-    desc(::std::string::String),
-}
-
-#[derive(Clone,PartialEq,Debug)]
-pub enum UpdateDocRequest_oneof_one_of_text {
-    text(::std::string::String),
+pub enum UpdateDocRequest_oneof_one_of_data {
+    data(::std::string::String),
 }
 
 impl UpdateDocRequest {
@@ -88,146 +76,289 @@ impl UpdateDocRequest {
         ::std::mem::replace(&mut self.id, ::std::string::String::new())
     }
 
-    // string name = 2;
+    // string data = 2;
 
 
-    pub fn get_name(&self) -> &str {
-        match self.one_of_name {
-            ::std::option::Option::Some(UpdateDocRequest_oneof_one_of_name::name(ref v)) => v,
+    pub fn get_data(&self) -> &str {
+        match self.one_of_data {
+            ::std::option::Option::Some(UpdateDocRequest_oneof_one_of_data::data(ref v)) => v,
             _ => "",
         }
     }
-    pub fn clear_name(&mut self) {
-        self.one_of_name = ::std::option::Option::None;
+    pub fn clear_data(&mut self) {
+        self.one_of_data = ::std::option::Option::None;
     }
 
-    pub fn has_name(&self) -> bool {
-        match self.one_of_name {
-            ::std::option::Option::Some(UpdateDocRequest_oneof_one_of_name::name(..)) => true,
+    pub fn has_data(&self) -> bool {
+        match self.one_of_data {
+            ::std::option::Option::Some(UpdateDocRequest_oneof_one_of_data::data(..)) => true,
             _ => false,
         }
     }
 
     // Param is passed by value, moved
-    pub fn set_name(&mut self, v: ::std::string::String) {
-        self.one_of_name = ::std::option::Option::Some(UpdateDocRequest_oneof_one_of_name::name(v))
+    pub fn set_data(&mut self, v: ::std::string::String) {
+        self.one_of_data = ::std::option::Option::Some(UpdateDocRequest_oneof_one_of_data::data(v))
     }
 
     // Mutable pointer to the field.
-    pub fn mut_name(&mut self) -> &mut ::std::string::String {
-        if let ::std::option::Option::Some(UpdateDocRequest_oneof_one_of_name::name(_)) = self.one_of_name {
+    pub fn mut_data(&mut self) -> &mut ::std::string::String {
+        if let ::std::option::Option::Some(UpdateDocRequest_oneof_one_of_data::data(_)) = self.one_of_data {
         } else {
-            self.one_of_name = ::std::option::Option::Some(UpdateDocRequest_oneof_one_of_name::name(::std::string::String::new()));
+            self.one_of_data = ::std::option::Option::Some(UpdateDocRequest_oneof_one_of_data::data(::std::string::String::new()));
         }
-        match self.one_of_name {
-            ::std::option::Option::Some(UpdateDocRequest_oneof_one_of_name::name(ref mut v)) => v,
+        match self.one_of_data {
+            ::std::option::Option::Some(UpdateDocRequest_oneof_one_of_data::data(ref mut v)) => v,
             _ => panic!(),
         }
     }
 
     // Take field
-    pub fn take_name(&mut self) -> ::std::string::String {
-        if self.has_name() {
-            match self.one_of_name.take() {
-                ::std::option::Option::Some(UpdateDocRequest_oneof_one_of_name::name(v)) => v,
+    pub fn take_data(&mut self) -> ::std::string::String {
+        if self.has_data() {
+            match self.one_of_data.take() {
+                ::std::option::Option::Some(UpdateDocRequest_oneof_one_of_data::data(v)) => v,
                 _ => panic!(),
             }
         } else {
             ::std::string::String::new()
         }
     }
+}
 
-    // string desc = 3;
-
+impl ::protobuf::Message for UpdateDocRequest {
+    fn is_initialized(&self) -> bool {
+        true
+    }
 
-    pub fn get_desc(&self) -> &str {
-        match self.one_of_desc {
-            ::std::option::Option::Some(UpdateDocRequest_oneof_one_of_desc::desc(ref v)) => v,
-            _ => "",
+    fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::ProtobufResult<()> {
+        while !is.eof()? {
+            let (field_number, wire_type) = is.read_tag_unpack()?;
+            match field_number {
+                1 => {
+                    ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.id)?;
+                },
+                2 => {
+                    if wire_type != ::protobuf::wire_format::WireTypeLengthDelimited {
+                        return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type));
+                    }
+                    self.one_of_data = ::std::option::Option::Some(UpdateDocRequest_oneof_one_of_data::data(is.read_string()?));
+                },
+                _ => {
+                    ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?;
+                },
+            };
         }
+        ::std::result::Result::Ok(())
     }
-    pub fn clear_desc(&mut self) {
-        self.one_of_desc = ::std::option::Option::None;
+
+    // Compute sizes of nested messages
+    #[allow(unused_variables)]
+    fn compute_size(&self) -> u32 {
+        let mut my_size = 0;
+        if !self.id.is_empty() {
+            my_size += ::protobuf::rt::string_size(1, &self.id);
+        }
+        if let ::std::option::Option::Some(ref v) = self.one_of_data {
+            match v {
+                &UpdateDocRequest_oneof_one_of_data::data(ref v) => {
+                    my_size += ::protobuf::rt::string_size(2, &v);
+                },
+            };
+        }
+        my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields());
+        self.cached_size.set(my_size);
+        my_size
     }
 
-    pub fn has_desc(&self) -> bool {
-        match self.one_of_desc {
-            ::std::option::Option::Some(UpdateDocRequest_oneof_one_of_desc::desc(..)) => true,
-            _ => false,
+    fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::ProtobufResult<()> {
+        if !self.id.is_empty() {
+            os.write_string(1, &self.id)?;
+        }
+        if let ::std::option::Option::Some(ref v) = self.one_of_data {
+            match v {
+                &UpdateDocRequest_oneof_one_of_data::data(ref v) => {
+                    os.write_string(2, v)?;
+                },
+            };
         }
+        os.write_unknown_fields(self.get_unknown_fields())?;
+        ::std::result::Result::Ok(())
+    }
+
+    fn get_cached_size(&self) -> u32 {
+        self.cached_size.get()
+    }
+
+    fn get_unknown_fields(&self) -> &::protobuf::UnknownFields {
+        &self.unknown_fields
+    }
+
+    fn mut_unknown_fields(&mut self) -> &mut ::protobuf::UnknownFields {
+        &mut self.unknown_fields
+    }
+
+    fn as_any(&self) -> &dyn (::std::any::Any) {
+        self as &dyn (::std::any::Any)
+    }
+    fn as_any_mut(&mut self) -> &mut dyn (::std::any::Any) {
+        self as &mut dyn (::std::any::Any)
+    }
+    fn into_any(self: ::std::boxed::Box<Self>) -> ::std::boxed::Box<dyn (::std::any::Any)> {
+        self
+    }
+
+    fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor {
+        Self::descriptor_static()
+    }
+
+    fn new() -> UpdateDocRequest {
+        UpdateDocRequest::new()
+    }
+
+    fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor {
+        static descriptor: ::protobuf::rt::LazyV2<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::LazyV2::INIT;
+        descriptor.get(|| {
+            let mut fields = ::std::vec::Vec::new();
+            fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>(
+                "id",
+                |m: &UpdateDocRequest| { &m.id },
+                |m: &mut UpdateDocRequest| { &mut m.id },
+            ));
+            fields.push(::protobuf::reflect::accessor::make_singular_string_accessor::<_>(
+                "data",
+                UpdateDocRequest::has_data,
+                UpdateDocRequest::get_data,
+            ));
+            ::protobuf::reflect::MessageDescriptor::new_pb_name::<UpdateDocRequest>(
+                "UpdateDocRequest",
+                fields,
+                file_descriptor_proto()
+            )
+        })
+    }
+
+    fn default_instance() -> &'static UpdateDocRequest {
+        static instance: ::protobuf::rt::LazyV2<UpdateDocRequest> = ::protobuf::rt::LazyV2::INIT;
+        instance.get(UpdateDocRequest::new)
+    }
+}
+
+impl ::protobuf::Clear for UpdateDocRequest {
+    fn clear(&mut self) {
+        self.id.clear();
+        self.one_of_data = ::std::option::Option::None;
+        self.unknown_fields.clear();
+    }
+}
+
+impl ::std::fmt::Debug for UpdateDocRequest {
+    fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
+        ::protobuf::text_format::fmt(self, f)
+    }
+}
+
+impl ::protobuf::reflect::ProtobufValue for UpdateDocRequest {
+    fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef {
+        ::protobuf::reflect::ReflectValueRef::Message(self)
+    }
+}
+
+#[derive(PartialEq,Clone,Default)]
+pub struct UpdateDocParams {
+    // message fields
+    pub id: ::std::string::String,
+    // message oneof groups
+    pub one_of_data: ::std::option::Option<UpdateDocParams_oneof_one_of_data>,
+    // special fields
+    pub unknown_fields: ::protobuf::UnknownFields,
+    pub cached_size: ::protobuf::CachedSize,
+}
+
+impl<'a> ::std::default::Default for &'a UpdateDocParams {
+    fn default() -> &'a UpdateDocParams {
+        <UpdateDocParams as ::protobuf::Message>::default_instance()
+    }
+}
+
+#[derive(Clone,PartialEq,Debug)]
+pub enum UpdateDocParams_oneof_one_of_data {
+    data(::std::string::String),
+}
+
+impl UpdateDocParams {
+    pub fn new() -> UpdateDocParams {
+        ::std::default::Default::default()
+    }
+
+    // string id = 1;
+
+
+    pub fn get_id(&self) -> &str {
+        &self.id
+    }
+    pub fn clear_id(&mut self) {
+        self.id.clear();
     }
 
     // Param is passed by value, moved
-    pub fn set_desc(&mut self, v: ::std::string::String) {
-        self.one_of_desc = ::std::option::Option::Some(UpdateDocRequest_oneof_one_of_desc::desc(v))
+    pub fn set_id(&mut self, v: ::std::string::String) {
+        self.id = v;
     }
 
     // Mutable pointer to the field.
-    pub fn mut_desc(&mut self) -> &mut ::std::string::String {
-        if let ::std::option::Option::Some(UpdateDocRequest_oneof_one_of_desc::desc(_)) = self.one_of_desc {
-        } else {
-            self.one_of_desc = ::std::option::Option::Some(UpdateDocRequest_oneof_one_of_desc::desc(::std::string::String::new()));
-        }
-        match self.one_of_desc {
-            ::std::option::Option::Some(UpdateDocRequest_oneof_one_of_desc::desc(ref mut v)) => v,
-            _ => panic!(),
-        }
+    // If field is not initialized, it is initialized with default value first.
+    pub fn mut_id(&mut self) -> &mut ::std::string::String {
+        &mut self.id
     }
 
     // Take field
-    pub fn take_desc(&mut self) -> ::std::string::String {
-        if self.has_desc() {
-            match self.one_of_desc.take() {
-                ::std::option::Option::Some(UpdateDocRequest_oneof_one_of_desc::desc(v)) => v,
-                _ => panic!(),
-            }
-        } else {
-            ::std::string::String::new()
-        }
+    pub fn take_id(&mut self) -> ::std::string::String {
+        ::std::mem::replace(&mut self.id, ::std::string::String::new())
     }
 
-    // string text = 4;
+    // string data = 2;
 
 
-    pub fn get_text(&self) -> &str {
-        match self.one_of_text {
-            ::std::option::Option::Some(UpdateDocRequest_oneof_one_of_text::text(ref v)) => v,
+    pub fn get_data(&self) -> &str {
+        match self.one_of_data {
+            ::std::option::Option::Some(UpdateDocParams_oneof_one_of_data::data(ref v)) => v,
             _ => "",
         }
     }
-    pub fn clear_text(&mut self) {
-        self.one_of_text = ::std::option::Option::None;
+    pub fn clear_data(&mut self) {
+        self.one_of_data = ::std::option::Option::None;
     }
 
-    pub fn has_text(&self) -> bool {
-        match self.one_of_text {
-            ::std::option::Option::Some(UpdateDocRequest_oneof_one_of_text::text(..)) => true,
+    pub fn has_data(&self) -> bool {
+        match self.one_of_data {
+            ::std::option::Option::Some(UpdateDocParams_oneof_one_of_data::data(..)) => true,
             _ => false,
         }
     }
 
     // Param is passed by value, moved
-    pub fn set_text(&mut self, v: ::std::string::String) {
-        self.one_of_text = ::std::option::Option::Some(UpdateDocRequest_oneof_one_of_text::text(v))
+    pub fn set_data(&mut self, v: ::std::string::String) {
+        self.one_of_data = ::std::option::Option::Some(UpdateDocParams_oneof_one_of_data::data(v))
     }
 
     // Mutable pointer to the field.
-    pub fn mut_text(&mut self) -> &mut ::std::string::String {
-        if let ::std::option::Option::Some(UpdateDocRequest_oneof_one_of_text::text(_)) = self.one_of_text {
+    pub fn mut_data(&mut self) -> &mut ::std::string::String {
+        if let ::std::option::Option::Some(UpdateDocParams_oneof_one_of_data::data(_)) = self.one_of_data {
         } else {
-            self.one_of_text = ::std::option::Option::Some(UpdateDocRequest_oneof_one_of_text::text(::std::string::String::new()));
+            self.one_of_data = ::std::option::Option::Some(UpdateDocParams_oneof_one_of_data::data(::std::string::String::new()));
         }
-        match self.one_of_text {
-            ::std::option::Option::Some(UpdateDocRequest_oneof_one_of_text::text(ref mut v)) => v,
+        match self.one_of_data {
+            ::std::option::Option::Some(UpdateDocParams_oneof_one_of_data::data(ref mut v)) => v,
             _ => panic!(),
         }
     }
 
     // Take field
-    pub fn take_text(&mut self) -> ::std::string::String {
-        if self.has_text() {
-            match self.one_of_text.take() {
-                ::std::option::Option::Some(UpdateDocRequest_oneof_one_of_text::text(v)) => v,
+    pub fn take_data(&mut self) -> ::std::string::String {
+        if self.has_data() {
+            match self.one_of_data.take() {
+                ::std::option::Option::Some(UpdateDocParams_oneof_one_of_data::data(v)) => v,
                 _ => panic!(),
             }
         } else {
@@ -236,7 +367,7 @@ impl UpdateDocRequest {
     }
 }
 
-impl ::protobuf::Message for UpdateDocRequest {
+impl ::protobuf::Message for UpdateDocParams {
     fn is_initialized(&self) -> bool {
         true
     }
@@ -252,19 +383,7 @@ impl ::protobuf::Message for UpdateDocRequest {
                     if wire_type != ::protobuf::wire_format::WireTypeLengthDelimited {
                         return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type));
                     }
-                    self.one_of_name = ::std::option::Option::Some(UpdateDocRequest_oneof_one_of_name::name(is.read_string()?));
-                },
-                3 => {
-                    if wire_type != ::protobuf::wire_format::WireTypeLengthDelimited {
-                        return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type));
-                    }
-                    self.one_of_desc = ::std::option::Option::Some(UpdateDocRequest_oneof_one_of_desc::desc(is.read_string()?));
-                },
-                4 => {
-                    if wire_type != ::protobuf::wire_format::WireTypeLengthDelimited {
-                        return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type));
-                    }
-                    self.one_of_text = ::std::option::Option::Some(UpdateDocRequest_oneof_one_of_text::text(is.read_string()?));
+                    self.one_of_data = ::std::option::Option::Some(UpdateDocParams_oneof_one_of_data::data(is.read_string()?));
                 },
                 _ => {
                     ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?;
@@ -281,27 +400,13 @@ impl ::protobuf::Message for UpdateDocRequest {
         if !self.id.is_empty() {
             my_size += ::protobuf::rt::string_size(1, &self.id);
         }
-        if let ::std::option::Option::Some(ref v) = self.one_of_name {
+        if let ::std::option::Option::Some(ref v) = self.one_of_data {
             match v {
-                &UpdateDocRequest_oneof_one_of_name::name(ref v) => {
+                &UpdateDocParams_oneof_one_of_data::data(ref v) => {
                     my_size += ::protobuf::rt::string_size(2, &v);
                 },
             };
         }
-        if let ::std::option::Option::Some(ref v) = self.one_of_desc {
-            match v {
-                &UpdateDocRequest_oneof_one_of_desc::desc(ref v) => {
-                    my_size += ::protobuf::rt::string_size(3, &v);
-                },
-            };
-        }
-        if let ::std::option::Option::Some(ref v) = self.one_of_text {
-            match v {
-                &UpdateDocRequest_oneof_one_of_text::text(ref v) => {
-                    my_size += ::protobuf::rt::string_size(4, &v);
-                },
-            };
-        }
         my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields());
         self.cached_size.set(my_size);
         my_size
@@ -311,27 +416,13 @@ impl ::protobuf::Message for UpdateDocRequest {
         if !self.id.is_empty() {
             os.write_string(1, &self.id)?;
         }
-        if let ::std::option::Option::Some(ref v) = self.one_of_name {
+        if let ::std::option::Option::Some(ref v) = self.one_of_data {
             match v {
-                &UpdateDocRequest_oneof_one_of_name::name(ref v) => {
+                &UpdateDocParams_oneof_one_of_data::data(ref v) => {
                     os.write_string(2, v)?;
                 },
             };
         }
-        if let ::std::option::Option::Some(ref v) = self.one_of_desc {
-            match v {
-                &UpdateDocRequest_oneof_one_of_desc::desc(ref v) => {
-                    os.write_string(3, v)?;
-                },
-            };
-        }
-        if let ::std::option::Option::Some(ref v) = self.one_of_text {
-            match v {
-                &UpdateDocRequest_oneof_one_of_text::text(ref v) => {
-                    os.write_string(4, v)?;
-                },
-            };
-        }
         os.write_unknown_fields(self.get_unknown_fields())?;
         ::std::result::Result::Ok(())
     }
@@ -362,8 +453,8 @@ impl ::protobuf::Message for UpdateDocRequest {
         Self::descriptor_static()
     }
 
-    fn new() -> UpdateDocRequest {
-        UpdateDocRequest::new()
+    fn new() -> UpdateDocParams {
+        UpdateDocParams::new()
     }
 
     fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor {
@@ -372,82 +463,70 @@ impl ::protobuf::Message for UpdateDocRequest {
             let mut fields = ::std::vec::Vec::new();
             fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>(
                 "id",
-                |m: &UpdateDocRequest| { &m.id },
-                |m: &mut UpdateDocRequest| { &mut m.id },
-            ));
-            fields.push(::protobuf::reflect::accessor::make_singular_string_accessor::<_>(
-                "name",
-                UpdateDocRequest::has_name,
-                UpdateDocRequest::get_name,
+                |m: &UpdateDocParams| { &m.id },
+                |m: &mut UpdateDocParams| { &mut m.id },
             ));
             fields.push(::protobuf::reflect::accessor::make_singular_string_accessor::<_>(
-                "desc",
-                UpdateDocRequest::has_desc,
-                UpdateDocRequest::get_desc,
+                "data",
+                UpdateDocParams::has_data,
+                UpdateDocParams::get_data,
             ));
-            fields.push(::protobuf::reflect::accessor::make_singular_string_accessor::<_>(
-                "text",
-                UpdateDocRequest::has_text,
-                UpdateDocRequest::get_text,
-            ));
-            ::protobuf::reflect::MessageDescriptor::new_pb_name::<UpdateDocRequest>(
-                "UpdateDocRequest",
+            ::protobuf::reflect::MessageDescriptor::new_pb_name::<UpdateDocParams>(
+                "UpdateDocParams",
                 fields,
                 file_descriptor_proto()
             )
         })
     }
 
-    fn default_instance() -> &'static UpdateDocRequest {
-        static instance: ::protobuf::rt::LazyV2<UpdateDocRequest> = ::protobuf::rt::LazyV2::INIT;
-        instance.get(UpdateDocRequest::new)
+    fn default_instance() -> &'static UpdateDocParams {
+        static instance: ::protobuf::rt::LazyV2<UpdateDocParams> = ::protobuf::rt::LazyV2::INIT;
+        instance.get(UpdateDocParams::new)
     }
 }
 
-impl ::protobuf::Clear for UpdateDocRequest {
+impl ::protobuf::Clear for UpdateDocParams {
     fn clear(&mut self) {
         self.id.clear();
-        self.one_of_name = ::std::option::Option::None;
-        self.one_of_desc = ::std::option::Option::None;
-        self.one_of_text = ::std::option::Option::None;
+        self.one_of_data = ::std::option::Option::None;
         self.unknown_fields.clear();
     }
 }
 
-impl ::std::fmt::Debug for UpdateDocRequest {
+impl ::std::fmt::Debug for UpdateDocParams {
     fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
         ::protobuf::text_format::fmt(self, f)
     }
 }
 
-impl ::protobuf::reflect::ProtobufValue for UpdateDocRequest {
+impl ::protobuf::reflect::ProtobufValue for UpdateDocParams {
     fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef {
         ::protobuf::reflect::ReflectValueRef::Message(self)
     }
 }
 
 static file_descriptor_proto_data: &'static [u8] = b"\
-    \n\x10doc_modify.proto\"\x91\x01\n\x10UpdateDocRequest\x12\x0e\n\x02id\
-    \x18\x01\x20\x01(\tR\x02id\x12\x14\n\x04name\x18\x02\x20\x01(\tH\0R\x04n\
-    ame\x12\x14\n\x04desc\x18\x03\x20\x01(\tH\x01R\x04desc\x12\x14\n\x04text\
-    \x18\x04\x20\x01(\tH\x02R\x04textB\r\n\x0bone_of_nameB\r\n\x0bone_of_des\
-    cB\r\n\x0bone_of_textJ\xd7\x02\n\x06\x12\x04\0\0\x07\x01\n\x08\n\x01\x0c\
-    \x12\x03\0\0\x12\n\n\n\x02\x04\0\x12\x04\x02\0\x07\x01\n\n\n\x03\x04\0\
-    \x01\x12\x03\x02\x08\x18\n\x0b\n\x04\x04\0\x02\0\x12\x03\x03\x04\x12\n\
-    \x0c\n\x05\x04\0\x02\0\x05\x12\x03\x03\x04\n\n\x0c\n\x05\x04\0\x02\0\x01\
-    \x12\x03\x03\x0b\r\n\x0c\n\x05\x04\0\x02\0\x03\x12\x03\x03\x10\x11\n\x0b\
-    \n\x04\x04\0\x08\0\x12\x03\x04\x04*\n\x0c\n\x05\x04\0\x08\0\x01\x12\x03\
-    \x04\n\x15\n\x0b\n\x04\x04\0\x02\x01\x12\x03\x04\x18(\n\x0c\n\x05\x04\0\
-    \x02\x01\x05\x12\x03\x04\x18\x1e\n\x0c\n\x05\x04\0\x02\x01\x01\x12\x03\
-    \x04\x1f#\n\x0c\n\x05\x04\0\x02\x01\x03\x12\x03\x04&'\n\x0b\n\x04\x04\0\
-    \x08\x01\x12\x03\x05\x04*\n\x0c\n\x05\x04\0\x08\x01\x01\x12\x03\x05\n\
-    \x15\n\x0b\n\x04\x04\0\x02\x02\x12\x03\x05\x18(\n\x0c\n\x05\x04\0\x02\
-    \x02\x05\x12\x03\x05\x18\x1e\n\x0c\n\x05\x04\0\x02\x02\x01\x12\x03\x05\
-    \x1f#\n\x0c\n\x05\x04\0\x02\x02\x03\x12\x03\x05&'\n\x0b\n\x04\x04\0\x08\
-    \x02\x12\x03\x06\x04*\n\x0c\n\x05\x04\0\x08\x02\x01\x12\x03\x06\n\x15\n\
-    \x0b\n\x04\x04\0\x02\x03\x12\x03\x06\x18(\n\x0c\n\x05\x04\0\x02\x03\x05\
-    \x12\x03\x06\x18\x1e\n\x0c\n\x05\x04\0\x02\x03\x01\x12\x03\x06\x1f#\n\
-    \x0c\n\x05\x04\0\x02\x03\x03\x12\x03\x06&'b\x06proto3\
+    \n\x10doc_modify.proto\"G\n\x10UpdateDocRequest\x12\x0e\n\x02id\x18\x01\
+    \x20\x01(\tR\x02id\x12\x14\n\x04data\x18\x02\x20\x01(\tH\0R\x04dataB\r\n\
+    \x0bone_of_data\"F\n\x0fUpdateDocParams\x12\x0e\n\x02id\x18\x01\x20\x01(\
+    \tR\x02id\x12\x14\n\x04data\x18\x02\x20\x01(\tH\0R\x04dataB\r\n\x0bone_o\
+    f_dataJ\xd4\x02\n\x06\x12\x04\0\0\t\x01\n\x08\n\x01\x0c\x12\x03\0\0\x12\
+    \n\n\n\x02\x04\0\x12\x04\x02\0\x05\x01\n\n\n\x03\x04\0\x01\x12\x03\x02\
+    \x08\x18\n\x0b\n\x04\x04\0\x02\0\x12\x03\x03\x04\x12\n\x0c\n\x05\x04\0\
+    \x02\0\x05\x12\x03\x03\x04\n\n\x0c\n\x05\x04\0\x02\0\x01\x12\x03\x03\x0b\
+    \r\n\x0c\n\x05\x04\0\x02\0\x03\x12\x03\x03\x10\x11\n\x0b\n\x04\x04\0\x08\
+    \0\x12\x03\x04\x04*\n\x0c\n\x05\x04\0\x08\0\x01\x12\x03\x04\n\x15\n\x0b\
+    \n\x04\x04\0\x02\x01\x12\x03\x04\x18(\n\x0c\n\x05\x04\0\x02\x01\x05\x12\
+    \x03\x04\x18\x1e\n\x0c\n\x05\x04\0\x02\x01\x01\x12\x03\x04\x1f#\n\x0c\n\
+    \x05\x04\0\x02\x01\x03\x12\x03\x04&'\n\n\n\x02\x04\x01\x12\x04\x06\0\t\
+    \x01\n\n\n\x03\x04\x01\x01\x12\x03\x06\x08\x17\n\x0b\n\x04\x04\x01\x02\0\
+    \x12\x03\x07\x04\x12\n\x0c\n\x05\x04\x01\x02\0\x05\x12\x03\x07\x04\n\n\
+    \x0c\n\x05\x04\x01\x02\0\x01\x12\x03\x07\x0b\r\n\x0c\n\x05\x04\x01\x02\0\
+    \x03\x12\x03\x07\x10\x11\n\x0b\n\x04\x04\x01\x08\0\x12\x03\x08\x04*\n\
+    \x0c\n\x05\x04\x01\x08\0\x01\x12\x03\x08\n\x15\n\x0b\n\x04\x04\x01\x02\
+    \x01\x12\x03\x08\x18(\n\x0c\n\x05\x04\x01\x02\x01\x05\x12\x03\x08\x18\
+    \x1e\n\x0c\n\x05\x04\x01\x02\x01\x01\x12\x03\x08\x1f#\n\x0c\n\x05\x04\
+    \x01\x02\x01\x03\x12\x03\x08&'b\x06proto3\
 ";
 
 static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;

+ 30 - 75
rust-lib/flowy-document/src/protobuf/model/doc_query.rs

@@ -183,23 +183,22 @@ impl ::protobuf::reflect::ProtobufValue for QueryDocRequest {
 }
 
 #[derive(PartialEq,Clone,Default)]
-pub struct QueryDocDataRequest {
+pub struct QueryDocParams {
     // message fields
     pub doc_id: ::std::string::String,
-    pub path: ::std::string::String,
     // special fields
     pub unknown_fields: ::protobuf::UnknownFields,
     pub cached_size: ::protobuf::CachedSize,
 }
 
-impl<'a> ::std::default::Default for &'a QueryDocDataRequest {
-    fn default() -> &'a QueryDocDataRequest {
-        <QueryDocDataRequest as ::protobuf::Message>::default_instance()
+impl<'a> ::std::default::Default for &'a QueryDocParams {
+    fn default() -> &'a QueryDocParams {
+        <QueryDocParams as ::protobuf::Message>::default_instance()
     }
 }
 
-impl QueryDocDataRequest {
-    pub fn new() -> QueryDocDataRequest {
+impl QueryDocParams {
+    pub fn new() -> QueryDocParams {
         ::std::default::Default::default()
     }
 
@@ -228,35 +227,9 @@ impl QueryDocDataRequest {
     pub fn take_doc_id(&mut self) -> ::std::string::String {
         ::std::mem::replace(&mut self.doc_id, ::std::string::String::new())
     }
-
-    // string path = 2;
-
-
-    pub fn get_path(&self) -> &str {
-        &self.path
-    }
-    pub fn clear_path(&mut self) {
-        self.path.clear();
-    }
-
-    // Param is passed by value, moved
-    pub fn set_path(&mut self, v: ::std::string::String) {
-        self.path = v;
-    }
-
-    // Mutable pointer to the field.
-    // If field is not initialized, it is initialized with default value first.
-    pub fn mut_path(&mut self) -> &mut ::std::string::String {
-        &mut self.path
-    }
-
-    // Take field
-    pub fn take_path(&mut self) -> ::std::string::String {
-        ::std::mem::replace(&mut self.path, ::std::string::String::new())
-    }
 }
 
-impl ::protobuf::Message for QueryDocDataRequest {
+impl ::protobuf::Message for QueryDocParams {
     fn is_initialized(&self) -> bool {
         true
     }
@@ -268,9 +241,6 @@ impl ::protobuf::Message for QueryDocDataRequest {
                 1 => {
                     ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.doc_id)?;
                 },
-                2 => {
-                    ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.path)?;
-                },
                 _ => {
                     ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?;
                 },
@@ -286,9 +256,6 @@ impl ::protobuf::Message for QueryDocDataRequest {
         if !self.doc_id.is_empty() {
             my_size += ::protobuf::rt::string_size(1, &self.doc_id);
         }
-        if !self.path.is_empty() {
-            my_size += ::protobuf::rt::string_size(2, &self.path);
-        }
         my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields());
         self.cached_size.set(my_size);
         my_size
@@ -298,9 +265,6 @@ impl ::protobuf::Message for QueryDocDataRequest {
         if !self.doc_id.is_empty() {
             os.write_string(1, &self.doc_id)?;
         }
-        if !self.path.is_empty() {
-            os.write_string(2, &self.path)?;
-        }
         os.write_unknown_fields(self.get_unknown_fields())?;
         ::std::result::Result::Ok(())
     }
@@ -331,8 +295,8 @@ impl ::protobuf::Message for QueryDocDataRequest {
         Self::descriptor_static()
     }
 
-    fn new() -> QueryDocDataRequest {
-        QueryDocDataRequest::new()
+    fn new() -> QueryDocParams {
+        QueryDocParams::new()
     }
 
     fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor {
@@ -341,43 +305,37 @@ impl ::protobuf::Message for QueryDocDataRequest {
             let mut fields = ::std::vec::Vec::new();
             fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>(
                 "doc_id",
-                |m: &QueryDocDataRequest| { &m.doc_id },
-                |m: &mut QueryDocDataRequest| { &mut m.doc_id },
-            ));
-            fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>(
-                "path",
-                |m: &QueryDocDataRequest| { &m.path },
-                |m: &mut QueryDocDataRequest| { &mut m.path },
+                |m: &QueryDocParams| { &m.doc_id },
+                |m: &mut QueryDocParams| { &mut m.doc_id },
             ));
-            ::protobuf::reflect::MessageDescriptor::new_pb_name::<QueryDocDataRequest>(
-                "QueryDocDataRequest",
+            ::protobuf::reflect::MessageDescriptor::new_pb_name::<QueryDocParams>(
+                "QueryDocParams",
                 fields,
                 file_descriptor_proto()
             )
         })
     }
 
-    fn default_instance() -> &'static QueryDocDataRequest {
-        static instance: ::protobuf::rt::LazyV2<QueryDocDataRequest> = ::protobuf::rt::LazyV2::INIT;
-        instance.get(QueryDocDataRequest::new)
+    fn default_instance() -> &'static QueryDocParams {
+        static instance: ::protobuf::rt::LazyV2<QueryDocParams> = ::protobuf::rt::LazyV2::INIT;
+        instance.get(QueryDocParams::new)
     }
 }
 
-impl ::protobuf::Clear for QueryDocDataRequest {
+impl ::protobuf::Clear for QueryDocParams {
     fn clear(&mut self) {
         self.doc_id.clear();
-        self.path.clear();
         self.unknown_fields.clear();
     }
 }
 
-impl ::std::fmt::Debug for QueryDocDataRequest {
+impl ::std::fmt::Debug for QueryDocParams {
     fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
         ::protobuf::text_format::fmt(self, f)
     }
 }
 
-impl ::protobuf::reflect::ProtobufValue for QueryDocDataRequest {
+impl ::protobuf::reflect::ProtobufValue for QueryDocParams {
     fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef {
         ::protobuf::reflect::ReflectValueRef::Message(self)
     }
@@ -385,20 +343,17 @@ impl ::protobuf::reflect::ProtobufValue for QueryDocDataRequest {
 
 static file_descriptor_proto_data: &'static [u8] = b"\
     \n\x0fdoc_query.proto\"(\n\x0fQueryDocRequest\x12\x15\n\x06doc_id\x18\
-    \x01\x20\x01(\tR\x05docId\"@\n\x13QueryDocDataRequest\x12\x15\n\x06doc_i\
-    d\x18\x01\x20\x01(\tR\x05docId\x12\x12\n\x04path\x18\x02\x20\x01(\tR\x04\
-    pathJ\xe7\x01\n\x06\x12\x04\0\0\x08\x01\n\x08\n\x01\x0c\x12\x03\0\0\x12\
-    \n\n\n\x02\x04\0\x12\x04\x02\0\x04\x01\n\n\n\x03\x04\0\x01\x12\x03\x02\
-    \x08\x17\n\x0b\n\x04\x04\0\x02\0\x12\x03\x03\x04\x16\n\x0c\n\x05\x04\0\
-    \x02\0\x05\x12\x03\x03\x04\n\n\x0c\n\x05\x04\0\x02\0\x01\x12\x03\x03\x0b\
-    \x11\n\x0c\n\x05\x04\0\x02\0\x03\x12\x03\x03\x14\x15\n\n\n\x02\x04\x01\
-    \x12\x04\x05\0\x08\x01\n\n\n\x03\x04\x01\x01\x12\x03\x05\x08\x1b\n\x0b\n\
-    \x04\x04\x01\x02\0\x12\x03\x06\x04\x16\n\x0c\n\x05\x04\x01\x02\0\x05\x12\
-    \x03\x06\x04\n\n\x0c\n\x05\x04\x01\x02\0\x01\x12\x03\x06\x0b\x11\n\x0c\n\
-    \x05\x04\x01\x02\0\x03\x12\x03\x06\x14\x15\n\x0b\n\x04\x04\x01\x02\x01\
-    \x12\x03\x07\x04\x14\n\x0c\n\x05\x04\x01\x02\x01\x05\x12\x03\x07\x04\n\n\
-    \x0c\n\x05\x04\x01\x02\x01\x01\x12\x03\x07\x0b\x0f\n\x0c\n\x05\x04\x01\
-    \x02\x01\x03\x12\x03\x07\x12\x13b\x06proto3\
+    \x01\x20\x01(\tR\x05docId\"'\n\x0eQueryDocParams\x12\x15\n\x06doc_id\x18\
+    \x01\x20\x01(\tR\x05docIdJ\xb0\x01\n\x06\x12\x04\0\0\x07\x01\n\x08\n\x01\
+    \x0c\x12\x03\0\0\x12\n\n\n\x02\x04\0\x12\x04\x02\0\x04\x01\n\n\n\x03\x04\
+    \0\x01\x12\x03\x02\x08\x17\n\x0b\n\x04\x04\0\x02\0\x12\x03\x03\x04\x16\n\
+    \x0c\n\x05\x04\0\x02\0\x05\x12\x03\x03\x04\n\n\x0c\n\x05\x04\0\x02\0\x01\
+    \x12\x03\x03\x0b\x11\n\x0c\n\x05\x04\0\x02\0\x03\x12\x03\x03\x14\x15\n\n\
+    \n\x02\x04\x01\x12\x04\x05\0\x07\x01\n\n\n\x03\x04\x01\x01\x12\x03\x05\
+    \x08\x16\n\x0b\n\x04\x04\x01\x02\0\x12\x03\x06\x04\x16\n\x0c\n\x05\x04\
+    \x01\x02\0\x05\x12\x03\x06\x04\n\n\x0c\n\x05\x04\x01\x02\0\x01\x12\x03\
+    \x06\x0b\x11\n\x0c\n\x05\x04\x01\x02\0\x03\x12\x03\x06\x14\x15b\x06proto\
+    3\
 ";
 
 static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;

+ 51 - 79
rust-lib/flowy-document/src/protobuf/model/errors.rs

@@ -26,7 +26,7 @@
 #[derive(PartialEq,Clone,Default)]
 pub struct DocError {
     // message fields
-    pub code: DocErrorCode,
+    pub code: ErrorCode,
     pub msg: ::std::string::String,
     // special fields
     pub unknown_fields: ::protobuf::UnknownFields,
@@ -44,18 +44,18 @@ impl DocError {
         ::std::default::Default::default()
     }
 
-    // .DocErrorCode code = 1;
+    // .ErrorCode code = 1;
 
 
-    pub fn get_code(&self) -> DocErrorCode {
+    pub fn get_code(&self) -> ErrorCode {
         self.code
     }
     pub fn clear_code(&mut self) {
-        self.code = DocErrorCode::Unknown;
+        self.code = ErrorCode::DocIdInvalid;
     }
 
     // Param is passed by value, moved
-    pub fn set_code(&mut self, v: DocErrorCode) {
+    pub fn set_code(&mut self, v: ErrorCode) {
         self.code = v;
     }
 
@@ -113,7 +113,7 @@ impl ::protobuf::Message for DocError {
     #[allow(unused_variables)]
     fn compute_size(&self) -> u32 {
         let mut my_size = 0;
-        if self.code != DocErrorCode::Unknown {
+        if self.code != ErrorCode::DocIdInvalid {
             my_size += ::protobuf::rt::enum_size(1, self.code);
         }
         if !self.msg.is_empty() {
@@ -125,7 +125,7 @@ impl ::protobuf::Message for DocError {
     }
 
     fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::ProtobufResult<()> {
-        if self.code != DocErrorCode::Unknown {
+        if self.code != ErrorCode::DocIdInvalid {
             os.write_enum(1, ::protobuf::ProtobufEnum::value(&self.code))?;
         }
         if !self.msg.is_empty() {
@@ -169,7 +169,7 @@ impl ::protobuf::Message for DocError {
         static descriptor: ::protobuf::rt::LazyV2<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::LazyV2::INIT;
         descriptor.get(|| {
             let mut fields = ::std::vec::Vec::new();
-            fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeEnum<DocErrorCode>>(
+            fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeEnum<ErrorCode>>(
                 "code",
                 |m: &DocError| { &m.code },
                 |m: &mut DocError| { &mut m.code },
@@ -195,7 +195,7 @@ impl ::protobuf::Message for DocError {
 
 impl ::protobuf::Clear for DocError {
     fn clear(&mut self) {
-        self.code = DocErrorCode::Unknown;
+        self.code = ErrorCode::DocIdInvalid;
         self.msg.clear();
         self.unknown_fields.clear();
     }
@@ -214,49 +214,34 @@ impl ::protobuf::reflect::ProtobufValue for DocError {
 }
 
 #[derive(Clone,PartialEq,Eq,Debug,Hash)]
-pub enum DocErrorCode {
-    Unknown = 0,
-    EditorDBInternalError = 1,
-    EditorDBConnFailed = 2,
-    DocNameInvalid = 10,
-    DocViewIdInvalid = 11,
-    DocDescTooLong = 12,
-    DocOpenFileError = 13,
-    DocFilePathInvalid = 14,
-    EditorUserNotLoginYet = 100,
+pub enum ErrorCode {
+    DocIdInvalid = 0,
+    DocNotfound = 1,
+    UserUnauthorized = 999,
+    InternalError = 1000,
 }
 
-impl ::protobuf::ProtobufEnum for DocErrorCode {
+impl ::protobuf::ProtobufEnum for ErrorCode {
     fn value(&self) -> i32 {
         *self as i32
     }
 
-    fn from_i32(value: i32) -> ::std::option::Option<DocErrorCode> {
+    fn from_i32(value: i32) -> ::std::option::Option<ErrorCode> {
         match value {
-            0 => ::std::option::Option::Some(DocErrorCode::Unknown),
-            1 => ::std::option::Option::Some(DocErrorCode::EditorDBInternalError),
-            2 => ::std::option::Option::Some(DocErrorCode::EditorDBConnFailed),
-            10 => ::std::option::Option::Some(DocErrorCode::DocNameInvalid),
-            11 => ::std::option::Option::Some(DocErrorCode::DocViewIdInvalid),
-            12 => ::std::option::Option::Some(DocErrorCode::DocDescTooLong),
-            13 => ::std::option::Option::Some(DocErrorCode::DocOpenFileError),
-            14 => ::std::option::Option::Some(DocErrorCode::DocFilePathInvalid),
-            100 => ::std::option::Option::Some(DocErrorCode::EditorUserNotLoginYet),
+            0 => ::std::option::Option::Some(ErrorCode::DocIdInvalid),
+            1 => ::std::option::Option::Some(ErrorCode::DocNotfound),
+            999 => ::std::option::Option::Some(ErrorCode::UserUnauthorized),
+            1000 => ::std::option::Option::Some(ErrorCode::InternalError),
             _ => ::std::option::Option::None
         }
     }
 
     fn values() -> &'static [Self] {
-        static values: &'static [DocErrorCode] = &[
-            DocErrorCode::Unknown,
-            DocErrorCode::EditorDBInternalError,
-            DocErrorCode::EditorDBConnFailed,
-            DocErrorCode::DocNameInvalid,
-            DocErrorCode::DocViewIdInvalid,
-            DocErrorCode::DocDescTooLong,
-            DocErrorCode::DocOpenFileError,
-            DocErrorCode::DocFilePathInvalid,
-            DocErrorCode::EditorUserNotLoginYet,
+        static values: &'static [ErrorCode] = &[
+            ErrorCode::DocIdInvalid,
+            ErrorCode::DocNotfound,
+            ErrorCode::UserUnauthorized,
+            ErrorCode::InternalError,
         ];
         values
     }
@@ -264,61 +249,48 @@ impl ::protobuf::ProtobufEnum for DocErrorCode {
     fn enum_descriptor_static() -> &'static ::protobuf::reflect::EnumDescriptor {
         static descriptor: ::protobuf::rt::LazyV2<::protobuf::reflect::EnumDescriptor> = ::protobuf::rt::LazyV2::INIT;
         descriptor.get(|| {
-            ::protobuf::reflect::EnumDescriptor::new_pb_name::<DocErrorCode>("DocErrorCode", file_descriptor_proto())
+            ::protobuf::reflect::EnumDescriptor::new_pb_name::<ErrorCode>("ErrorCode", file_descriptor_proto())
         })
     }
 }
 
-impl ::std::marker::Copy for DocErrorCode {
+impl ::std::marker::Copy for ErrorCode {
 }
 
-impl ::std::default::Default for DocErrorCode {
+impl ::std::default::Default for ErrorCode {
     fn default() -> Self {
-        DocErrorCode::Unknown
+        ErrorCode::DocIdInvalid
     }
 }
 
-impl ::protobuf::reflect::ProtobufValue for DocErrorCode {
+impl ::protobuf::reflect::ProtobufValue for ErrorCode {
     fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef {
         ::protobuf::reflect::ReflectValueRef::Enum(::protobuf::ProtobufEnum::descriptor(self))
     }
 }
 
 static file_descriptor_proto_data: &'static [u8] = b"\
-    \n\x0cerrors.proto\"?\n\x08DocError\x12!\n\x04code\x18\x01\x20\x01(\x0e2\
-    \r.DocErrorCodeR\x04code\x12\x10\n\x03msg\x18\x02\x20\x01(\tR\x03msg*\
-    \xd5\x01\n\x0cDocErrorCode\x12\x0b\n\x07Unknown\x10\0\x12\x19\n\x15Edito\
-    rDBInternalError\x10\x01\x12\x16\n\x12EditorDBConnFailed\x10\x02\x12\x12\
-    \n\x0eDocNameInvalid\x10\n\x12\x14\n\x10DocViewIdInvalid\x10\x0b\x12\x12\
-    \n\x0eDocDescTooLong\x10\x0c\x12\x14\n\x10DocOpenFileError\x10\r\x12\x16\
-    \n\x12DocFilePathInvalid\x10\x0e\x12\x19\n\x15EditorUserNotLoginYet\x10d\
-    J\xa1\x04\n\x06\x12\x04\0\0\x10\x01\n\x08\n\x01\x0c\x12\x03\0\0\x12\n\n\
-    \n\x02\x04\0\x12\x04\x02\0\x05\x01\n\n\n\x03\x04\0\x01\x12\x03\x02\x08\
-    \x10\n\x0b\n\x04\x04\0\x02\0\x12\x03\x03\x04\x1a\n\x0c\n\x05\x04\0\x02\0\
-    \x06\x12\x03\x03\x04\x10\n\x0c\n\x05\x04\0\x02\0\x01\x12\x03\x03\x11\x15\
-    \n\x0c\n\x05\x04\0\x02\0\x03\x12\x03\x03\x18\x19\n\x0b\n\x04\x04\0\x02\
-    \x01\x12\x03\x04\x04\x13\n\x0c\n\x05\x04\0\x02\x01\x05\x12\x03\x04\x04\n\
-    \n\x0c\n\x05\x04\0\x02\x01\x01\x12\x03\x04\x0b\x0e\n\x0c\n\x05\x04\0\x02\
-    \x01\x03\x12\x03\x04\x11\x12\n\n\n\x02\x05\0\x12\x04\x06\0\x10\x01\n\n\n\
-    \x03\x05\0\x01\x12\x03\x06\x05\x11\n\x0b\n\x04\x05\0\x02\0\x12\x03\x07\
-    \x04\x10\n\x0c\n\x05\x05\0\x02\0\x01\x12\x03\x07\x04\x0b\n\x0c\n\x05\x05\
-    \0\x02\0\x02\x12\x03\x07\x0e\x0f\n\x0b\n\x04\x05\0\x02\x01\x12\x03\x08\
-    \x04\x1e\n\x0c\n\x05\x05\0\x02\x01\x01\x12\x03\x08\x04\x19\n\x0c\n\x05\
-    \x05\0\x02\x01\x02\x12\x03\x08\x1c\x1d\n\x0b\n\x04\x05\0\x02\x02\x12\x03\
-    \t\x04\x1b\n\x0c\n\x05\x05\0\x02\x02\x01\x12\x03\t\x04\x16\n\x0c\n\x05\
-    \x05\0\x02\x02\x02\x12\x03\t\x19\x1a\n\x0b\n\x04\x05\0\x02\x03\x12\x03\n\
-    \x04\x18\n\x0c\n\x05\x05\0\x02\x03\x01\x12\x03\n\x04\x12\n\x0c\n\x05\x05\
-    \0\x02\x03\x02\x12\x03\n\x15\x17\n\x0b\n\x04\x05\0\x02\x04\x12\x03\x0b\
-    \x04\x1a\n\x0c\n\x05\x05\0\x02\x04\x01\x12\x03\x0b\x04\x14\n\x0c\n\x05\
-    \x05\0\x02\x04\x02\x12\x03\x0b\x17\x19\n\x0b\n\x04\x05\0\x02\x05\x12\x03\
-    \x0c\x04\x18\n\x0c\n\x05\x05\0\x02\x05\x01\x12\x03\x0c\x04\x12\n\x0c\n\
-    \x05\x05\0\x02\x05\x02\x12\x03\x0c\x15\x17\n\x0b\n\x04\x05\0\x02\x06\x12\
-    \x03\r\x04\x1a\n\x0c\n\x05\x05\0\x02\x06\x01\x12\x03\r\x04\x14\n\x0c\n\
-    \x05\x05\0\x02\x06\x02\x12\x03\r\x17\x19\n\x0b\n\x04\x05\0\x02\x07\x12\
-    \x03\x0e\x04\x1c\n\x0c\n\x05\x05\0\x02\x07\x01\x12\x03\x0e\x04\x16\n\x0c\
-    \n\x05\x05\0\x02\x07\x02\x12\x03\x0e\x19\x1b\n\x0b\n\x04\x05\0\x02\x08\
-    \x12\x03\x0f\x04\x20\n\x0c\n\x05\x05\0\x02\x08\x01\x12\x03\x0f\x04\x19\n\
-    \x0c\n\x05\x05\0\x02\x08\x02\x12\x03\x0f\x1c\x1fb\x06proto3\
+    \n\x0cerrors.proto\"<\n\x08DocError\x12\x1e\n\x04code\x18\x01\x20\x01(\
+    \x0e2\n.ErrorCodeR\x04code\x12\x10\n\x03msg\x18\x02\x20\x01(\tR\x03msg*Y\
+    \n\tErrorCode\x12\x10\n\x0cDocIdInvalid\x10\0\x12\x0f\n\x0bDocNotfound\
+    \x10\x01\x12\x15\n\x10UserUnauthorized\x10\xe7\x07\x12\x12\n\rInternalEr\
+    ror\x10\xe8\x07J\xd4\x02\n\x06\x12\x04\0\0\x0b\x01\n\x08\n\x01\x0c\x12\
+    \x03\0\0\x12\n\n\n\x02\x04\0\x12\x04\x02\0\x05\x01\n\n\n\x03\x04\0\x01\
+    \x12\x03\x02\x08\x10\n\x0b\n\x04\x04\0\x02\0\x12\x03\x03\x04\x17\n\x0c\n\
+    \x05\x04\0\x02\0\x06\x12\x03\x03\x04\r\n\x0c\n\x05\x04\0\x02\0\x01\x12\
+    \x03\x03\x0e\x12\n\x0c\n\x05\x04\0\x02\0\x03\x12\x03\x03\x15\x16\n\x0b\n\
+    \x04\x04\0\x02\x01\x12\x03\x04\x04\x13\n\x0c\n\x05\x04\0\x02\x01\x05\x12\
+    \x03\x04\x04\n\n\x0c\n\x05\x04\0\x02\x01\x01\x12\x03\x04\x0b\x0e\n\x0c\n\
+    \x05\x04\0\x02\x01\x03\x12\x03\x04\x11\x12\n\n\n\x02\x05\0\x12\x04\x06\0\
+    \x0b\x01\n\n\n\x03\x05\0\x01\x12\x03\x06\x05\x0e\n\x0b\n\x04\x05\0\x02\0\
+    \x12\x03\x07\x04\x15\n\x0c\n\x05\x05\0\x02\0\x01\x12\x03\x07\x04\x10\n\
+    \x0c\n\x05\x05\0\x02\0\x02\x12\x03\x07\x13\x14\n\x0b\n\x04\x05\0\x02\x01\
+    \x12\x03\x08\x04\x14\n\x0c\n\x05\x05\0\x02\x01\x01\x12\x03\x08\x04\x0f\n\
+    \x0c\n\x05\x05\0\x02\x01\x02\x12\x03\x08\x12\x13\n\x0b\n\x04\x05\0\x02\
+    \x02\x12\x03\t\x04\x1b\n\x0c\n\x05\x05\0\x02\x02\x01\x12\x03\t\x04\x14\n\
+    \x0c\n\x05\x05\0\x02\x02\x02\x12\x03\t\x17\x1a\n\x0b\n\x04\x05\0\x02\x03\
+    \x12\x03\n\x04\x19\n\x0c\n\x05\x05\0\x02\x03\x01\x12\x03\n\x04\x11\n\x0c\
+    \n\x05\x05\0\x02\x03\x02\x12\x03\n\x14\x18b\x06proto3\
 ";
 
 static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;

+ 19 - 19
rust-lib/flowy-document/src/protobuf/model/event.rs

@@ -27,8 +27,8 @@
 pub enum EditorEvent {
     CreateDoc = 0,
     UpdateDoc = 1,
-    ReadDocInfo = 2,
-    ReadDocData = 3,
+    ReadDoc = 2,
+    DeleteDoc = 3,
 }
 
 impl ::protobuf::ProtobufEnum for EditorEvent {
@@ -40,8 +40,8 @@ impl ::protobuf::ProtobufEnum for EditorEvent {
         match value {
             0 => ::std::option::Option::Some(EditorEvent::CreateDoc),
             1 => ::std::option::Option::Some(EditorEvent::UpdateDoc),
-            2 => ::std::option::Option::Some(EditorEvent::ReadDocInfo),
-            3 => ::std::option::Option::Some(EditorEvent::ReadDocData),
+            2 => ::std::option::Option::Some(EditorEvent::ReadDoc),
+            3 => ::std::option::Option::Some(EditorEvent::DeleteDoc),
             _ => ::std::option::Option::None
         }
     }
@@ -50,8 +50,8 @@ impl ::protobuf::ProtobufEnum for EditorEvent {
         static values: &'static [EditorEvent] = &[
             EditorEvent::CreateDoc,
             EditorEvent::UpdateDoc,
-            EditorEvent::ReadDocInfo,
-            EditorEvent::ReadDocData,
+            EditorEvent::ReadDoc,
+            EditorEvent::DeleteDoc,
         ];
         values
     }
@@ -80,19 +80,19 @@ impl ::protobuf::reflect::ProtobufValue for EditorEvent {
 }
 
 static file_descriptor_proto_data: &'static [u8] = b"\
-    \n\x0bevent.proto*M\n\x0bEditorEvent\x12\r\n\tCreateDoc\x10\0\x12\r\n\tU\
-    pdateDoc\x10\x01\x12\x0f\n\x0bReadDocInfo\x10\x02\x12\x0f\n\x0bReadDocDa\
-    ta\x10\x03J\xce\x01\n\x06\x12\x04\0\0\x07\x01\n\x08\n\x01\x0c\x12\x03\0\
-    \0\x12\n\n\n\x02\x05\0\x12\x04\x02\0\x07\x01\n\n\n\x03\x05\0\x01\x12\x03\
-    \x02\x05\x10\n\x0b\n\x04\x05\0\x02\0\x12\x03\x03\x04\x12\n\x0c\n\x05\x05\
-    \0\x02\0\x01\x12\x03\x03\x04\r\n\x0c\n\x05\x05\0\x02\0\x02\x12\x03\x03\
-    \x10\x11\n\x0b\n\x04\x05\0\x02\x01\x12\x03\x04\x04\x12\n\x0c\n\x05\x05\0\
-    \x02\x01\x01\x12\x03\x04\x04\r\n\x0c\n\x05\x05\0\x02\x01\x02\x12\x03\x04\
-    \x10\x11\n\x0b\n\x04\x05\0\x02\x02\x12\x03\x05\x04\x14\n\x0c\n\x05\x05\0\
-    \x02\x02\x01\x12\x03\x05\x04\x0f\n\x0c\n\x05\x05\0\x02\x02\x02\x12\x03\
-    \x05\x12\x13\n\x0b\n\x04\x05\0\x02\x03\x12\x03\x06\x04\x14\n\x0c\n\x05\
-    \x05\0\x02\x03\x01\x12\x03\x06\x04\x0f\n\x0c\n\x05\x05\0\x02\x03\x02\x12\
-    \x03\x06\x12\x13b\x06proto3\
+    \n\x0bevent.proto*G\n\x0bEditorEvent\x12\r\n\tCreateDoc\x10\0\x12\r\n\tU\
+    pdateDoc\x10\x01\x12\x0b\n\x07ReadDoc\x10\x02\x12\r\n\tDeleteDoc\x10\x03\
+    J\xce\x01\n\x06\x12\x04\0\0\x07\x01\n\x08\n\x01\x0c\x12\x03\0\0\x12\n\n\
+    \n\x02\x05\0\x12\x04\x02\0\x07\x01\n\n\n\x03\x05\0\x01\x12\x03\x02\x05\
+    \x10\n\x0b\n\x04\x05\0\x02\0\x12\x03\x03\x04\x12\n\x0c\n\x05\x05\0\x02\0\
+    \x01\x12\x03\x03\x04\r\n\x0c\n\x05\x05\0\x02\0\x02\x12\x03\x03\x10\x11\n\
+    \x0b\n\x04\x05\0\x02\x01\x12\x03\x04\x04\x12\n\x0c\n\x05\x05\0\x02\x01\
+    \x01\x12\x03\x04\x04\r\n\x0c\n\x05\x05\0\x02\x01\x02\x12\x03\x04\x10\x11\
+    \n\x0b\n\x04\x05\0\x02\x02\x12\x03\x05\x04\x10\n\x0c\n\x05\x05\0\x02\x02\
+    \x01\x12\x03\x05\x04\x0b\n\x0c\n\x05\x05\0\x02\x02\x02\x12\x03\x05\x0e\
+    \x0f\n\x0b\n\x04\x05\0\x02\x03\x12\x03\x06\x04\x12\n\x0c\n\x05\x05\0\x02\
+    \x03\x01\x12\x03\x06\x04\r\n\x0c\n\x05\x05\0\x02\x03\x02\x12\x03\x06\x10\
+    \x11b\x06proto3\
 ";
 
 static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;

+ 3 - 0
rust-lib/flowy-document/src/protobuf/model/mod.rs

@@ -6,6 +6,9 @@ pub use doc_modify::*;
 mod doc_create; 
 pub use doc_create::*; 
 
+mod observable; 
+pub use observable::*; 
+
 mod errors; 
 pub use errors::*; 
 

+ 92 - 0
rust-lib/flowy-document/src/protobuf/model/observable.rs

@@ -0,0 +1,92 @@
+// This file is generated by rust-protobuf 2.22.1. Do not edit
+// @generated
+
+// https://github.com/rust-lang/rust-clippy/issues/702
+#![allow(unknown_lints)]
+#![allow(clippy::all)]
+
+#![allow(unused_attributes)]
+#![cfg_attr(rustfmt, rustfmt::skip)]
+
+#![allow(box_pointers)]
+#![allow(dead_code)]
+#![allow(missing_docs)]
+#![allow(non_camel_case_types)]
+#![allow(non_snake_case)]
+#![allow(non_upper_case_globals)]
+#![allow(trivial_casts)]
+#![allow(unused_imports)]
+#![allow(unused_results)]
+//! Generated file from `observable.proto`
+
+/// Generated files are compatible only with the same version
+/// of protobuf runtime.
+// const _PROTOBUF_VERSION_CHECK: () = ::protobuf::VERSION_2_22_1;
+
+#[derive(Clone,PartialEq,Eq,Debug,Hash)]
+pub enum DocObservable {
+    UserCreateDoc = 0,
+}
+
+impl ::protobuf::ProtobufEnum for DocObservable {
+    fn value(&self) -> i32 {
+        *self as i32
+    }
+
+    fn from_i32(value: i32) -> ::std::option::Option<DocObservable> {
+        match value {
+            0 => ::std::option::Option::Some(DocObservable::UserCreateDoc),
+            _ => ::std::option::Option::None
+        }
+    }
+
+    fn values() -> &'static [Self] {
+        static values: &'static [DocObservable] = &[
+            DocObservable::UserCreateDoc,
+        ];
+        values
+    }
+
+    fn enum_descriptor_static() -> &'static ::protobuf::reflect::EnumDescriptor {
+        static descriptor: ::protobuf::rt::LazyV2<::protobuf::reflect::EnumDescriptor> = ::protobuf::rt::LazyV2::INIT;
+        descriptor.get(|| {
+            ::protobuf::reflect::EnumDescriptor::new_pb_name::<DocObservable>("DocObservable", file_descriptor_proto())
+        })
+    }
+}
+
+impl ::std::marker::Copy for DocObservable {
+}
+
+impl ::std::default::Default for DocObservable {
+    fn default() -> Self {
+        DocObservable::UserCreateDoc
+    }
+}
+
+impl ::protobuf::reflect::ProtobufValue for DocObservable {
+    fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef {
+        ::protobuf::reflect::ReflectValueRef::Enum(::protobuf::ProtobufEnum::descriptor(self))
+    }
+}
+
+static file_descriptor_proto_data: &'static [u8] = b"\
+    \n\x10observable.proto*\"\n\rDocObservable\x12\x11\n\rUserCreateDoc\x10\
+    \0JS\n\x06\x12\x04\0\0\x04\x01\n\x08\n\x01\x0c\x12\x03\0\0\x12\n\n\n\x02\
+    \x05\0\x12\x04\x02\0\x04\x01\n\n\n\x03\x05\0\x01\x12\x03\x02\x05\x12\n\
+    \x0b\n\x04\x05\0\x02\0\x12\x03\x03\x04\x16\n\x0c\n\x05\x05\0\x02\0\x01\
+    \x12\x03\x03\x04\x11\n\x0c\n\x05\x05\0\x02\0\x02\x12\x03\x03\x14\x15b\
+    \x06proto3\
+";
+
+static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;
+
+fn parse_descriptor_proto() -> ::protobuf::descriptor::FileDescriptorProto {
+    ::protobuf::Message::parse_from_bytes(file_descriptor_proto_data).unwrap()
+}
+
+pub fn file_descriptor_proto() -> &'static ::protobuf::descriptor::FileDescriptorProto {
+    file_descriptor_proto_lazy.get(|| {
+        parse_descriptor_proto()
+    })
+}

+ 6 - 9
rust-lib/flowy-document/src/protobuf/proto/doc_create.proto

@@ -2,16 +2,13 @@ syntax = "proto3";
 
 message CreateDocRequest {
     string id = 1;
-    string name = 2;
-    string desc = 3;
-    string text = 4;
+    string data = 2;
 }
-message DocInfo {
+message CreateDocParams {
     string id = 1;
-    string name = 2;
-    string desc = 3;
-    string path = 4;
+    string data = 2;
 }
-message DocData {
-    string text = 1;
+message Doc {
+    string id = 1;
+    string data = 2;
 }

+ 5 - 3
rust-lib/flowy-document/src/protobuf/proto/doc_modify.proto

@@ -2,7 +2,9 @@ syntax = "proto3";
 
 message UpdateDocRequest {
     string id = 1;
-    oneof one_of_name { string name = 2; };
-    oneof one_of_desc { string desc = 3; };
-    oneof one_of_text { string text = 4; };
+    oneof one_of_data { string data = 2; };
+}
+message UpdateDocParams {
+    string id = 1;
+    oneof one_of_data { string data = 2; };
 }

+ 1 - 2
rust-lib/flowy-document/src/protobuf/proto/doc_query.proto

@@ -3,7 +3,6 @@ syntax = "proto3";
 message QueryDocRequest {
     string doc_id = 1;
 }
-message QueryDocDataRequest {
+message QueryDocParams {
     string doc_id = 1;
-    string path = 2;
 }

+ 6 - 11
rust-lib/flowy-document/src/protobuf/proto/errors.proto

@@ -1,17 +1,12 @@
 syntax = "proto3";
 
 message DocError {
-    DocErrorCode code = 1;
+    ErrorCode code = 1;
     string msg = 2;
 }
-enum DocErrorCode {
-    Unknown = 0;
-    EditorDBInternalError = 1;
-    EditorDBConnFailed = 2;
-    DocNameInvalid = 10;
-    DocViewIdInvalid = 11;
-    DocDescTooLong = 12;
-    DocOpenFileError = 13;
-    DocFilePathInvalid = 14;
-    EditorUserNotLoginYet = 100;
+enum ErrorCode {
+    DocIdInvalid = 0;
+    DocNotfound = 1;
+    UserUnauthorized = 999;
+    InternalError = 1000;
 }

+ 2 - 2
rust-lib/flowy-document/src/protobuf/proto/event.proto

@@ -3,6 +3,6 @@ syntax = "proto3";
 enum EditorEvent {
     CreateDoc = 0;
     UpdateDoc = 1;
-    ReadDocInfo = 2;
-    ReadDocData = 3;
+    ReadDoc = 2;
+    DeleteDoc = 3;
 }

+ 5 - 0
rust-lib/flowy-document/src/protobuf/proto/observable.proto

@@ -0,0 +1,5 @@
+syntax = "proto3";
+
+enum DocObservable {
+    UserCreateDoc = 0;
+}

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

@@ -1,42 +1,118 @@
 use crate::{
-    entities::doc::{CreateDocParams, DocInfo, UpdateDocParams},
+    entities::doc::{CreateDocParams, Doc, QueryDocParams, UpdateDocParams},
     errors::DocError,
-    module::DocumentDatabase,
+    module::{DocumentDatabase, DocumentUser},
+    services::server::Server,
     sql_tables::doc::{DocTable, DocTableChangeset, DocTableSql},
 };
 use std::sync::Arc;
 
 pub struct DocController {
+    server: Server,
     sql: Arc<DocTableSql>,
+    user: Arc<dyn DocumentUser>,
+    database: Arc<dyn DocumentDatabase>,
 }
 
 impl DocController {
-    pub(crate) fn new(database: Arc<dyn DocumentDatabase>) -> Self {
-        let sql = Arc::new(DocTableSql { database });
-        Self { sql }
+    pub(crate) fn new(database: Arc<dyn DocumentDatabase>, server: Server, user: Arc<dyn DocumentUser>) -> Self {
+        let sql = Arc::new(DocTableSql {});
+        Self {
+            sql,
+            server,
+            user,
+            database,
+        }
     }
 
-    pub(crate) async fn create_doc(
-        &self,
-        params: CreateDocParams,
-        path: &str,
-    ) -> Result<DocInfo, DocError> {
-        let doc_table = DocTable::new(params, path);
-        let doc: DocInfo = doc_table.clone().into();
-        let _ = self.sql.create_doc_table(doc_table)?;
+    pub(crate) async fn create_doc(&self, params: CreateDocParams) -> Result<Doc, DocError> {
+        let doc = self.create_doc_on_server(params).await?;
+        let doc_table = DocTable::new(doc.clone());
+
+        let conn = self.database.db_connection()?;
+        let _ = self.sql.create_doc_table(doc_table, &*conn)?;
 
         Ok(doc)
     }
 
     pub(crate) async fn update_doc(&self, params: UpdateDocParams) -> Result<(), DocError> {
-        let changeset = DocTableChangeset::new(params);
-        let _ = self.sql.update_doc_table(changeset)?;
+        let changeset = DocTableChangeset::new(params.clone());
+        let conn = self.database.db_connection()?;
+        let _ = self.sql.update_doc_table(changeset, &*conn)?;
+        let _ = self.update_doc_on_server(params)?;
+
+        Ok(())
+    }
+
+    pub(crate) async fn read_doc(&self, params: QueryDocParams) -> Result<Doc, DocError> {
+        let conn = self.database.db_connection()?;
+        let doc: Doc = self.sql.read_doc_table(&params.doc_id, &*conn)?.into();
+
+        let _ = self.read_doc_on_server(params)?;
+        Ok(doc)
+    }
+
+    pub(crate) async fn delete_doc(&self, params: QueryDocParams) -> Result<(), DocError> {
+        let conn = self.database.db_connection()?;
+        let _ = self.sql.delete_doc(&params.doc_id, &*conn)?;
+
+        let _ = self.delete_doc_on_server(params)?;
         Ok(())
     }
+}
 
-    pub(crate) async fn read_doc(&self, doc_id: &str) -> Result<DocInfo, DocError> {
-        let doc_table = self.sql.read_doc_table(doc_id)?;
-        let doc_desc: DocInfo = doc_table.into();
-        Ok(doc_desc)
+impl DocController {
+    #[tracing::instrument(level = "debug", 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)]
+    fn update_doc_on_server(&self, params: UpdateDocParams) -> Result<(), DocError> {
+        let token = self.user.token()?;
+        let server = self.server.clone();
+        tokio::spawn(async move {
+            match server.update_doc(&token, params).await {
+                Ok(_) => {},
+                Err(e) => {
+                    // TODO: retry?
+                    log::error!("Update doc failed: {}", e);
+                },
+            }
+        });
+        Ok(())
+    }
+
+    #[tracing::instrument(level = "debug", skip(self, params), 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?;
+            // save to disk
+            // notify
+
+            Result::<(), DocError>::Ok(())
+        });
+        Ok(())
+    }
+
+    #[tracing::instrument(level = "debug", skip(self, params), err)]
+    fn delete_doc_on_server(&self, params: QueryDocParams) -> Result<(), DocError> {
+        let token = self.user.token()?;
+        let server = self.server.clone();
+        tokio::spawn(async move {
+            match server.delete_doc(&token, params).await {
+                Ok(_) => {},
+                Err(e) => {
+                    // TODO: retry?
+                    log::error!("Delete doc failed: {:?}", e);
+                },
+            }
+        });
+        Ok(())
     }
 }

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

@@ -1,2 +1,3 @@
 pub mod doc_controller;
 pub mod file_manager;
+pub mod server;

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

@@ -0,0 +1,29 @@
+use flowy_net::{request::ResponseMiddleware, response::FlowyResponse};
+use lazy_static::lazy_static;
+use std::sync::Arc;
+
+lazy_static! {
+    pub(crate) static ref MIDDLEWARE: Arc<DocMiddleware> = Arc::new(DocMiddleware {});
+}
+
+pub(crate) struct DocMiddleware {}
+impl ResponseMiddleware for DocMiddleware {
+    fn receive_response(&self, token: &Option<String>, response: &FlowyResponse) {
+        if let Some(error) = &response.error {
+            if error.is_unauthorized() {
+                log::error!("workspace user is unauthorized");
+
+                match token {
+                    None => {},
+                    Some(token) => {
+                        // let error =
+                        // WorkspaceError::new(ErrorCode::UserUnauthorized, "");
+                        // observable(token,
+                        // WorkspaceObservable::UserUnauthorized).error(error).
+                        // build()
+                    },
+                }
+            }
+        }
+    }
+}

+ 32 - 0
rust-lib/flowy-document/src/services/server/mod.rs

@@ -0,0 +1,32 @@
+mod middleware;
+mod server_api;
+mod server_api_mock;
+
+pub use server_api::*;
+// TODO: ignore mock files in production
+use crate::{
+    entities::doc::{CreateDocParams, Doc, QueryDocParams, UpdateDocParams},
+    errors::DocError,
+};
+use flowy_infra::future::ResultFuture;
+pub use server_api_mock::*;
+use std::sync::Arc;
+
+pub(crate) type Server = Arc<dyn DocumentServerAPI + Send + Sync>;
+pub trait DocumentServerAPI {
+    fn create_doc(&self, token: &str, params: CreateDocParams) -> ResultFuture<Doc, DocError>;
+
+    fn read_doc(&self, token: &str, params: QueryDocParams) -> ResultFuture<Option<Doc>, DocError>;
+
+    fn update_doc(&self, token: &str, params: UpdateDocParams) -> ResultFuture<(), DocError>;
+
+    fn delete_doc(&self, token: &str, params: QueryDocParams) -> ResultFuture<(), DocError>;
+}
+
+pub(crate) fn construct_doc_server() -> Arc<dyn DocumentServerAPI + Send + Sync> {
+    if cfg!(feature = "http_server") {
+        Arc::new(DocServer {})
+    } else {
+        Arc::new(DocServerMock {})
+    }
+}

+ 33 - 0
rust-lib/flowy-document/src/services/server/server_api.rs

@@ -0,0 +1,33 @@
+use crate::{
+    entities::doc::{CreateDocParams, Doc, QueryDocParams, UpdateDocParams},
+    errors::DocError,
+    services::server::DocumentServerAPI,
+};
+use flowy_infra::future::ResultFuture;
+use flowy_net::{config::HEADER_TOKEN, request::HttpRequestBuilder};
+
+pub struct DocServer {}
+
+impl DocumentServerAPI for DocServer {
+    fn create_doc(&self, token: &str, params: CreateDocParams) -> ResultFuture<Doc, DocError> { unimplemented!() }
+
+    fn read_doc(&self, token: &str, params: QueryDocParams) -> ResultFuture<Option<Doc>, DocError> { unimplemented!() }
+
+    fn update_doc(&self, token: &str, params: UpdateDocParams) -> ResultFuture<(), DocError> { unimplemented!() }
+
+    fn delete_doc(&self, token: &str, params: QueryDocParams) -> ResultFuture<(), DocError> { unimplemented!() }
+}
+
+pub(crate) fn request_builder() -> HttpRequestBuilder { HttpRequestBuilder::new().middleware(super::middleware::MIDDLEWARE.clone()) }
+
+pub async fn create_doc_request(token: &str, params: CreateDocParams, url: &str) -> Result<Doc, DocError> {
+    let doc = request_builder()
+        .post(&url.to_owned())
+        .header(HEADER_TOKEN, token)
+        .protobuf(params)?
+        .send()
+        .await?
+        .response()
+        .await?;
+    Ok(doc)
+}

+ 27 - 0
rust-lib/flowy-document/src/services/server/server_api_mock.rs

@@ -0,0 +1,27 @@
+use crate::{
+    entities::doc::{CreateDocParams, Doc, QueryDocParams, UpdateDocParams},
+    errors::DocError,
+    services::server::DocumentServerAPI,
+};
+use flowy_infra::{future::ResultFuture, uuid};
+pub struct DocServerMock {}
+
+impl DocumentServerAPI for DocServerMock {
+    fn create_doc(&self, _token: &str, _params: CreateDocParams) -> ResultFuture<Doc, DocError> {
+        let uuid = uuid();
+        let doc = Doc {
+            id: uuid,
+            data: "".to_string(),
+        };
+
+        ResultFuture::new(async { Ok(doc) })
+    }
+
+    fn read_doc(&self, _token: &str, _params: QueryDocParams) -> ResultFuture<Option<Doc>, DocError> {
+        ResultFuture::new(async { Ok(None) })
+    }
+
+    fn update_doc(&self, _token: &str, _params: UpdateDocParams) -> ResultFuture<(), DocError> { ResultFuture::new(async { Ok(()) }) }
+
+    fn delete_doc(&self, _token: &str, _params: QueryDocParams) -> ResultFuture<(), DocError> { ResultFuture::new(async { Ok(()) }) }
+}

+ 13 - 15
rust-lib/flowy-document/src/sql_tables/doc/doc_sql.rs

@@ -6,34 +6,32 @@ use crate::{
 use flowy_database::{
     prelude::*,
     schema::{doc_table, doc_table::dsl},
+    SqliteConnection,
 };
 use std::sync::Arc;
-
-pub struct DocTableSql {
-    pub database: Arc<dyn DocumentDatabase>,
-}
+pub struct DocTableSql {}
 
 impl DocTableSql {
-    pub(crate) fn create_doc_table(&self, doc_table: DocTable) -> Result<(), DocError> {
-        let conn = self.database.db_connection()?;
-        let _ = diesel::insert_into(doc_table::table).values(doc_table).execute(&*conn)?;
+    pub(crate) fn create_doc_table(&self, doc_table: DocTable, conn: &SqliteConnection) -> Result<(), DocError> {
+        let _ = diesel::insert_into(doc_table::table).values(doc_table).execute(conn)?;
         Ok(())
     }
 
-    pub(crate) fn update_doc_table(&self, changeset: DocTableChangeset) -> Result<(), DocError> {
-        let conn = self.database.db_connection()?;
-        diesel_update_table!(doc_table, changeset, &*conn);
+    pub(crate) fn update_doc_table(&self, changeset: DocTableChangeset, conn: &SqliteConnection) -> Result<(), DocError> {
+        diesel_update_table!(doc_table, changeset, conn);
         Ok(())
     }
 
-    pub(crate) fn read_doc_table(&self, doc_id: &str) -> Result<DocTable, DocError> {
-        let doc_table = dsl::doc_table
-            .filter(doc_table::id.eq(doc_id))
-            .first::<DocTable>(&*(self.database.db_connection()?))?;
+    pub(crate) fn read_doc_table(&self, doc_id: &str, conn: &SqliteConnection) -> Result<DocTable, DocError> {
+        let doc_table = dsl::doc_table.filter(doc_table::id.eq(doc_id)).first::<DocTable>(conn)?;
 
         Ok(doc_table)
     }
 
     #[allow(dead_code)]
-    pub(crate) fn delete_doc(&self, _view_id: &str) -> Result<(), DocError> { unimplemented!() }
+    pub(crate) fn delete_doc(&self, doc_id: &str, conn: &SqliteConnection) -> Result<DocTable, DocError> {
+        let doc_table = dsl::doc_table.filter(doc_table::id.eq(doc_id)).first::<DocTable>(conn)?;
+        diesel_delete_table!(doc_table, doc_id, conn);
+        Ok(doc_table)
+    }
 }

+ 11 - 24
rust-lib/flowy-document/src/sql_tables/doc/doc_table.rs

@@ -1,4 +1,4 @@
-use crate::entities::doc::{CreateDocParams, DocInfo, UpdateDocParams};
+use crate::entities::doc::{CreateDocParams, Doc, UpdateDocParams};
 use flowy_database::schema::doc_table;
 use flowy_infra::timestamp;
 
@@ -6,24 +6,15 @@ use flowy_infra::timestamp;
 #[table_name = "doc_table"]
 pub(crate) struct DocTable {
     pub id: String,
-    pub name: String,
-    pub desc: String,
-    pub path: String,
-    pub modified_time: i64,
-    pub create_time: i64,
+    pub data: String,
     pub version: i64,
 }
 
 impl DocTable {
-    pub fn new(params: CreateDocParams, path: &str) -> Self {
-        let time = timestamp();
+    pub fn new(doc: Doc) -> Self {
         Self {
-            id: params.id,
-            name: params.name,
-            desc: params.desc,
-            path: path.to_owned(),
-            modified_time: time,
-            create_time: time,
+            id: doc.id,
+            data: "".to_owned(),
             version: 0,
         }
     }
@@ -33,27 +24,23 @@ impl DocTable {
 #[table_name = "doc_table"]
 pub(crate) struct DocTableChangeset {
     pub id: String,
-    pub name: Option<String>,
-    pub desc: Option<String>,
+    pub data: Option<String>,
 }
 
 impl DocTableChangeset {
     pub(crate) fn new(params: UpdateDocParams) -> Self {
         Self {
             id: params.id,
-            name: params.name,
-            desc: params.desc,
+            data: params.data,
         }
     }
 }
 
-impl std::convert::Into<DocInfo> for DocTable {
-    fn into(self) -> DocInfo {
-        DocInfo {
+impl std::convert::Into<Doc> for DocTable {
+    fn into(self) -> Doc {
+        Doc {
             id: self.id,
-            name: self.name,
-            desc: self.desc,
-            path: self.path,
+            data: self.data,
         }
     }
 }

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

@@ -4,28 +4,28 @@ 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) -> DocInfo {
+pub fn create_doc(sdk: &FlowyTestSDK, name: &str, desc: &str, text: &str) -> Doc {
     let request = CreateDocRequest {
         id: uuid(),
         name: name.to_owned(),
         desc: desc.to_owned(),
-        text: text.to_owned(),
+        data: text.to_owned(),
     };
 
     let doc = DocTest::new(sdk.clone())
         .event(CreateDoc)
         .request(request)
         .sync_send()
-        .parse::<DocInfo>();
+        .parse::<Doc>();
     doc
 }
 
-pub fn save_doc(sdk: &FlowyTestSDK, desc: &DocInfo, content: &str) {
+pub fn save_doc(sdk: &FlowyTestSDK, desc: &Doc, content: &str) {
     let request = UpdateDocRequest {
         id: desc.id.clone(),
         name: Some(desc.name.clone()),
         desc: Some(desc.desc.clone()),
-        text: Some(content.to_owned()),
+        data: Some(content.to_owned()),
     };
 
     let _ = DocTest::new(sdk.clone()).event(UpdateDoc).request(request).sync_send();

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

@@ -27,7 +27,7 @@ impl ServerError {
     static_error!(internal, ErrorCode::InternalError);
     static_error!(http, ErrorCode::HttpError);
     static_error!(payload_none, ErrorCode::PayloadUnexpectedNone);
-    static_error!(unauthorized, ErrorCode::Unauthorized);
+    static_error!(unauthorized, ErrorCode::UserUnauthorized);
     static_error!(password_not_match, ErrorCode::PasswordNotMatch);
     static_error!(params_invalid, ErrorCode::ParamsInvalid);
     static_error!(connect_timeout, ErrorCode::ConnectTimeout);
@@ -44,7 +44,7 @@ impl ServerError {
 
     pub fn is_not_found(&self) -> bool { self.code == ErrorCode::RecordNotFound }
 
-    pub fn is_unauthorized(&self) -> bool { self.code == ErrorCode::Unauthorized }
+    pub fn is_unauthorized(&self) -> bool { self.code == ErrorCode::UserUnauthorized }
 }
 
 pub fn invalid_params<T: Debug>(e: T) -> ServerError { ServerError::params_invalid().context(e) }
@@ -69,7 +69,7 @@ impl std::convert::From<&ServerError> for FlowyResponse {
 #[repr(u16)]
 pub enum ErrorCode {
     #[display(fmt = "Unauthorized")]
-    Unauthorized       = 1,
+    UserUnauthorized   = 1,
     #[display(fmt = "Payload too large")]
     PayloadOverflow    = 2,
     #[display(fmt = "Payload deserialize failed")]

+ 1 - 1
rust-lib/flowy-sdk/Cargo.toml

@@ -27,5 +27,5 @@ tokio = { version = "1", features = ["full"]}
 futures-util = "0.3.15"
 
 [features]
-http_server = ["flowy-user/http_server", "flowy-workspace/http_server"]
+http_server = ["flowy-user/http_server", "flowy-workspace/http_server", "flowy-document/http_server"]
 use_bunyan = ["flowy-log/use_bunyan"]

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

@@ -1,6 +1,6 @@
 use flowy_database::DBConnection;
 use flowy_document::{
-    errors::{DocError, DocErrorCode, ErrorBuilder},
+    errors::{DocError, ErrorBuilder, ErrorCode},
     module::{DocumentDatabase, DocumentUser},
 };
 use flowy_user::prelude::UserSession;
@@ -14,7 +14,7 @@ impl DocumentDatabase for EditorDatabaseImpl {
     fn db_connection(&self) -> Result<DBConnection, DocError> {
         self.user_session
             .db_conn()
-            .map_err(|e| ErrorBuilder::new(DocErrorCode::EditorDBConnFailed).error(e).build())
+            .map_err(|e| ErrorBuilder::new(ErrorCode::InternalError).error(e).build())
     }
 }
 
@@ -27,7 +27,7 @@ impl DocumentUser for EditorUserImpl {
         let dir = self
             .user_session
             .user_dir()
-            .map_err(|e| ErrorBuilder::new(DocErrorCode::EditorUserNotLoginYet).error(e).build())?;
+            .map_err(|e| ErrorBuilder::new(ErrorCode::EditorUserNotLoginYet).error(e).build())?;
 
         let doc_dir = format!("{}/doc", dir);
         if !Path::new(&doc_dir).exists() {
@@ -36,4 +36,16 @@ impl DocumentUser for EditorUserImpl {
         }
         Ok(doc_dir)
     }
+
+    fn user_id(&self) -> Result<String, DocError> {
+        self.user_session
+            .user_id()
+            .map_err(|e| ErrorBuilder::new(ErrorCode::InternalError).error(e).build())
+    }
+
+    fn token(&self) -> Result<String, DocError> {
+        self.user_session
+            .token()
+            .map_err(|e| ErrorBuilder::new(ErrorCode::InternalError).error(e).build())
+    }
 }

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

@@ -106,7 +106,7 @@ impl std::convert::From<flowy_net::errors::ServerError> for UserError {
 use flowy_net::errors::ErrorCode as ServerErrorCode;
 fn server_error_to_user_error(code: ServerErrorCode) -> ErrorCode {
     match code {
-        ServerErrorCode::Unauthorized => ErrorCode::UserUnauthorized,
+        ServerErrorCode::UserUnauthorized => ErrorCode::UserUnauthorized,
         ServerErrorCode::PasswordNotMatch => ErrorCode::PasswordNotMatch,
         ServerErrorCode::RecordNotFound => ErrorCode::UserNotExist,
         _ => ErrorCode::InternalError,

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

@@ -109,7 +109,7 @@ impl flowy_infra::errors::Build<ErrorCode> for WorkspaceError {
 use flowy_net::errors::ErrorCode as ServerErrorCode;
 fn server_error_to_workspace_error(code: ServerErrorCode) -> ErrorCode {
     match code {
-        ServerErrorCode::Unauthorized => ErrorCode::UserUnauthorized,
+        ServerErrorCode::UserUnauthorized => ErrorCode::UserUnauthorized,
         ServerErrorCode::RecordNotFound => ErrorCode::RecordNotFound,
         _ => ErrorCode::InternalError,
     }

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

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

+ 0 - 7
rust-lib/flowy-workspace/src/observable/observable.rs

@@ -1,27 +1,20 @@
 use flowy_derive::ProtoBuf_Enum;
-
 use flowy_observable::ObservableBuilder;
-
 const OBSERVABLE_CATEGORY: &'static str = "Workspace";
 
 #[derive(ProtoBuf_Enum, Debug)]
 pub(crate) enum WorkspaceObservable {
     Unknown              = 0,
-
     UserCreateWorkspace  = 10,
     UserDeleteWorkspace  = 11,
-
     WorkspaceUpdated     = 12,
     WorkspaceCreateApp   = 13,
     WorkspaceDeleteApp   = 14,
     WorkspaceListUpdated = 15,
-
     AppUpdated           = 21,
     AppCreateView        = 23,
     AppDeleteView        = 24,
-
     ViewUpdated          = 31,
-
     UserUnauthorized     = 100,
 }
 

+ 35 - 27
rust-lib/flowy-workspace/src/services/app_controller.rs

@@ -32,14 +32,17 @@ impl AppController {
     pub(crate) async fn create_app(&self, params: CreateAppParams) -> Result<App, WorkspaceError> {
         let app = self.create_app_on_server(params).await?;
         let app_table = AppTable::new(app.clone());
-        let conn = self.database.db_connection()?;
-        let _ = self.sql.create_app(app_table, &*conn)?;
-
-        // Opti: transaction
-        let apps = self.read_local_apps(&app.workspace_id, &*conn)?;
-        observable(&app.workspace_id, WorkspaceObservable::WorkspaceCreateApp)
-            .payload(apps)
-            .build();
+        let conn = &*self.database.db_connection()?;
+
+        conn.immediate_transaction::<_, WorkspaceError, _>(|| {
+            let _ = self.sql.create_app(app_table, &*conn)?;
+            let apps = self.read_local_apps(&app.workspace_id, &*conn)?;
+            observable(&app.workspace_id, WorkspaceObservable::WorkspaceCreateApp)
+                .payload(apps)
+                .build();
+            Ok(())
+        })?;
+
         Ok(app)
     }
 
@@ -47,20 +50,22 @@ impl AppController {
         let app_table = self
             .sql
             .read_app(&params.app_id, params.is_trash, &*self.database.db_connection()?)?;
-        let _ = self.read_app_on_server(params).await?;
+        let _ = self.read_app_on_server(params)?;
         Ok(app_table.into())
     }
 
     pub(crate) async fn delete_app(&self, app_id: &str) -> Result<(), WorkspaceError> {
-        let _ = self.delete_app_on_server(app_id);
+        let conn = &*self.database.db_connection()?;
+        conn.immediate_transaction::<_, WorkspaceError, _>(|| {
+            let app = self.sql.delete_app(app_id, &*conn)?;
+            let apps = self.read_local_apps(&app.workspace_id, &*conn)?;
+            observable(&app.workspace_id, WorkspaceObservable::WorkspaceDeleteApp)
+                .payload(apps)
+                .build();
+            Ok(())
+        })?;
 
-        let conn = self.database.db_connection()?;
-        let app = self.sql.delete_app(app_id, &*conn)?;
-        // Opti: transaction
-        let apps = self.read_local_apps(&app.workspace_id, &*conn)?;
-        observable(&app.workspace_id, WorkspaceObservable::WorkspaceDeleteApp)
-            .payload(apps)
-            .build();
+        let _ = self.delete_app_on_server(app_id);
         Ok(())
     }
 
@@ -71,14 +76,17 @@ impl AppController {
     }
 
     pub(crate) async fn update_app(&self, params: UpdateAppParams) -> Result<(), WorkspaceError> {
-        let _ = self.update_app_on_server(params.clone()).await?;
-
-        let changeset = AppTableChangeset::new(params);
+        let changeset = AppTableChangeset::new(params.clone());
         let app_id = changeset.id.clone();
-        let conn = self.database.db_connection()?;
-        let _ = self.sql.update_app(changeset, &*conn)?;
-        let app: App = self.sql.read_app(&app_id, false, &*conn)?.into();
-        observable(&app_id, WorkspaceObservable::AppUpdated).payload(app).build();
+        let conn = &*self.database.db_connection()?;
+        conn.immediate_transaction::<_, WorkspaceError, _>(|| {
+            let _ = self.sql.update_app(changeset, conn)?;
+            let app: App = self.sql.read_app(&app_id, false, conn)?.into();
+            observable(&app_id, WorkspaceObservable::AppUpdated).payload(app).build();
+            Ok(())
+        })?;
+
+        let _ = self.update_app_on_server(params)?;
         Ok(())
     }
 }
@@ -93,7 +101,7 @@ impl AppController {
     }
 
     #[tracing::instrument(level = "debug", skip(self), err)]
-    async fn update_app_on_server(&self, params: UpdateAppParams) -> Result<(), WorkspaceError> {
+    fn update_app_on_server(&self, params: UpdateAppParams) -> Result<(), WorkspaceError> {
         let token = self.user.token()?;
         let server = self.server.clone();
         spawn(async move {
@@ -109,7 +117,7 @@ impl AppController {
     }
 
     #[tracing::instrument(level = "debug", skip(self), err)]
-    async fn delete_app_on_server(&self, app_id: &str) -> Result<(), WorkspaceError> {
+    fn delete_app_on_server(&self, app_id: &str) -> Result<(), WorkspaceError> {
         let token = self.user.token()?;
         let server = self.server.clone();
         let params = DeleteAppParams {
@@ -128,7 +136,7 @@ impl AppController {
     }
 
     #[tracing::instrument(level = "debug", skip(self), err)]
-    async fn read_app_on_server(&self, params: QueryAppParams) -> Result<(), WorkspaceError> {
+    fn read_app_on_server(&self, params: QueryAppParams) -> Result<(), WorkspaceError> {
         let token = self.user.token()?;
         let server = self.server.clone();
         spawn(async move {

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

@@ -0,0 +1,30 @@
+use lazy_static::lazy_static;
+use std::sync::Arc;
+lazy_static! {
+    pub(crate) static ref MIDDLEWARE: Arc<WorkspaceMiddleware> = Arc::new(WorkspaceMiddleware {});
+}
+
+use crate::{
+    errors::{ErrorCode, WorkspaceError},
+    observable::*,
+};
+use flowy_net::{request::ResponseMiddleware, response::FlowyResponse};
+
+struct WorkspaceMiddleware {}
+impl ResponseMiddleware for WorkspaceMiddleware {
+    fn receive_response(&self, token: &Option<String>, response: &FlowyResponse) {
+        if let Some(error) = &response.error {
+            if error.is_unauthorized() {
+                log::error!("workspace user is unauthorized");
+
+                match token {
+                    None => {},
+                    Some(token) => {
+                        let error = WorkspaceError::new(ErrorCode::UserUnauthorized, "");
+                        observable(token, WorkspaceObservable::UserUnauthorized).error(error).build()
+                    },
+                }
+            }
+        }
+    }
+}

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

@@ -1,7 +1,9 @@
+mod middleware;
 mod server_api;
 mod server_api_mock;
+
 pub use server_api::*;
-// TODO: exclude mock files in production
+// TODO: ignore mock files in production
 pub use server_api_mock::*;
 
 use crate::{

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

@@ -20,7 +20,6 @@ use flowy_net::{
     request::{HttpRequestBuilder, ResponseMiddleware},
     response::FlowyResponse,
 };
-use lazy_static::lazy_static;
 use std::sync::Arc;
 
 pub struct WorkspaceServer {}
@@ -87,33 +86,7 @@ impl WorkspaceServerAPI for WorkspaceServer {
     }
 }
 
-lazy_static! {
-    static ref MIDDLEWARE: Arc<WorkspaceMiddleware> = Arc::new(WorkspaceMiddleware {});
-}
-
-use crate::{errors::ErrorCode, observable::*};
-
-struct WorkspaceMiddleware {}
-impl ResponseMiddleware for WorkspaceMiddleware {
-    fn receive_response(&self, token: &Option<String>, response: &FlowyResponse) {
-        if let Some(error) = &response.error {
-            if error.is_unauthorized() {
-                log::error!("workspace user is unauthorized");
-
-                match token {
-                    None => {},
-                    Some(token) => {
-                        let error = WorkspaceError::new(ErrorCode::UserUnauthorized, "");
-                        observable(token, WorkspaceObservable::UserUnauthorized).error(error).build()
-                    },
-                }
-            }
-        }
-    }
-}
-
-pub(crate) fn request_builder() -> HttpRequestBuilder { HttpRequestBuilder::new().middleware(MIDDLEWARE.clone()) }
-
+pub(crate) fn request_builder() -> HttpRequestBuilder { HttpRequestBuilder::new().middleware(super::middleware::MIDDLEWARE.clone()) }
 pub async fn create_workspace_request(token: &str, params: CreateWorkspaceParams, url: &str) -> Result<Workspace, WorkspaceError> {
     let workspace = request_builder()
         .post(&url.to_owned())

+ 6 - 6
rust-lib/flowy-workspace/src/services/view_controller.rs

@@ -38,7 +38,7 @@ impl ViewController {
         let conn = &*self.database.db_connection()?;
         let view_table = ViewTable::new(view.clone());
 
-        (conn).immediate_transaction::<_, WorkspaceError, _>(|| {
+        conn.immediate_transaction::<_, WorkspaceError, _>(|| {
             let _ = self.sql.create_view(view_table, conn)?;
             let repeated_view = self.read_local_views_belong_to(&view.belong_to_id, conn)?;
             observable(&view.belong_to_id, WorkspaceObservable::AppCreateView)
@@ -61,7 +61,7 @@ impl ViewController {
     pub(crate) async fn delete_view(&self, view_id: &str) -> Result<(), WorkspaceError> {
         let conn = &*self.database.db_connection()?;
 
-        (conn).immediate_transaction::<_, WorkspaceError, _>(|| {
+        conn.immediate_transaction::<_, WorkspaceError, _>(|| {
             let view_table = self.sql.delete_view(view_id, conn)?;
             let repeated_view = self.read_local_views_belong_to(&view_table.belong_to_id, conn)?;
             observable(&view_table.belong_to_id, WorkspaceObservable::AppDeleteView)
@@ -89,7 +89,7 @@ impl ViewController {
         let changeset = ViewTableChangeset::new(params.clone());
         let view_id = changeset.id.clone();
 
-        (conn).immediate_transaction::<_, WorkspaceError, _>(|| {
+        conn.immediate_transaction::<_, WorkspaceError, _>(|| {
             let _ = self.sql.update_view(changeset, conn)?;
             let view: View = self.sql.read_view(&view_id, None, conn)?.into();
             observable(&view_id, WorkspaceObservable::ViewUpdated).payload(view).build();
@@ -110,7 +110,7 @@ impl ViewController {
     }
 
     #[tracing::instrument(skip(self), err)]
-    async fn update_view_on_server(&self, params: UpdateViewParams) -> Result<(), WorkspaceError> {
+    fn update_view_on_server(&self, params: UpdateViewParams) -> Result<(), WorkspaceError> {
         let token = self.user.token()?;
         let server = self.server.clone();
         spawn(async move {
@@ -126,7 +126,7 @@ impl ViewController {
     }
 
     #[tracing::instrument(skip(self), err)]
-    async fn delete_view_on_server(&self, view_id: &str) -> Result<(), WorkspaceError> {
+    fn delete_view_on_server(&self, view_id: &str) -> Result<(), WorkspaceError> {
         let token = self.user.token()?;
         let server = self.server.clone();
         let params = DeleteViewParams {
@@ -145,7 +145,7 @@ impl ViewController {
     }
 
     #[tracing::instrument(skip(self), err)]
-    async fn read_view_on_server(&self, params: QueryViewParams) -> Result<(), WorkspaceError> {
+    fn read_view_on_server(&self, params: QueryViewParams) -> Result<(), WorkspaceError> {
         let token = self.user.token()?;
         let server = self.server.clone();
         spawn(async move {

+ 20 - 23
rust-lib/flowy-workspace/src/services/workspace_controller.rs

@@ -5,7 +5,7 @@ use crate::{
     },
     errors::*,
     module::{WorkspaceDatabase, WorkspaceUser},
-    observable::{observable, WorkspaceObservable},
+    observable::*,
     services::{helper::spawn, server::Server, AppController},
     sql_tables::{
         app::{AppTable, AppTableSql},
@@ -65,7 +65,7 @@ impl WorkspaceController {
         // immediately. EXCLUSIVE and IMMEDIATE are the same in WAL mode, but in
         // other journaling modes, EXCLUSIVE prevents other database connections from
         // reading the database while the transaction is underway.
-        (conn).immediate_transaction::<_, WorkspaceError, _>(|| {
+        conn.immediate_transaction::<_, WorkspaceError, _>(|| {
             self.workspace_sql.create_workspace(workspace_table, conn)?;
             let repeated_workspace = self.read_local_workspaces(None, &user_id, conn)?;
             observable(&token, WorkspaceObservable::UserCreateWorkspace)
@@ -79,12 +79,10 @@ impl WorkspaceController {
     }
 
     pub(crate) async fn update_workspace(&self, params: UpdateWorkspaceParams) -> Result<(), WorkspaceError> {
-        let _ = self.update_workspace_on_server(params.clone()).await?;
-
-        let changeset = WorkspaceTableChangeset::new(params);
+        let changeset = WorkspaceTableChangeset::new(params.clone());
         let workspace_id = changeset.id.clone();
         let conn = &*self.database.db_connection()?;
-        (conn).immediate_transaction::<_, WorkspaceError, _>(|| {
+        conn.immediate_transaction::<_, WorkspaceError, _>(|| {
             let _ = self.workspace_sql.update_workspace(changeset, conn)?;
             let user_id = self.user.user_id()?;
             let workspace = self.read_local_workspace(workspace_id.clone(), &user_id, conn)?;
@@ -95,15 +93,16 @@ impl WorkspaceController {
             Ok(())
         })?;
 
+        let _ = self.update_workspace_on_server(params)?;
+
         Ok(())
     }
 
     pub(crate) async fn delete_workspace(&self, workspace_id: &str) -> Result<(), WorkspaceError> {
         let user_id = self.user.user_id()?;
         let token = self.user.token()?;
-        let _ = self.delete_workspace_on_server(workspace_id).await?;
         let conn = &*self.database.db_connection()?;
-        (conn).immediate_transaction::<_, WorkspaceError, _>(|| {
+        conn.immediate_transaction::<_, WorkspaceError, _>(|| {
             let _ = self.workspace_sql.delete_workspace(workspace_id, conn)?;
             let repeated_workspace = self.read_local_workspaces(None, &user_id, conn)?;
             observable(&token, WorkspaceObservable::UserDeleteWorkspace)
@@ -113,6 +112,7 @@ impl WorkspaceController {
             Ok(())
         })?;
 
+        let _ = self.delete_workspace_on_server(workspace_id)?;
         Ok(())
     }
 
@@ -132,10 +132,8 @@ impl WorkspaceController {
 
     pub(crate) async fn read_workspaces(&self, params: QueryWorkspaceParams) -> Result<RepeatedWorkspace, WorkspaceError> {
         let user_id = self.user.user_id()?;
-        let _ = self.read_workspaces_on_server(user_id.clone(), params.clone()).await;
-
-        let conn = self.database.db_connection()?;
-        let workspaces = self.read_local_workspaces(params.workspace_id.clone(), &user_id, &*conn)?;
+        let workspaces = self.read_local_workspaces(params.workspace_id.clone(), &user_id, &*self.database.db_connection()?)?;
+        let _ = self.read_workspaces_on_server(user_id.clone(), params.clone());
         Ok(workspaces)
     }
 
@@ -145,10 +143,9 @@ impl WorkspaceController {
         let params = QueryWorkspaceParams {
             workspace_id: Some(workspace_id.clone()),
         };
-        let _ = self.read_workspaces_on_server(user_id.clone(), params).await?;
+        let workspace = self.read_local_workspace(workspace_id, &user_id, &*self.database.db_connection()?)?;
 
-        let conn = self.database.db_connection()?;
-        let workspace = self.read_local_workspace(workspace_id, &user_id, &*conn)?;
+        let _ = self.read_workspaces_on_server(user_id.clone(), params)?;
         Ok(workspace)
     }
 
@@ -212,15 +209,15 @@ impl WorkspaceController {
         Ok((token, server))
     }
 
-    #[tracing::instrument(skip(self), err)]
+    #[tracing::instrument(level = "debug", skip(self), err)]
     async fn create_workspace_on_server(&self, params: CreateWorkspaceParams) -> Result<Workspace, WorkspaceError> {
         let token = self.user.token()?;
         let workspace = self.server.create_workspace(&token, params).await?;
         Ok(workspace)
     }
 
-    #[tracing::instrument(skip(self), err)]
-    async fn update_workspace_on_server(&self, params: UpdateWorkspaceParams) -> Result<(), WorkspaceError> {
+    #[tracing::instrument(level = "debug", skip(self), err)]
+    fn update_workspace_on_server(&self, params: UpdateWorkspaceParams) -> Result<(), WorkspaceError> {
         let (token, server) = self.token_with_server()?;
         spawn(async move {
             match server.update_workspace(&token, params).await {
@@ -234,8 +231,8 @@ impl WorkspaceController {
         Ok(())
     }
 
-    #[tracing::instrument(skip(self), err)]
-    async fn delete_workspace_on_server(&self, workspace_id: &str) -> Result<(), WorkspaceError> {
+    #[tracing::instrument(level = "debug", skip(self), err)]
+    fn delete_workspace_on_server(&self, workspace_id: &str) -> Result<(), WorkspaceError> {
         let params = DeleteWorkspaceParams {
             workspace_id: workspace_id.to_string(),
         };
@@ -252,15 +249,15 @@ impl WorkspaceController {
         Ok(())
     }
 
-    #[tracing::instrument(skip(self), err)]
-    async fn read_workspaces_on_server(&self, user_id: String, params: QueryWorkspaceParams) -> Result<(), WorkspaceError> {
+    #[tracing::instrument(level = "debug", skip(self), err)]
+    fn read_workspaces_on_server(&self, user_id: String, params: QueryWorkspaceParams) -> Result<(), WorkspaceError> {
         let (token, server) = self.token_with_server()?;
         let workspace_sql = self.workspace_sql.clone();
         let app_sql = self.app_sql.clone();
         let view_sql = self.view_sql.clone();
         let conn = self.database.db_connection()?;
         spawn(async move {
-            // Opti: retry?
+            // Opti: handle the error and retry?
             let workspaces = server.read_workspace(&token, params).await?;
             let _ = (&*conn).immediate_transaction::<_, WorkspaceError, _>(|| {
                 log::debug!("Save {} workspace", workspaces.len());