瀏覽代碼

errors with static constructor

appflowy 3 年之前
父節點
當前提交
e2e47e8df0
共有 63 個文件被更改,包括 510 次插入666 次删除
  1. 1 1
      app_flowy/packages/flowy_sdk/lib/protobuf/flowy-user/errors.pb.dart
  2. 15 27
      app_flowy/packages/flowy_sdk/lib/protobuf/flowy-user/errors.pbenum.dart
  3. 15 21
      app_flowy/packages/flowy_sdk/lib/protobuf/flowy-user/errors.pbjson.dart
  4. 1 1
      app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/errors.pb.dart
  5. 5 11
      app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/errors.pbenum.dart
  6. 6 9
      app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/errors.pbjson.dart
  7. 3 3
      backend/src/service/workspace_service/user_default/user_default.rs
  8. 1 1
      backend/tests/api/helper.rs
  9. 0 2
      rust-lib/dart-ffi/src/protobuf/mod.rs
  10. 5 5
      rust-lib/dart-ffi/src/protobuf/model/mod.rs
  11. 1 7
      rust-lib/flowy-database/src/schema.rs
  12. 2 4
      rust-lib/flowy-derive/src/derive_cache/derive_cache.rs
  13. 1 1
      rust-lib/flowy-dispatch/tests/api/helper.rs
  14. 0 1
      rust-lib/flowy-document/src/entities/doc/doc.rs
  15. 34 9
      rust-lib/flowy-document/src/errors.rs
  16. 3 3
      rust-lib/flowy-document/src/module.rs
  17. 0 2
      rust-lib/flowy-document/src/protobuf/mod.rs
  18. 9 9
      rust-lib/flowy-document/src/protobuf/model/mod.rs
  19. 4 12
      rust-lib/flowy-document/src/services/doc_cache.rs
  20. 6 12
      rust-lib/flowy-document/src/services/doc_controller.rs
  21. 1 1
      rust-lib/flowy-infra/src/errors/builder.rs
  22. 0 2
      rust-lib/flowy-infra/src/protobuf/mod.rs
  23. 3 3
      rust-lib/flowy-infra/src/protobuf/model/mod.rs
  24. 2 2
      rust-lib/flowy-net/src/response/response_serde.rs
  25. 0 2
      rust-lib/flowy-observable/src/protobuf/mod.rs
  26. 3 3
      rust-lib/flowy-observable/src/protobuf/model/mod.rs
  27. 1 1
      rust-lib/flowy-ot/src/core/attributes/attribute.rs
  28. 2 2
      rust-lib/flowy-ot/src/core/attributes/attributes_serde.rs
  29. 4 18
      rust-lib/flowy-sdk/src/deps_resolve/editor_deps_impl.rs
  30. 4 14
      rust-lib/flowy-sdk/src/deps_resolve/workspace_deps_impl.rs
  31. 4 4
      rust-lib/flowy-test/src/helper.rs
  32. 5 5
      rust-lib/flowy-user/src/entities/auth.rs
  33. 1 1
      rust-lib/flowy-user/src/entities/parser/user_name.rs
  34. 5 7
      rust-lib/flowy-user/src/entities/user_profile.rs
  35. 60 44
      rust-lib/flowy-user/src/errors.rs
  36. 0 2
      rust-lib/flowy-user/src/protobuf/mod.rs
  37. 80 113
      rust-lib/flowy-user/src/protobuf/model/errors.rs
  38. 13 13
      rust-lib/flowy-user/src/protobuf/model/mod.rs
  39. 14 20
      rust-lib/flowy-user/src/protobuf/proto/errors.proto
  40. 2 2
      rust-lib/flowy-user/src/services/server/server_api_mock.rs
  41. 7 15
      rust-lib/flowy-user/src/services/user/database.rs
  42. 2 2
      rust-lib/flowy-user/src/services/user/user_session.rs
  43. 3 4
      rust-lib/flowy-workspace/src/entities/app/app_create.rs
  44. 2 7
      rust-lib/flowy-workspace/src/entities/app/app_delete.rs
  45. 1 3
      rust-lib/flowy-workspace/src/entities/app/app_query.rs
  46. 4 10
      rust-lib/flowy-workspace/src/entities/app/app_update.rs
  47. 0 2
      rust-lib/flowy-workspace/src/entities/view/parser/delta_data.rs
  48. 4 8
      rust-lib/flowy-workspace/src/entities/view/view_create.rs
  49. 2 7
      rust-lib/flowy-workspace/src/entities/view/view_delete.rs
  50. 3 10
      rust-lib/flowy-workspace/src/entities/view/view_query.rs
  51. 9 27
      rust-lib/flowy-workspace/src/entities/view/view_update.rs
  52. 2 2
      rust-lib/flowy-workspace/src/entities/workspace/workspace_create.rs
  53. 2 5
      rust-lib/flowy-workspace/src/entities/workspace/workspace_delete.rs
  54. 1 1
      rust-lib/flowy-workspace/src/entities/workspace/workspace_query.rs
  55. 2 2
      rust-lib/flowy-workspace/src/entities/workspace/workspace_update.rs
  56. 42 28
      rust-lib/flowy-workspace/src/errors.rs
  57. 2 4
      rust-lib/flowy-workspace/src/module.rs
  58. 0 2
      rust-lib/flowy-workspace/src/protobuf/mod.rs
  59. 57 74
      rust-lib/flowy-workspace/src/protobuf/model/errors.rs
  60. 33 33
      rust-lib/flowy-workspace/src/protobuf/model/mod.rs
  61. 5 8
      rust-lib/flowy-workspace/src/protobuf/proto/errors.proto
  62. 4 6
      rust-lib/flowy-workspace/src/services/workspace_controller.rs
  63. 7 6
      rust-lib/flowy-workspace/tests/workspace/view_test.rs

+ 1 - 1
app_flowy/packages/flowy_sdk/lib/protobuf/flowy-user/errors.pb.dart

@@ -15,7 +15,7 @@ export 'errors.pbenum.dart';
 
 class UserError extends $pb.GeneratedMessage {
   static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'UserError', createEmptyInstance: create)
-    ..e<ErrorCode>(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'code', $pb.PbFieldType.OE, defaultOrMaker: ErrorCode.Unknown, valueOf: ErrorCode.valueOf, enumValues: ErrorCode.values)
+    ..e<ErrorCode>(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'code', $pb.PbFieldType.OE, defaultOrMaker: ErrorCode.EmailIsEmpty, valueOf: ErrorCode.valueOf, enumValues: ErrorCode.values)
     ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'msg')
     ..hasRequiredFields = false
   ;

+ 15 - 27
app_flowy/packages/flowy_sdk/lib/protobuf/flowy-user/errors.pbenum.dart

@@ -10,34 +10,23 @@ import 'dart:core' as $core;
 import 'package:protobuf/protobuf.dart' as $pb;
 
 class ErrorCode extends $pb.ProtobufEnum {
-  static const ErrorCode Unknown = ErrorCode._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Unknown');
-  static const ErrorCode UserDatabaseInitFailed = ErrorCode._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserDatabaseInitFailed');
-  static const ErrorCode AcquireWriteLockedFailed = ErrorCode._(2, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'AcquireWriteLockedFailed');
-  static const ErrorCode AcquireReadLockedFailed = ErrorCode._(3, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'AcquireReadLockedFailed');
-  static const ErrorCode UserDatabaseDidNotMatch = ErrorCode._(4, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserDatabaseDidNotMatch');
-  static const ErrorCode EmailIsEmpty = ErrorCode._(20, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'EmailIsEmpty');
-  static const ErrorCode EmailFormatInvalid = ErrorCode._(21, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'EmailFormatInvalid');
-  static const ErrorCode EmailAlreadyExists = ErrorCode._(22, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'EmailAlreadyExists');
-  static const ErrorCode PasswordIsEmpty = ErrorCode._(30, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'PasswordIsEmpty');
-  static const ErrorCode PasswordTooLong = ErrorCode._(31, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'PasswordTooLong');
-  static const ErrorCode PasswordContainsForbidCharacters = ErrorCode._(32, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'PasswordContainsForbidCharacters');
-  static const ErrorCode PasswordFormatInvalid = ErrorCode._(33, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'PasswordFormatInvalid');
-  static const ErrorCode PasswordNotMatch = ErrorCode._(34, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'PasswordNotMatch');
-  static const ErrorCode UserNameTooLong = ErrorCode._(40, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserNameTooLong');
-  static const ErrorCode ContainForbiddenCharacters = ErrorCode._(41, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ContainForbiddenCharacters');
-  static const ErrorCode UserNameIsEmpty = ErrorCode._(42, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserNameIsEmpty');
-  static const ErrorCode UserWorkspaceInvalid = ErrorCode._(50, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserWorkspaceInvalid');
-  static const ErrorCode UserIdInvalid = ErrorCode._(51, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserIdInvalid');
-  static const ErrorCode UserUnauthorized = ErrorCode._(54, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserUnauthorized');
-  static const ErrorCode UserNotExist = ErrorCode._(55, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserNotExist');
+  static const ErrorCode EmailIsEmpty = ErrorCode._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'EmailIsEmpty');
+  static const ErrorCode EmailFormatInvalid = ErrorCode._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'EmailFormatInvalid');
+  static const ErrorCode EmailAlreadyExists = ErrorCode._(2, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'EmailAlreadyExists');
+  static const ErrorCode PasswordIsEmpty = ErrorCode._(10, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'PasswordIsEmpty');
+  static const ErrorCode PasswordTooLong = ErrorCode._(11, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'PasswordTooLong');
+  static const ErrorCode PasswordContainsForbidCharacters = ErrorCode._(12, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'PasswordContainsForbidCharacters');
+  static const ErrorCode PasswordFormatInvalid = ErrorCode._(13, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'PasswordFormatInvalid');
+  static const ErrorCode PasswordNotMatch = ErrorCode._(14, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'PasswordNotMatch');
+  static const ErrorCode UserNameTooLong = ErrorCode._(20, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserNameTooLong');
+  static const ErrorCode UserNameContainForbiddenCharacters = ErrorCode._(21, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserNameContainForbiddenCharacters');
+  static const ErrorCode UserNameIsEmpty = ErrorCode._(22, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserNameIsEmpty');
+  static const ErrorCode UserIdInvalid = ErrorCode._(23, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserIdInvalid');
+  static const ErrorCode UserUnauthorized = ErrorCode._(24, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserUnauthorized');
+  static const ErrorCode UserNotExist = ErrorCode._(25, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserNotExist');
   static const ErrorCode InternalError = ErrorCode._(100, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'InternalError');
 
   static const $core.List<ErrorCode> values = <ErrorCode> [
-    Unknown,
-    UserDatabaseInitFailed,
-    AcquireWriteLockedFailed,
-    AcquireReadLockedFailed,
-    UserDatabaseDidNotMatch,
     EmailIsEmpty,
     EmailFormatInvalid,
     EmailAlreadyExists,
@@ -47,9 +36,8 @@ class ErrorCode extends $pb.ProtobufEnum {
     PasswordFormatInvalid,
     PasswordNotMatch,
     UserNameTooLong,
-    ContainForbiddenCharacters,
+    UserNameContainForbiddenCharacters,
     UserNameIsEmpty,
-    UserWorkspaceInvalid,
     UserIdInvalid,
     UserUnauthorized,
     UserNotExist,

+ 15 - 21
app_flowy/packages/flowy_sdk/lib/protobuf/flowy-user/errors.pbjson.dart

@@ -12,32 +12,26 @@ import 'dart:typed_data' as $typed_data;
 const ErrorCode$json = const {
   '1': 'ErrorCode',
   '2': const [
-    const {'1': 'Unknown', '2': 0},
-    const {'1': 'UserDatabaseInitFailed', '2': 1},
-    const {'1': 'AcquireWriteLockedFailed', '2': 2},
-    const {'1': 'AcquireReadLockedFailed', '2': 3},
-    const {'1': 'UserDatabaseDidNotMatch', '2': 4},
-    const {'1': 'EmailIsEmpty', '2': 20},
-    const {'1': 'EmailFormatInvalid', '2': 21},
-    const {'1': 'EmailAlreadyExists', '2': 22},
-    const {'1': 'PasswordIsEmpty', '2': 30},
-    const {'1': 'PasswordTooLong', '2': 31},
-    const {'1': 'PasswordContainsForbidCharacters', '2': 32},
-    const {'1': 'PasswordFormatInvalid', '2': 33},
-    const {'1': 'PasswordNotMatch', '2': 34},
-    const {'1': 'UserNameTooLong', '2': 40},
-    const {'1': 'ContainForbiddenCharacters', '2': 41},
-    const {'1': 'UserNameIsEmpty', '2': 42},
-    const {'1': 'UserWorkspaceInvalid', '2': 50},
-    const {'1': 'UserIdInvalid', '2': 51},
-    const {'1': 'UserUnauthorized', '2': 54},
-    const {'1': 'UserNotExist', '2': 55},
+    const {'1': 'EmailIsEmpty', '2': 0},
+    const {'1': 'EmailFormatInvalid', '2': 1},
+    const {'1': 'EmailAlreadyExists', '2': 2},
+    const {'1': 'PasswordIsEmpty', '2': 10},
+    const {'1': 'PasswordTooLong', '2': 11},
+    const {'1': 'PasswordContainsForbidCharacters', '2': 12},
+    const {'1': 'PasswordFormatInvalid', '2': 13},
+    const {'1': 'PasswordNotMatch', '2': 14},
+    const {'1': 'UserNameTooLong', '2': 20},
+    const {'1': 'UserNameContainForbiddenCharacters', '2': 21},
+    const {'1': 'UserNameIsEmpty', '2': 22},
+    const {'1': 'UserIdInvalid', '2': 23},
+    const {'1': 'UserUnauthorized', '2': 24},
+    const {'1': 'UserNotExist', '2': 25},
     const {'1': 'InternalError', '2': 100},
   ],
 };
 
 /// Descriptor for `ErrorCode`. Decode as a `google.protobuf.EnumDescriptorProto`.
-final $typed_data.Uint8List errorCodeDescriptor = $convert.base64Decode('CglFcnJvckNvZGUSCwoHVW5rbm93bhAAEhoKFlVzZXJEYXRhYmFzZUluaXRGYWlsZWQQARIcChhBY3F1aXJlV3JpdGVMb2NrZWRGYWlsZWQQAhIbChdBY3F1aXJlUmVhZExvY2tlZEZhaWxlZBADEhsKF1VzZXJEYXRhYmFzZURpZE5vdE1hdGNoEAQSEAoMRW1haWxJc0VtcHR5EBQSFgoSRW1haWxGb3JtYXRJbnZhbGlkEBUSFgoSRW1haWxBbHJlYWR5RXhpc3RzEBYSEwoPUGFzc3dvcmRJc0VtcHR5EB4SEwoPUGFzc3dvcmRUb29Mb25nEB8SJAogUGFzc3dvcmRDb250YWluc0ZvcmJpZENoYXJhY3RlcnMQIBIZChVQYXNzd29yZEZvcm1hdEludmFsaWQQIRIUChBQYXNzd29yZE5vdE1hdGNoECISEwoPVXNlck5hbWVUb29Mb25nECgSHgoaQ29udGFpbkZvcmJpZGRlbkNoYXJhY3RlcnMQKRITCg9Vc2VyTmFtZUlzRW1wdHkQKhIYChRVc2VyV29ya3NwYWNlSW52YWxpZBAyEhEKDVVzZXJJZEludmFsaWQQMxIUChBVc2VyVW5hdXRob3JpemVkEDYSEAoMVXNlck5vdEV4aXN0EDcSEQoNSW50ZXJuYWxFcnJvchBk');
+final $typed_data.Uint8List errorCodeDescriptor = $convert.base64Decode('CglFcnJvckNvZGUSEAoMRW1haWxJc0VtcHR5EAASFgoSRW1haWxGb3JtYXRJbnZhbGlkEAESFgoSRW1haWxBbHJlYWR5RXhpc3RzEAISEwoPUGFzc3dvcmRJc0VtcHR5EAoSEwoPUGFzc3dvcmRUb29Mb25nEAsSJAogUGFzc3dvcmRDb250YWluc0ZvcmJpZENoYXJhY3RlcnMQDBIZChVQYXNzd29yZEZvcm1hdEludmFsaWQQDRIUChBQYXNzd29yZE5vdE1hdGNoEA4SEwoPVXNlck5hbWVUb29Mb25nEBQSJgoiVXNlck5hbWVDb250YWluRm9yYmlkZGVuQ2hhcmFjdGVycxAVEhMKD1VzZXJOYW1lSXNFbXB0eRAWEhEKDVVzZXJJZEludmFsaWQQFxIUChBVc2VyVW5hdXRob3JpemVkEBgSEAoMVXNlck5vdEV4aXN0EBkSEQoNSW50ZXJuYWxFcnJvchBk');
 @$core.Deprecated('Use userErrorDescriptor instead')
 const UserError$json = const {
   '1': 'UserError',

+ 1 - 1
app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/errors.pb.dart

@@ -15,7 +15,7 @@ export 'errors.pbenum.dart';
 
 class WorkspaceError extends $pb.GeneratedMessage {
   static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'WorkspaceError', createEmptyInstance: create)
-    ..e<ErrorCode>(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'code', $pb.PbFieldType.OE, defaultOrMaker: ErrorCode.Unknown, valueOf: ErrorCode.valueOf, enumValues: ErrorCode.values)
+    ..e<ErrorCode>(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'code', $pb.PbFieldType.OE, defaultOrMaker: ErrorCode.WorkspaceNameInvalid, valueOf: ErrorCode.valueOf, enumValues: ErrorCode.values)
     ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'msg')
     ..hasRequiredFields = false
   ;

+ 5 - 11
app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/errors.pbenum.dart

@@ -10,12 +10,10 @@ import 'dart:core' as $core;
 import 'package:protobuf/protobuf.dart' as $pb;
 
 class ErrorCode extends $pb.ProtobufEnum {
-  static const ErrorCode Unknown = ErrorCode._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Unknown');
-  static const ErrorCode WorkspaceNameInvalid = ErrorCode._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'WorkspaceNameInvalid');
-  static const ErrorCode WorkspaceIdInvalid = ErrorCode._(2, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'WorkspaceIdInvalid');
-  static const ErrorCode AppColorStyleInvalid = ErrorCode._(3, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'AppColorStyleInvalid');
-  static const ErrorCode WorkspaceDescInvalid = ErrorCode._(4, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'WorkspaceDescInvalid');
-  static const ErrorCode CurrentWorkspaceNotFound = ErrorCode._(5, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CurrentWorkspaceNotFound');
+  static const ErrorCode WorkspaceNameInvalid = ErrorCode._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'WorkspaceNameInvalid');
+  static const ErrorCode WorkspaceIdInvalid = ErrorCode._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'WorkspaceIdInvalid');
+  static const ErrorCode AppColorStyleInvalid = ErrorCode._(2, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'AppColorStyleInvalid');
+  static const ErrorCode WorkspaceDescInvalid = ErrorCode._(3, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'WorkspaceDescInvalid');
   static const ErrorCode AppIdInvalid = ErrorCode._(10, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'AppIdInvalid');
   static const ErrorCode AppNameInvalid = ErrorCode._(11, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'AppNameInvalid');
   static const ErrorCode ViewNameInvalid = ErrorCode._(20, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ViewNameInvalid');
@@ -23,18 +21,15 @@ class ErrorCode extends $pb.ProtobufEnum {
   static const ErrorCode ViewIdInvalid = ErrorCode._(22, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ViewIdInvalid');
   static const ErrorCode ViewDescInvalid = ErrorCode._(23, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ViewDescInvalid');
   static const ErrorCode ViewDataInvalid = ErrorCode._(24, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ViewDataInvalid');
-  static const ErrorCode UserIdIsEmpty = ErrorCode._(100, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserIdIsEmpty');
-  static const ErrorCode UserUnauthorized = ErrorCode._(101, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserUnauthorized');
+  static const ErrorCode UserUnauthorized = ErrorCode._(100, 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 ErrorCode RecordNotFound = ErrorCode._(1001, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'RecordNotFound');
 
   static const $core.List<ErrorCode> values = <ErrorCode> [
-    Unknown,
     WorkspaceNameInvalid,
     WorkspaceIdInvalid,
     AppColorStyleInvalid,
     WorkspaceDescInvalid,
-    CurrentWorkspaceNotFound,
     AppIdInvalid,
     AppNameInvalid,
     ViewNameInvalid,
@@ -42,7 +37,6 @@ class ErrorCode extends $pb.ProtobufEnum {
     ViewIdInvalid,
     ViewDescInvalid,
     ViewDataInvalid,
-    UserIdIsEmpty,
     UserUnauthorized,
     InternalError,
     RecordNotFound,

+ 6 - 9
app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/errors.pbjson.dart

@@ -12,12 +12,10 @@ import 'dart:typed_data' as $typed_data;
 const ErrorCode$json = const {
   '1': 'ErrorCode',
   '2': const [
-    const {'1': 'Unknown', '2': 0},
-    const {'1': 'WorkspaceNameInvalid', '2': 1},
-    const {'1': 'WorkspaceIdInvalid', '2': 2},
-    const {'1': 'AppColorStyleInvalid', '2': 3},
-    const {'1': 'WorkspaceDescInvalid', '2': 4},
-    const {'1': 'CurrentWorkspaceNotFound', '2': 5},
+    const {'1': 'WorkspaceNameInvalid', '2': 0},
+    const {'1': 'WorkspaceIdInvalid', '2': 1},
+    const {'1': 'AppColorStyleInvalid', '2': 2},
+    const {'1': 'WorkspaceDescInvalid', '2': 3},
     const {'1': 'AppIdInvalid', '2': 10},
     const {'1': 'AppNameInvalid', '2': 11},
     const {'1': 'ViewNameInvalid', '2': 20},
@@ -25,15 +23,14 @@ const ErrorCode$json = const {
     const {'1': 'ViewIdInvalid', '2': 22},
     const {'1': 'ViewDescInvalid', '2': 23},
     const {'1': 'ViewDataInvalid', '2': 24},
-    const {'1': 'UserIdIsEmpty', '2': 100},
-    const {'1': 'UserUnauthorized', '2': 101},
+    const {'1': 'UserUnauthorized', '2': 100},
     const {'1': 'InternalError', '2': 1000},
     const {'1': 'RecordNotFound', '2': 1001},
   ],
 };
 
 /// Descriptor for `ErrorCode`. Decode as a `google.protobuf.EnumDescriptorProto`.
-final $typed_data.Uint8List errorCodeDescriptor = $convert.base64Decode('CglFcnJvckNvZGUSCwoHVW5rbm93bhAAEhgKFFdvcmtzcGFjZU5hbWVJbnZhbGlkEAESFgoSV29ya3NwYWNlSWRJbnZhbGlkEAISGAoUQXBwQ29sb3JTdHlsZUludmFsaWQQAxIYChRXb3Jrc3BhY2VEZXNjSW52YWxpZBAEEhwKGEN1cnJlbnRXb3Jrc3BhY2VOb3RGb3VuZBAFEhAKDEFwcElkSW52YWxpZBAKEhIKDkFwcE5hbWVJbnZhbGlkEAsSEwoPVmlld05hbWVJbnZhbGlkEBQSGAoUVmlld1RodW1ibmFpbEludmFsaWQQFRIRCg1WaWV3SWRJbnZhbGlkEBYSEwoPVmlld0Rlc2NJbnZhbGlkEBcSEwoPVmlld0RhdGFJbnZhbGlkEBgSEQoNVXNlcklkSXNFbXB0eRBkEhQKEFVzZXJVbmF1dGhvcml6ZWQQZRISCg1JbnRlcm5hbEVycm9yEOgHEhMKDlJlY29yZE5vdEZvdW5kEOkH');
+final $typed_data.Uint8List errorCodeDescriptor = $convert.base64Decode('CglFcnJvckNvZGUSGAoUV29ya3NwYWNlTmFtZUludmFsaWQQABIWChJXb3Jrc3BhY2VJZEludmFsaWQQARIYChRBcHBDb2xvclN0eWxlSW52YWxpZBACEhgKFFdvcmtzcGFjZURlc2NJbnZhbGlkEAMSEAoMQXBwSWRJbnZhbGlkEAoSEgoOQXBwTmFtZUludmFsaWQQCxITCg9WaWV3TmFtZUludmFsaWQQFBIYChRWaWV3VGh1bWJuYWlsSW52YWxpZBAVEhEKDVZpZXdJZEludmFsaWQQFhITCg9WaWV3RGVzY0ludmFsaWQQFxITCg9WaWV3RGF0YUludmFsaWQQGBIUChBVc2VyVW5hdXRob3JpemVkEGQSEgoNSW50ZXJuYWxFcnJvchDoBxITCg5SZWNvcmROb3RGb3VuZBDpBw==');
 @$core.Deprecated('Use workspaceErrorDescriptor instead')
 const WorkspaceError$json = const {
   '1': 'WorkspaceError',

+ 3 - 3
backend/src/service/workspace_service/user_default/user_default.rs

@@ -69,9 +69,9 @@ async fn create_view(transaction: &mut DBTransaction<'_>, app: &App) -> Result<V
         cached_size: Default::default(),
     };
 
-    let name = "DefaultView".to_string();
-    let desc = "View created by AppFlowy Server".to_string();
-    let thumbnail = "http://1.png".to_string();
+    let _name = "DefaultView".to_string();
+    let _desc = "View created by AppFlowy Server".to_string();
+    let _thumbnail = "http://1.png".to_string();
 
     let view = create_view_with_transaction(transaction, params).await?;
 

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

@@ -4,7 +4,7 @@ use backend::{
 };
 
 use flowy_document::{
-    entities::doc::{Doc, QueryDocParams, SaveDocParams},
+    entities::doc::{Doc, QueryDocParams},
     prelude::*,
 };
 use flowy_user::{errors::UserError, prelude::*};

+ 0 - 2
rust-lib/dart-ffi/src/protobuf/mod.rs

@@ -1,4 +1,2 @@
-
 mod model;
 pub use model::*;
-        

+ 5 - 5
rust-lib/dart-ffi/src/protobuf/model/mod.rs

@@ -1,7 +1,7 @@
-// Auto-generated, do not edit 
+// Auto-generated, do not edit
 
-mod ffi_response; 
-pub use ffi_response::*; 
+mod ffi_response;
+pub use ffi_response::*;
 
-mod ffi_request; 
-pub use ffi_request::*; 
+mod ffi_request;
+pub use ffi_request::*;

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

@@ -58,10 +58,4 @@ table! {
     }
 }
 
-allow_tables_to_appear_in_same_query!(
-    app_table,
-    doc_table,
-    user_table,
-    view_table,
-    workspace_table,
-);
+allow_tables_to_appear_in_same_query!(app_table, doc_table, user_table, view_table, workspace_table,);

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

@@ -71,8 +71,7 @@ pub fn category_from_str(type_str: &str) -> TypeCategory {
         | "UserProfile"
         | "UpdateUserRequest"
         | "UpdateUserParams"
-        | "UserError"
-        => TypeCategory::Protobuf,
+        | "UserError" => TypeCategory::Protobuf,
         "ViewType"
         | "WorkspaceEvent"
         | "ErrorCode"
@@ -81,8 +80,7 @@ pub fn category_from_str(type_str: &str) -> TypeCategory {
         | "FFIStatusCode"
         | "UserStatus"
         | "UserEvent"
-        | "UserObservable"
-        => TypeCategory::Enum,
+        | "UserObservable" => TypeCategory::Enum,
 
         "Option" => TypeCategory::Opt,
         _ => TypeCategory::Primitive,

+ 1 - 1
rust-lib/flowy-dispatch/tests/api/helper.rs

@@ -5,7 +5,7 @@ use std::sync::Once;
 #[allow(dead_code)]
 pub fn setup_env() {
     static INIT: Once = Once::new();
-    INIT.call_once(|| env_logger::init());
+    (|| env_logger::init());
 }
 
 pub fn init_dispatch<F>(module_factory: F) -> EventDispatch

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

@@ -1,5 +1,4 @@
 use flowy_derive::ProtoBuf;
-use std::convert::TryInto;
 
 #[derive(ProtoBuf, Default, Debug, Clone)]
 pub struct CreateDocParams {

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

@@ -14,10 +14,39 @@ pub struct DocError {
     pub msg: String,
 }
 
+macro_rules! static_doc_error {
+    ($name:ident, $status:expr) => {
+        #[allow(non_snake_case, missing_docs)]
+        pub fn $name() -> DocError {
+            DocError {
+                code: $status,
+                msg: format!("{}", $status),
+            }
+        }
+    };
+}
+
 impl DocError {
     fn new(code: ErrorCode, msg: &str) -> Self { Self { code, msg: msg.to_owned() } }
 
+    pub fn context<T: Debug>(mut self, error: T) -> Self {
+        self.msg = format!("{:?}", error);
+        self
+    }
+
     pub fn is_record_not_found(&self) -> bool { self.code == ErrorCode::DocNotfound }
+
+    static_doc_error!(id_invalid, ErrorCode::DocIdInvalid);
+    static_doc_error!(internal, ErrorCode::InternalError);
+    static_doc_error!(not_found, ErrorCode::DocNotfound);
+    static_doc_error!(unauthorized, ErrorCode::UserUnauthorized);
+}
+
+pub fn internal_error<T>(e: T) -> DocError
+where
+    T: std::fmt::Debug,
+{
+    DocError::internal().context(e)
 }
 
 #[derive(Debug, Clone, ProtoBuf_Enum, Display, PartialEq, Eq)]
@@ -42,14 +71,14 @@ impl std::default::Default for ErrorCode {
 impl std::convert::From<flowy_database::Error> for DocError {
     fn from(error: flowy_database::Error) -> Self {
         match error {
-            flowy_database::Error::NotFound => ErrorBuilder::new(ErrorCode::DocNotfound).error(error).build(),
-            _ => ErrorBuilder::new(ErrorCode::InternalError).error(error).build(),
+            flowy_database::Error::NotFound => DocError::not_found().context(error),
+            _ => DocError::internal().context(error),
         }
     }
 }
 
 impl std::convert::From<flowy_ot::errors::OTError> for DocError {
-    fn from(error: flowy_ot::errors::OTError) -> Self { ErrorBuilder::new(ErrorCode::InternalError).error(error).build() }
+    fn from(error: flowy_ot::errors::OTError) -> Self { DocError::internal().context(error) }
 }
 
 // impl std::convert::From<::r2d2::Error> for DocError {
@@ -63,11 +92,12 @@ impl std::convert::From<flowy_ot::errors::OTError> for DocError {
 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()
+        DocError::new(code, &error.msg)
     }
 }
 
 use flowy_net::errors::ErrorCode as ServerErrorCode;
+use std::fmt::Debug;
 
 fn server_error_to_doc_error(code: ServerErrorCode) -> ErrorCode {
     match code {
@@ -87,8 +117,3 @@ impl flowy_dispatch::Error for DocError {
 impl fmt::Display for DocError {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{:?}: {}", &self.code, &self.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) }
-}

+ 3 - 3
rust-lib/flowy-document/src/module.rs

@@ -9,9 +9,9 @@ use crate::{
 };
 use diesel::SqliteConnection;
 use flowy_database::ConnectionPool;
-use flowy_ot::client::Document;
+
+use crate::errors::internal_error;
 use std::sync::Arc;
-use tokio::sync::RwLock;
 
 pub trait DocumentUser: Send + Sync {
     fn user_doc_dir(&self) -> Result<String, DocError>;
@@ -51,7 +51,7 @@ impl FlowyDocument {
     }
 
     pub async fn update(&self, params: SaveDocParams, pool: Arc<ConnectionPool>) -> Result<(), DocError> {
-        let _ = self.controller.update(params, &*pool.get().unwrap())?;
+        let _ = self.controller.update(params, &*pool.get().map_err(internal_error)?)?;
         Ok(())
     }
 

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

@@ -1,4 +1,2 @@
-
 mod model;
 pub use model::*;
-        

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

@@ -1,13 +1,13 @@
-// Auto-generated, do not edit 
+// Auto-generated, do not edit
 
-mod observable; 
-pub use observable::*; 
+mod observable;
+pub use observable::*;
 
-mod errors; 
-pub use errors::*; 
+mod errors;
+pub use errors::*;
 
-mod event; 
-pub use event::*; 
+mod event;
+pub use event::*;
 
-mod doc; 
-pub use doc::*; 
+mod doc;
+pub use doc::*;

+ 4 - 12
rust-lib/flowy-document/src/services/doc_cache.rs

@@ -1,10 +1,6 @@
-use crate::errors::{DocError, ErrorBuilder, ErrorCode};
+use crate::errors::DocError;
 use dashmap::DashMap;
-use flowy_ot::{
-    client::{Document, FlowyDoc},
-    core::Delta,
-    errors::OTError,
-};
+use flowy_ot::{client::Document, core::Delta, errors::OTError};
 use std::convert::TryInto;
 use tokio::sync::RwLock;
 
@@ -65,7 +61,7 @@ impl DocCache {
         match self.inner.get(&doc_id) {
             None => Err(doc_not_found()),
             Some(doc_info) => {
-                let mut write_guard = doc_info.read().await;
+                let write_guard = doc_info.read().await;
                 let doc = &(*write_guard).document;
                 Ok(Some(doc.to_json()))
             },
@@ -82,8 +78,4 @@ impl DocCache {
     }
 }
 
-fn doc_not_found() -> DocError {
-    ErrorBuilder::new(ErrorCode::DocNotfound)
-        .msg("Doc is close or you should call open first")
-        .build()
-}
+fn doc_not_found() -> DocError { DocError::not_found().context("Doc is close or you should call open first") }

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

@@ -1,12 +1,13 @@
 use crate::{
     entities::doc::{CreateDocParams, Doc, QueryDocParams, SaveDocParams},
-    errors::{DocError, ErrorBuilder, ErrorCode},
+    errors::DocError,
     module::DocumentUser,
     services::server::Server,
     sql_tables::doc::{DocTable, DocTableChangeset, DocTableSql},
 };
 use flowy_database::{ConnectionPool, SqliteConnection};
 
+use crate::errors::internal_error;
 use std::sync::Arc;
 use tokio::task::JoinHandle;
 
@@ -86,10 +87,10 @@ impl DocController {
 
         Ok(tokio::spawn(async move {
             match server.read_doc(&token, params).await? {
-                None => Err(ErrorBuilder::new(ErrorCode::DocNotfound).build()),
+                None => Err(DocError::not_found()),
                 Some(doc) => {
                     let doc_table = DocTable::new(doc.clone());
-                    let _ = sql.create_doc_table(doc_table, &*(pool.get().unwrap()))?;
+                    let _ = sql.create_doc_table(doc_table, &*(pool.get().map_err(internal_error)?))?;
                     // TODO: notify
                     Ok(doc)
                 },
@@ -101,7 +102,7 @@ impl DocController {
     async fn sync_read_doc_from_server(&self, params: QueryDocParams) -> Result<Doc, DocError> {
         let token = self.user.token()?;
         match self.server.read_doc(&token, params).await? {
-            None => Err(ErrorBuilder::new(ErrorCode::DocNotfound).build()),
+            None => Err(DocError::not_found()),
             Some(doc) => Ok(doc),
         }
     }
@@ -123,7 +124,7 @@ impl DocController {
     }
 
     fn _open(&self, params: QueryDocParams, pool: Arc<ConnectionPool>) -> Result<Doc, DocError> {
-        let doc_table = self.sql.read_doc_table(&params.doc_id, &*(pool.get().unwrap()))?;
+        let doc_table = self.sql.read_doc_table(&params.doc_id, &*(pool.get().map_err(internal_error)?))?;
         let doc: Doc = doc_table.into();
         let _ = self.read_doc_from_server(params, pool.clone())?;
         Ok(doc)
@@ -138,10 +139,3 @@ impl DocController {
         }
     }
 }
-
-fn internal_error<T>(e: T) -> DocError
-where
-    T: std::fmt::Debug,
-{
-    ErrorBuilder::new(ErrorCode::InternalError).error(e).build()
-}

+ 1 - 1
rust-lib/flowy-infra/src/errors/builder.rs

@@ -3,7 +3,7 @@ use std::{fmt::Debug, marker::PhantomData};
 pub trait Build<C> {
     fn build(code: C, msg: String) -> Self;
 }
-
+#[allow(dead_code)]
 pub struct Builder<C, O> {
     pub code: C,
     pub msg: Option<String>,

+ 0 - 2
rust-lib/flowy-infra/src/protobuf/mod.rs

@@ -1,4 +1,2 @@
-
 mod model;
 pub use model::*;
-        

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

@@ -1,4 +1,4 @@
-// Auto-generated, do not edit 
+// Auto-generated, do not edit
 
-mod kv; 
-pub use kv::*; 
+mod kv;
+pub use kv::*;

+ 2 - 2
rust-lib/flowy-net/src/response/response_serde.rs

@@ -49,7 +49,7 @@
 //                                 return
 // Err(de::Error::duplicate_field("data"));                             }
 //                             data = match
-// MapAccess::next_value::<DeserializeWith<T>>(&mut map) {                      
+// MapAccess::next_value::<DeserializeWith<T>>(&mut map) {
 // Ok(wrapper) => wrapper.value,                                 Err(err) =>
 // return Err(err),                             };
 //                         },
@@ -58,7 +58,7 @@
 //                 }
 //                 let msg = msg.ok_or_else(||
 // de::Error::missing_field("msg"))?;                 let code =
-// code.ok_or_else(|| de::Error::missing_field("code"))?;                 
+// code.ok_or_else(|| de::Error::missing_field("code"))?;
 // Ok(Self::Value::new(data, msg, code))             }
 //         }
 //         const FIELDS: &'static [&'static str] = &["msg", "code", "data"];

+ 0 - 2
rust-lib/flowy-observable/src/protobuf/mod.rs

@@ -1,4 +1,2 @@
-
 mod model;
 pub use model::*;
-        

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

@@ -1,4 +1,4 @@
-// Auto-generated, do not edit 
+// Auto-generated, do not edit
 
-mod subject; 
-pub use subject::*; 
+mod subject;
+pub use subject::*;

+ 1 - 1
rust-lib/flowy-ot/src/core/attributes/attribute.rs

@@ -2,7 +2,7 @@
 
 use crate::{block_attribute, core::Attributes, ignore_attribute, inline_attribute, list_attribute};
 use lazy_static::lazy_static;
-use serde::{Deserialize, Serialize};
+
 use std::{collections::HashSet, fmt, fmt::Formatter, iter::FromIterator};
 use strum_macros::Display;
 #[derive(Debug, Clone)]

+ 2 - 2
rust-lib/flowy-ot/src/core/attributes/attributes_serde.rs

@@ -1,6 +1,6 @@
 #[rustfmt::skip]
 use crate::core::AttributeValue;
-use crate::core::{Attribute, AttributeKey, Attributes};
+use crate::core::{AttributeKey, Attributes};
 use serde::{
     de,
     de::{MapAccess, Visitor},
@@ -10,7 +10,7 @@ use serde::{
     Serialize,
     Serializer,
 };
-use std::{collections::HashMap, fmt, marker::PhantomData, str::ParseBoolError};
+use std::fmt;
 
 impl Serialize for Attributes {
     fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>

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

@@ -1,7 +1,4 @@
-use flowy_document::{
-    errors::{DocError, ErrorBuilder, ErrorCode},
-    module::DocumentUser,
-};
+use flowy_document::{errors::DocError, module::DocumentUser};
 
 use flowy_user::services::user::UserSession;
 use std::{path::Path, sync::Arc};
@@ -12,10 +9,7 @@ pub struct EditorUserImpl {
 
 impl DocumentUser for EditorUserImpl {
     fn user_doc_dir(&self) -> Result<String, DocError> {
-        let dir = self
-            .user_session
-            .user_dir()
-            .map_err(|e| ErrorBuilder::new(ErrorCode::UserUnauthorized).error(e).build())?;
+        let dir = self.user_session.user_dir().map_err(|e| DocError::unauthorized().context(e))?;
 
         let doc_dir = format!("{}/doc", dir);
         if !Path::new(&doc_dir).exists() {
@@ -25,15 +19,7 @@ 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 user_id(&self) -> Result<String, DocError> { self.user_session.user_id().map_err(|e| DocError::internal().context(e)) }
 
-    fn token(&self) -> Result<String, DocError> {
-        self.user_session
-            .token()
-            .map_err(|e| ErrorBuilder::new(ErrorCode::InternalError).error(e).build())
-    }
+    fn token(&self) -> Result<String, DocError> { self.user_session.token().map_err(|e| DocError::internal().context(e)) }
 }

+ 4 - 14
rust-lib/flowy-sdk/src/deps_resolve/workspace_deps_impl.rs

@@ -1,7 +1,7 @@
 use flowy_database::ConnectionPool;
 use flowy_user::services::user::UserSession;
 use flowy_workspace::{
-    errors::{ErrorBuilder, ErrorCode, WorkspaceError},
+    errors::WorkspaceError,
     module::{WorkspaceDatabase, WorkspaceUser},
 };
 use std::sync::Arc;
@@ -11,17 +11,9 @@ pub struct WorkspaceUserImpl {
 }
 
 impl WorkspaceUser for WorkspaceUserImpl {
-    fn user_id(&self) -> Result<String, WorkspaceError> {
-        self.user_session
-            .user_id()
-            .map_err(|e| ErrorBuilder::new(ErrorCode::InternalError).error(e).build())
-    }
+    fn user_id(&self) -> Result<String, WorkspaceError> { self.user_session.user_id().map_err(|e| WorkspaceError::internal().context(e)) }
 
-    fn token(&self) -> Result<String, WorkspaceError> {
-        self.user_session
-            .token()
-            .map_err(|e| ErrorBuilder::new(ErrorCode::InternalError).error(e).build())
-    }
+    fn token(&self) -> Result<String, WorkspaceError> { self.user_session.token().map_err(|e| WorkspaceError::internal().context(e)) }
 }
 
 pub struct WorkspaceDatabaseImpl {
@@ -30,8 +22,6 @@ pub struct WorkspaceDatabaseImpl {
 
 impl WorkspaceDatabase for WorkspaceDatabaseImpl {
     fn db_pool(&self) -> Result<Arc<ConnectionPool>, WorkspaceError> {
-        self.user_session
-            .db_pool()
-            .map_err(|e| ErrorBuilder::new(ErrorCode::InternalError).error(e).build())
+        self.user_session.db_pool().map_err(|e| WorkspaceError::internal().context(e))
     }
 }

+ 4 - 4
rust-lib/flowy-test/src/helper.rs

@@ -4,7 +4,7 @@ use flowy_infra::{kv::KV, uuid};
 
 use flowy_user::{
     entities::{SignInRequest, SignUpRequest, UserProfile},
-    errors::{ErrorBuilder, ErrorCode, UserError},
+    errors::UserError,
     event::UserEvent::{SignIn, SignOut, SignUp},
 };
 use flowy_workspace::{
@@ -44,7 +44,7 @@ const DEFAULT_WORKSPACE: &'static str = "Default_Workspace";
 pub(crate) fn create_default_workspace_if_need(dispatch: Arc<EventDispatch>, user_id: &str) -> Result<(), UserError> {
     let key = format!("{}{}", user_id, DEFAULT_WORKSPACE);
     if KV::get_bool(&key).unwrap_or(false) {
-        return Err(ErrorBuilder::new(ErrorCode::InternalError).build());
+        return Err(UserError::internal());
     }
     KV::set_bool(&key, true);
 
@@ -58,9 +58,9 @@ pub(crate) fn create_default_workspace_if_need(dispatch: Arc<EventDispatch>, use
     let request = ModuleRequest::new(CreateWorkspace).payload(payload);
     let result = EventDispatch::sync_send(dispatch.clone(), request)
         .parse::<Workspace, WorkspaceError>()
-        .map_err(|e| ErrorBuilder::new(ErrorCode::InternalError).error(e).build())?;
+        .map_err(|e| UserError::internal().context(e))?;
 
-    let workspace = result.map_err(|e| ErrorBuilder::new(ErrorCode::InternalError).error(e).build())?;
+    let workspace = result.map_err(|e| UserError::internal().context(e))?;
     let query: Bytes = QueryWorkspaceRequest {
         workspace_id: Some(workspace.id.clone()),
     }

+ 5 - 5
rust-lib/flowy-user/src/entities/auth.rs

@@ -39,8 +39,8 @@ impl TryInto<SignInParams> for SignInRequest {
     type Error = UserError;
 
     fn try_into(self) -> Result<SignInParams, Self::Error> {
-        let email = UserEmail::parse(self.email).map_err(|e| ErrorBuilder::new(e).build())?;
-        let password = UserPassword::parse(self.password).map_err(|e| ErrorBuilder::new(e).build())?;
+        let email = UserEmail::parse(self.email).map_err(|e| UserError::code(e))?;
+        let password = UserPassword::parse(self.password).map_err(|e| UserError::code(e))?;
 
         Ok(SignInParams {
             email: email.0,
@@ -64,9 +64,9 @@ impl TryInto<SignUpParams> for SignUpRequest {
     type Error = UserError;
 
     fn try_into(self) -> Result<SignUpParams, Self::Error> {
-        let email = UserEmail::parse(self.email).map_err(|e| ErrorBuilder::new(e).build())?;
-        let password = UserPassword::parse(self.password).map_err(|e| ErrorBuilder::new(e).build())?;
-        let name = UserName::parse(self.name).map_err(|e| ErrorBuilder::new(e).build())?;
+        let email = UserEmail::parse(self.email).map_err(|e| UserError::code(e))?;
+        let password = UserPassword::parse(self.password).map_err(|e| UserError::code(e))?;
+        let name = UserName::parse(self.name).map_err(|e| UserError::code(e))?;
 
         Ok(SignUpParams {
             email: email.0,

+ 1 - 1
rust-lib/flowy-user/src/entities/parser/user_name.rs

@@ -26,7 +26,7 @@ impl UserName {
         let contains_forbidden_characters = s.chars().any(|g| forbidden_characters.contains(&g));
 
         if contains_forbidden_characters {
-            return Err(ErrorCode::ContainForbiddenCharacters);
+            return Err(ErrorCode::UserNameContainForbiddenCharacters);
         }
 
         Ok(Self(s))

+ 5 - 7
rust-lib/flowy-user/src/entities/user_profile.rs

@@ -34,7 +34,7 @@ pub struct UserProfile {
 
 use crate::{
     entities::parser::{UserEmail, UserId, UserName, UserPassword},
-    errors::{ErrorBuilder, ErrorCode, UserError},
+    errors::UserError,
     sql_tables::UserTable,
 };
 use std::convert::TryInto;
@@ -133,23 +133,21 @@ impl TryInto<UpdateUserParams> for UpdateUserRequest {
     type Error = UserError;
 
     fn try_into(self) -> Result<UpdateUserParams, Self::Error> {
-        let id = UserId::parse(self.id)
-            .map_err(|e| ErrorBuilder::new(ErrorCode::UserIdInvalid).msg(e).build())?
-            .0;
+        let id = UserId::parse(self.id).map_err(|e| UserError::user_id().context(e))?.0;
 
         let name = match self.name {
             None => None,
-            Some(name) => Some(UserName::parse(name).map_err(|e| ErrorBuilder::new(e).build())?.0),
+            Some(name) => Some(UserName::parse(name).map_err(|e| UserError::code(e))?.0),
         };
 
         let email = match self.email {
             None => None,
-            Some(email) => Some(UserEmail::parse(email).map_err(|e| ErrorBuilder::new(e).build())?.0),
+            Some(email) => Some(UserEmail::parse(email).map_err(|e| UserError::code(e))?.0),
         };
 
         let password = match self.password {
             None => None,
-            Some(password) => Some(UserPassword::parse(password).map_err(|e| ErrorBuilder::new(e).build())?.0),
+            Some(password) => Some(UserPassword::parse(password).map_err(|e| UserError::code(e))?.0),
         };
 
         Ok(UpdateUserParams { id, name, email, password })

+ 60 - 44
rust-lib/flowy-user/src/errors.rs

@@ -14,86 +14,111 @@ pub struct UserError {
     pub msg: String,
 }
 
+macro_rules! static_user_error {
+    ($name:ident, $status:expr) => {
+        #[allow(non_snake_case, missing_docs)]
+        pub fn $name() -> UserError {
+            UserError {
+                code: $status,
+                msg: format!("{}", $status),
+            }
+        }
+    };
+}
+
 impl UserError {
     pub(crate) fn new(code: ErrorCode, msg: &str) -> Self { Self { code, msg: msg.to_owned() } }
+
+    pub(crate) fn code(code: ErrorCode) -> Self { Self { code, msg: "".to_owned() } }
+
+    pub fn context<T: Debug>(mut self, error: T) -> Self {
+        self.msg = format!("{:?}", error);
+        self
+    }
+
+    static_user_error!(email_empty, ErrorCode::EmailIsEmpty);
+    static_user_error!(email_format, ErrorCode::EmailFormatInvalid);
+    static_user_error!(email_exist, ErrorCode::EmailAlreadyExists);
+    static_user_error!(password_empty, ErrorCode::PasswordIsEmpty);
+    static_user_error!(passworkd_too_long, ErrorCode::PasswordTooLong);
+    static_user_error!(password_forbid_char, ErrorCode::PasswordContainsForbidCharacters);
+    static_user_error!(password_format, ErrorCode::PasswordFormatInvalid);
+    static_user_error!(password_not_match, ErrorCode::PasswordNotMatch);
+    static_user_error!(name_too_long, ErrorCode::UserNameTooLong);
+    static_user_error!(name_forbid_char, ErrorCode::UserNameContainForbiddenCharacters);
+    static_user_error!(name_empty, ErrorCode::UserNameIsEmpty);
+    static_user_error!(user_id, ErrorCode::UserIdInvalid);
+    static_user_error!(unauthorized, ErrorCode::UserUnauthorized);
+    static_user_error!(user_not_exist, ErrorCode::UserNotExist);
+    static_user_error!(internal, ErrorCode::InternalError);
 }
 
 #[derive(Debug, Clone, ProtoBuf_Enum, Display, PartialEq, Eq)]
 pub enum ErrorCode {
-    #[display(fmt = "Unknown")]
-    Unknown              = 0,
-    #[display(fmt = "Database init failed")]
-    UserDatabaseInitFailed = 1,
-    #[display(fmt = "Acquire database write lock failed")]
-    AcquireWriteLockedFailed = 2,
-    #[display(fmt = "Acquire database read lock failed")]
-    AcquireReadLockedFailed = 3,
-    #[display(fmt = "Opening database is not belonging to the current user")]
-    UserDatabaseDidNotMatch = 4,
-
     #[display(fmt = "Email can not be empty or whitespace")]
-    EmailIsEmpty         = 20,
+    EmailIsEmpty       = 0,
     #[display(fmt = "Email format is not valid")]
-    EmailFormatInvalid   = 21,
+    EmailFormatInvalid = 1,
     #[display(fmt = "Email already exists")]
-    EmailAlreadyExists   = 22,
+    EmailAlreadyExists = 2,
     #[display(fmt = "Password can not be empty or whitespace")]
-    PasswordIsEmpty      = 30,
+    PasswordIsEmpty    = 10,
     #[display(fmt = "Password format too long")]
-    PasswordTooLong      = 31,
+    PasswordTooLong    = 11,
     #[display(fmt = "Password contains forbidden characters.")]
-    PasswordContainsForbidCharacters = 32,
+    PasswordContainsForbidCharacters = 12,
     #[display(fmt = "Password should contain a minimum of 6 characters with 1 special 1 letter and 1 numeric")]
-    PasswordFormatInvalid = 33,
+    PasswordFormatInvalid = 13,
     #[display(fmt = "Password not match")]
-    PasswordNotMatch     = 34,
-
+    PasswordNotMatch   = 14,
     #[display(fmt = "User name is too long")]
-    UserNameTooLong      = 40,
+    UserNameTooLong    = 20,
     #[display(fmt = "User name contain forbidden characters")]
-    ContainForbiddenCharacters = 41,
+    UserNameContainForbiddenCharacters = 21,
     #[display(fmt = "User name can not be empty or whitespace")]
-    UserNameIsEmpty      = 42,
-    #[display(fmt = "User workspace is invalid")]
-    UserWorkspaceInvalid = 50,
+    UserNameIsEmpty    = 22,
     #[display(fmt = "User id is invalid")]
-    UserIdInvalid        = 51,
+    UserIdInvalid      = 23,
     #[display(fmt = "User token is invalid")]
-    UserUnauthorized     = 54,
+    UserUnauthorized   = 24,
     #[display(fmt = "User not exist")]
-    UserNotExist         = 55,
+    UserNotExist       = 25,
 
     #[display(fmt = "Internal error")]
-    InternalError        = 100,
+    InternalError      = 100,
+}
+
+impl std::convert::Into<UserError> for ErrorCode {
+    fn into(self) -> UserError { UserError::new(self, "") }
 }
 
 impl std::default::Default for ErrorCode {
-    fn default() -> Self { ErrorCode::Unknown }
+    fn default() -> Self { ErrorCode::InternalError }
 }
 
 impl std::convert::From<flowy_database::Error> for UserError {
     fn from(error: flowy_database::Error) -> Self {
         match error {
-            flowy_database::Error::NotFound => ErrorBuilder::new(ErrorCode::UserNotExist).error(error).build(),
-            _ => ErrorBuilder::new(ErrorCode::InternalError).error(error).build(),
+            flowy_database::Error::NotFound => UserError::user_not_exist().context(error),
+            _ => UserError::internal().context(error),
         }
     }
 }
 
 impl std::convert::From<::r2d2::Error> for UserError {
-    fn from(error: r2d2::Error) -> Self { ErrorBuilder::new(ErrorCode::InternalError).error(error).build() }
+    fn from(error: r2d2::Error) -> Self { UserError::internal().context(error) }
 }
 
 // use diesel::result::{Error, DatabaseErrorKind};
 // use flowy_sqlite::ErrorKind;
 impl std::convert::From<flowy_sqlite::Error> for UserError {
-    fn from(error: flowy_sqlite::Error) -> Self { ErrorBuilder::new(ErrorCode::InternalError).error(error).build() }
+    fn from(error: flowy_sqlite::Error) -> Self { UserError::internal().context(error) }
 }
 
 impl std::convert::From<flowy_net::errors::ServerError> for UserError {
     fn from(error: flowy_net::errors::ServerError) -> Self {
         let code = server_error_to_user_error(error.code);
-        ErrorBuilder::new(code).error(error.msg).build()
+        UserError::new(code, &error.msg)
     }
 }
 
@@ -113,12 +138,3 @@ impl flowy_dispatch::Error for UserError {
         ResponseBuilder::Err().data(bytes).build()
     }
 }
-
-pub type ErrorBuilder = flowy_infra::errors::Builder<ErrorCode, UserError>;
-
-impl flowy_infra::errors::Build<ErrorCode> for UserError {
-    fn build(code: ErrorCode, msg: String) -> Self {
-        let msg = if msg.is_empty() { format!("{}", code) } else { msg };
-        UserError::new(code, &msg)
-    }
-}

+ 0 - 2
rust-lib/flowy-user/src/protobuf/mod.rs

@@ -1,4 +1,2 @@
-
 mod model;
 pub use model::*;
-        

+ 80 - 113
rust-lib/flowy-user/src/protobuf/model/errors.rs

@@ -51,7 +51,7 @@ impl UserError {
         self.code
     }
     pub fn clear_code(&mut self) {
-        self.code = ErrorCode::Unknown;
+        self.code = ErrorCode::EmailIsEmpty;
     }
 
     // Param is passed by value, moved
@@ -113,7 +113,7 @@ impl ::protobuf::Message for UserError {
     #[allow(unused_variables)]
     fn compute_size(&self) -> u32 {
         let mut my_size = 0;
-        if self.code != ErrorCode::Unknown {
+        if self.code != ErrorCode::EmailIsEmpty {
             my_size += ::protobuf::rt::enum_size(1, self.code);
         }
         if !self.msg.is_empty() {
@@ -125,7 +125,7 @@ impl ::protobuf::Message for UserError {
     }
 
     fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::ProtobufResult<()> {
-        if self.code != ErrorCode::Unknown {
+        if self.code != ErrorCode::EmailIsEmpty {
             os.write_enum(1, ::protobuf::ProtobufEnum::value(&self.code))?;
         }
         if !self.msg.is_empty() {
@@ -195,7 +195,7 @@ impl ::protobuf::Message for UserError {
 
 impl ::protobuf::Clear for UserError {
     fn clear(&mut self) {
-        self.code = ErrorCode::Unknown;
+        self.code = ErrorCode::EmailIsEmpty;
         self.msg.clear();
         self.unknown_fields.clear();
     }
@@ -215,26 +215,20 @@ impl ::protobuf::reflect::ProtobufValue for UserError {
 
 #[derive(Clone,PartialEq,Eq,Debug,Hash)]
 pub enum ErrorCode {
-    Unknown = 0,
-    UserDatabaseInitFailed = 1,
-    AcquireWriteLockedFailed = 2,
-    AcquireReadLockedFailed = 3,
-    UserDatabaseDidNotMatch = 4,
-    EmailIsEmpty = 20,
-    EmailFormatInvalid = 21,
-    EmailAlreadyExists = 22,
-    PasswordIsEmpty = 30,
-    PasswordTooLong = 31,
-    PasswordContainsForbidCharacters = 32,
-    PasswordFormatInvalid = 33,
-    PasswordNotMatch = 34,
-    UserNameTooLong = 40,
-    ContainForbiddenCharacters = 41,
-    UserNameIsEmpty = 42,
-    UserWorkspaceInvalid = 50,
-    UserIdInvalid = 51,
-    UserUnauthorized = 54,
-    UserNotExist = 55,
+    EmailIsEmpty = 0,
+    EmailFormatInvalid = 1,
+    EmailAlreadyExists = 2,
+    PasswordIsEmpty = 10,
+    PasswordTooLong = 11,
+    PasswordContainsForbidCharacters = 12,
+    PasswordFormatInvalid = 13,
+    PasswordNotMatch = 14,
+    UserNameTooLong = 20,
+    UserNameContainForbiddenCharacters = 21,
+    UserNameIsEmpty = 22,
+    UserIdInvalid = 23,
+    UserUnauthorized = 24,
+    UserNotExist = 25,
     InternalError = 100,
 }
 
@@ -245,26 +239,20 @@ impl ::protobuf::ProtobufEnum for ErrorCode {
 
     fn from_i32(value: i32) -> ::std::option::Option<ErrorCode> {
         match value {
-            0 => ::std::option::Option::Some(ErrorCode::Unknown),
-            1 => ::std::option::Option::Some(ErrorCode::UserDatabaseInitFailed),
-            2 => ::std::option::Option::Some(ErrorCode::AcquireWriteLockedFailed),
-            3 => ::std::option::Option::Some(ErrorCode::AcquireReadLockedFailed),
-            4 => ::std::option::Option::Some(ErrorCode::UserDatabaseDidNotMatch),
-            20 => ::std::option::Option::Some(ErrorCode::EmailIsEmpty),
-            21 => ::std::option::Option::Some(ErrorCode::EmailFormatInvalid),
-            22 => ::std::option::Option::Some(ErrorCode::EmailAlreadyExists),
-            30 => ::std::option::Option::Some(ErrorCode::PasswordIsEmpty),
-            31 => ::std::option::Option::Some(ErrorCode::PasswordTooLong),
-            32 => ::std::option::Option::Some(ErrorCode::PasswordContainsForbidCharacters),
-            33 => ::std::option::Option::Some(ErrorCode::PasswordFormatInvalid),
-            34 => ::std::option::Option::Some(ErrorCode::PasswordNotMatch),
-            40 => ::std::option::Option::Some(ErrorCode::UserNameTooLong),
-            41 => ::std::option::Option::Some(ErrorCode::ContainForbiddenCharacters),
-            42 => ::std::option::Option::Some(ErrorCode::UserNameIsEmpty),
-            50 => ::std::option::Option::Some(ErrorCode::UserWorkspaceInvalid),
-            51 => ::std::option::Option::Some(ErrorCode::UserIdInvalid),
-            54 => ::std::option::Option::Some(ErrorCode::UserUnauthorized),
-            55 => ::std::option::Option::Some(ErrorCode::UserNotExist),
+            0 => ::std::option::Option::Some(ErrorCode::EmailIsEmpty),
+            1 => ::std::option::Option::Some(ErrorCode::EmailFormatInvalid),
+            2 => ::std::option::Option::Some(ErrorCode::EmailAlreadyExists),
+            10 => ::std::option::Option::Some(ErrorCode::PasswordIsEmpty),
+            11 => ::std::option::Option::Some(ErrorCode::PasswordTooLong),
+            12 => ::std::option::Option::Some(ErrorCode::PasswordContainsForbidCharacters),
+            13 => ::std::option::Option::Some(ErrorCode::PasswordFormatInvalid),
+            14 => ::std::option::Option::Some(ErrorCode::PasswordNotMatch),
+            20 => ::std::option::Option::Some(ErrorCode::UserNameTooLong),
+            21 => ::std::option::Option::Some(ErrorCode::UserNameContainForbiddenCharacters),
+            22 => ::std::option::Option::Some(ErrorCode::UserNameIsEmpty),
+            23 => ::std::option::Option::Some(ErrorCode::UserIdInvalid),
+            24 => ::std::option::Option::Some(ErrorCode::UserUnauthorized),
+            25 => ::std::option::Option::Some(ErrorCode::UserNotExist),
             100 => ::std::option::Option::Some(ErrorCode::InternalError),
             _ => ::std::option::Option::None
         }
@@ -272,11 +260,6 @@ impl ::protobuf::ProtobufEnum for ErrorCode {
 
     fn values() -> &'static [Self] {
         static values: &'static [ErrorCode] = &[
-            ErrorCode::Unknown,
-            ErrorCode::UserDatabaseInitFailed,
-            ErrorCode::AcquireWriteLockedFailed,
-            ErrorCode::AcquireReadLockedFailed,
-            ErrorCode::UserDatabaseDidNotMatch,
             ErrorCode::EmailIsEmpty,
             ErrorCode::EmailFormatInvalid,
             ErrorCode::EmailAlreadyExists,
@@ -286,9 +269,8 @@ impl ::protobuf::ProtobufEnum for ErrorCode {
             ErrorCode::PasswordFormatInvalid,
             ErrorCode::PasswordNotMatch,
             ErrorCode::UserNameTooLong,
-            ErrorCode::ContainForbiddenCharacters,
+            ErrorCode::UserNameContainForbiddenCharacters,
             ErrorCode::UserNameIsEmpty,
-            ErrorCode::UserWorkspaceInvalid,
             ErrorCode::UserIdInvalid,
             ErrorCode::UserUnauthorized,
             ErrorCode::UserNotExist,
@@ -310,7 +292,7 @@ impl ::std::marker::Copy for ErrorCode {
 
 impl ::std::default::Default for ErrorCode {
     fn default() -> Self {
-        ErrorCode::Unknown
+        ErrorCode::EmailIsEmpty
     }
 }
 
@@ -323,69 +305,54 @@ impl ::protobuf::reflect::ProtobufValue for ErrorCode {
 static file_descriptor_proto_data: &'static [u8] = b"\
     \n\x0cerrors.proto\"=\n\tUserError\x12\x1e\n\x04code\x18\x01\x20\x01(\
     \x0e2\n.ErrorCodeR\x04code\x12\x10\n\x03msg\x18\x02\x20\x01(\tR\x03msg*\
-    \x81\x04\n\tErrorCode\x12\x0b\n\x07Unknown\x10\0\x12\x1a\n\x16UserDataba\
-    seInitFailed\x10\x01\x12\x1c\n\x18AcquireWriteLockedFailed\x10\x02\x12\
-    \x1b\n\x17AcquireReadLockedFailed\x10\x03\x12\x1b\n\x17UserDatabaseDidNo\
-    tMatch\x10\x04\x12\x10\n\x0cEmailIsEmpty\x10\x14\x12\x16\n\x12EmailForma\
-    tInvalid\x10\x15\x12\x16\n\x12EmailAlreadyExists\x10\x16\x12\x13\n\x0fPa\
-    sswordIsEmpty\x10\x1e\x12\x13\n\x0fPasswordTooLong\x10\x1f\x12$\n\x20Pas\
-    swordContainsForbidCharacters\x10\x20\x12\x19\n\x15PasswordFormatInvalid\
-    \x10!\x12\x14\n\x10PasswordNotMatch\x10\"\x12\x13\n\x0fUserNameTooLong\
-    \x10(\x12\x1e\n\x1aContainForbiddenCharacters\x10)\x12\x13\n\x0fUserName\
-    IsEmpty\x10*\x12\x18\n\x14UserWorkspaceInvalid\x102\x12\x11\n\rUserIdInv\
-    alid\x103\x12\x14\n\x10UserUnauthorized\x106\x12\x10\n\x0cUserNotExist\
-    \x107\x12\x11\n\rInternalError\x10dJ\x8d\x08\n\x06\x12\x04\0\0\x1c\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\x11\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\x1c\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\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\x1f\n\x0c\n\x05\x05\0\x02\x01\x01\x12\x03\
-    \x08\x04\x1a\n\x0c\n\x05\x05\0\x02\x01\x02\x12\x03\x08\x1d\x1e\n\x0b\n\
-    \x04\x05\0\x02\x02\x12\x03\t\x04!\n\x0c\n\x05\x05\0\x02\x02\x01\x12\x03\
-    \t\x04\x1c\n\x0c\n\x05\x05\0\x02\x02\x02\x12\x03\t\x1f\x20\n\x0b\n\x04\
-    \x05\0\x02\x03\x12\x03\n\x04\x20\n\x0c\n\x05\x05\0\x02\x03\x01\x12\x03\n\
-    \x04\x1b\n\x0c\n\x05\x05\0\x02\x03\x02\x12\x03\n\x1e\x1f\n\x0b\n\x04\x05\
-    \0\x02\x04\x12\x03\x0b\x04\x20\n\x0c\n\x05\x05\0\x02\x04\x01\x12\x03\x0b\
-    \x04\x1b\n\x0c\n\x05\x05\0\x02\x04\x02\x12\x03\x0b\x1e\x1f\n\x0b\n\x04\
-    \x05\0\x02\x05\x12\x03\x0c\x04\x16\n\x0c\n\x05\x05\0\x02\x05\x01\x12\x03\
-    \x0c\x04\x10\n\x0c\n\x05\x05\0\x02\x05\x02\x12\x03\x0c\x13\x15\n\x0b\n\
-    \x04\x05\0\x02\x06\x12\x03\r\x04\x1c\n\x0c\n\x05\x05\0\x02\x06\x01\x12\
-    \x03\r\x04\x16\n\x0c\n\x05\x05\0\x02\x06\x02\x12\x03\r\x19\x1b\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\x19\n\x0c\n\x05\x05\0\x02\x08\x01\
-    \x12\x03\x0f\x04\x13\n\x0c\n\x05\x05\0\x02\x08\x02\x12\x03\x0f\x16\x18\n\
-    \x0b\n\x04\x05\0\x02\t\x12\x03\x10\x04\x19\n\x0c\n\x05\x05\0\x02\t\x01\
-    \x12\x03\x10\x04\x13\n\x0c\n\x05\x05\0\x02\t\x02\x12\x03\x10\x16\x18\n\
-    \x0b\n\x04\x05\0\x02\n\x12\x03\x11\x04*\n\x0c\n\x05\x05\0\x02\n\x01\x12\
-    \x03\x11\x04$\n\x0c\n\x05\x05\0\x02\n\x02\x12\x03\x11')\n\x0b\n\x04\x05\
-    \0\x02\x0b\x12\x03\x12\x04\x1f\n\x0c\n\x05\x05\0\x02\x0b\x01\x12\x03\x12\
-    \x04\x19\n\x0c\n\x05\x05\0\x02\x0b\x02\x12\x03\x12\x1c\x1e\n\x0b\n\x04\
+    \xee\x02\n\tErrorCode\x12\x10\n\x0cEmailIsEmpty\x10\0\x12\x16\n\x12Email\
+    FormatInvalid\x10\x01\x12\x16\n\x12EmailAlreadyExists\x10\x02\x12\x13\n\
+    \x0fPasswordIsEmpty\x10\n\x12\x13\n\x0fPasswordTooLong\x10\x0b\x12$\n\
+    \x20PasswordContainsForbidCharacters\x10\x0c\x12\x19\n\x15PasswordFormat\
+    Invalid\x10\r\x12\x14\n\x10PasswordNotMatch\x10\x0e\x12\x13\n\x0fUserNam\
+    eTooLong\x10\x14\x12&\n\"UserNameContainForbiddenCharacters\x10\x15\x12\
+    \x13\n\x0fUserNameIsEmpty\x10\x16\x12\x11\n\rUserIdInvalid\x10\x17\x12\
+    \x14\n\x10UserUnauthorized\x10\x18\x12\x10\n\x0cUserNotExist\x10\x19\x12\
+    \x11\n\rInternalError\x10dJ\x97\x06\n\x06\x12\x04\0\0\x16\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\x11\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\x16\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\x1b\n\x0c\n\x05\x05\0\x02\x01\x01\x12\x03\
+    \x08\x04\x16\n\x0c\n\x05\x05\0\x02\x01\x02\x12\x03\x08\x19\x1a\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\x19\n\x0c\n\x05\x05\0\x02\x03\x01\x12\
+    \x03\n\x04\x13\n\x0c\n\x05\x05\0\x02\x03\x02\x12\x03\n\x16\x18\n\x0b\n\
+    \x04\x05\0\x02\x04\x12\x03\x0b\x04\x19\n\x0c\n\x05\x05\0\x02\x04\x01\x12\
+    \x03\x0b\x04\x13\n\x0c\n\x05\x05\0\x02\x04\x02\x12\x03\x0b\x16\x18\n\x0b\
+    \n\x04\x05\0\x02\x05\x12\x03\x0c\x04*\n\x0c\n\x05\x05\0\x02\x05\x01\x12\
+    \x03\x0c\x04$\n\x0c\n\x05\x05\0\x02\x05\x02\x12\x03\x0c')\n\x0b\n\x04\
+    \x05\0\x02\x06\x12\x03\r\x04\x1f\n\x0c\n\x05\x05\0\x02\x06\x01\x12\x03\r\
+    \x04\x19\n\x0c\n\x05\x05\0\x02\x06\x02\x12\x03\r\x1c\x1e\n\x0b\n\x04\x05\
+    \0\x02\x07\x12\x03\x0e\x04\x1a\n\x0c\n\x05\x05\0\x02\x07\x01\x12\x03\x0e\
+    \x04\x14\n\x0c\n\x05\x05\0\x02\x07\x02\x12\x03\x0e\x17\x19\n\x0b\n\x04\
+    \x05\0\x02\x08\x12\x03\x0f\x04\x19\n\x0c\n\x05\x05\0\x02\x08\x01\x12\x03\
+    \x0f\x04\x13\n\x0c\n\x05\x05\0\x02\x08\x02\x12\x03\x0f\x16\x18\n\x0b\n\
+    \x04\x05\0\x02\t\x12\x03\x10\x04,\n\x0c\n\x05\x05\0\x02\t\x01\x12\x03\
+    \x10\x04&\n\x0c\n\x05\x05\0\x02\t\x02\x12\x03\x10)+\n\x0b\n\x04\x05\0\
+    \x02\n\x12\x03\x11\x04\x19\n\x0c\n\x05\x05\0\x02\n\x01\x12\x03\x11\x04\
+    \x13\n\x0c\n\x05\x05\0\x02\n\x02\x12\x03\x11\x16\x18\n\x0b\n\x04\x05\0\
+    \x02\x0b\x12\x03\x12\x04\x17\n\x0c\n\x05\x05\0\x02\x0b\x01\x12\x03\x12\
+    \x04\x11\n\x0c\n\x05\x05\0\x02\x0b\x02\x12\x03\x12\x14\x16\n\x0b\n\x04\
     \x05\0\x02\x0c\x12\x03\x13\x04\x1a\n\x0c\n\x05\x05\0\x02\x0c\x01\x12\x03\
     \x13\x04\x14\n\x0c\n\x05\x05\0\x02\x0c\x02\x12\x03\x13\x17\x19\n\x0b\n\
-    \x04\x05\0\x02\r\x12\x03\x14\x04\x19\n\x0c\n\x05\x05\0\x02\r\x01\x12\x03\
-    \x14\x04\x13\n\x0c\n\x05\x05\0\x02\r\x02\x12\x03\x14\x16\x18\n\x0b\n\x04\
-    \x05\0\x02\x0e\x12\x03\x15\x04$\n\x0c\n\x05\x05\0\x02\x0e\x01\x12\x03\
-    \x15\x04\x1e\n\x0c\n\x05\x05\0\x02\x0e\x02\x12\x03\x15!#\n\x0b\n\x04\x05\
-    \0\x02\x0f\x12\x03\x16\x04\x19\n\x0c\n\x05\x05\0\x02\x0f\x01\x12\x03\x16\
-    \x04\x13\n\x0c\n\x05\x05\0\x02\x0f\x02\x12\x03\x16\x16\x18\n\x0b\n\x04\
-    \x05\0\x02\x10\x12\x03\x17\x04\x1e\n\x0c\n\x05\x05\0\x02\x10\x01\x12\x03\
-    \x17\x04\x18\n\x0c\n\x05\x05\0\x02\x10\x02\x12\x03\x17\x1b\x1d\n\x0b\n\
-    \x04\x05\0\x02\x11\x12\x03\x18\x04\x17\n\x0c\n\x05\x05\0\x02\x11\x01\x12\
-    \x03\x18\x04\x11\n\x0c\n\x05\x05\0\x02\x11\x02\x12\x03\x18\x14\x16\n\x0b\
-    \n\x04\x05\0\x02\x12\x12\x03\x19\x04\x1a\n\x0c\n\x05\x05\0\x02\x12\x01\
-    \x12\x03\x19\x04\x14\n\x0c\n\x05\x05\0\x02\x12\x02\x12\x03\x19\x17\x19\n\
-    \x0b\n\x04\x05\0\x02\x13\x12\x03\x1a\x04\x16\n\x0c\n\x05\x05\0\x02\x13\
-    \x01\x12\x03\x1a\x04\x10\n\x0c\n\x05\x05\0\x02\x13\x02\x12\x03\x1a\x13\
-    \x15\n\x0b\n\x04\x05\0\x02\x14\x12\x03\x1b\x04\x18\n\x0c\n\x05\x05\0\x02\
-    \x14\x01\x12\x03\x1b\x04\x11\n\x0c\n\x05\x05\0\x02\x14\x02\x12\x03\x1b\
-    \x14\x17b\x06proto3\
+    \x04\x05\0\x02\r\x12\x03\x14\x04\x16\n\x0c\n\x05\x05\0\x02\r\x01\x12\x03\
+    \x14\x04\x10\n\x0c\n\x05\x05\0\x02\r\x02\x12\x03\x14\x13\x15\n\x0b\n\x04\
+    \x05\0\x02\x0e\x12\x03\x15\x04\x18\n\x0c\n\x05\x05\0\x02\x0e\x01\x12\x03\
+    \x15\x04\x11\n\x0c\n\x05\x05\0\x02\x0e\x02\x12\x03\x15\x14\x17b\x06proto\
+    3\
 ";
 
 static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;

+ 13 - 13
rust-lib/flowy-user/src/protobuf/model/mod.rs

@@ -1,19 +1,19 @@
-// Auto-generated, do not edit 
+// Auto-generated, do not edit
 
-mod observable; 
-pub use observable::*; 
+mod observable;
+pub use observable::*;
 
-mod user_table; 
-pub use user_table::*; 
+mod user_table;
+pub use user_table::*;
 
-mod errors; 
-pub use errors::*; 
+mod errors;
+pub use errors::*;
 
-mod user_profile; 
-pub use user_profile::*; 
+mod user_profile;
+pub use user_profile::*;
 
-mod event; 
-pub use event::*; 
+mod event;
+pub use event::*;
 
-mod auth; 
-pub use auth::*; 
+mod auth;
+pub use auth::*;

+ 14 - 20
rust-lib/flowy-user/src/protobuf/proto/errors.proto

@@ -5,25 +5,19 @@ message UserError {
     string msg = 2;
 }
 enum ErrorCode {
-    Unknown = 0;
-    UserDatabaseInitFailed = 1;
-    AcquireWriteLockedFailed = 2;
-    AcquireReadLockedFailed = 3;
-    UserDatabaseDidNotMatch = 4;
-    EmailIsEmpty = 20;
-    EmailFormatInvalid = 21;
-    EmailAlreadyExists = 22;
-    PasswordIsEmpty = 30;
-    PasswordTooLong = 31;
-    PasswordContainsForbidCharacters = 32;
-    PasswordFormatInvalid = 33;
-    PasswordNotMatch = 34;
-    UserNameTooLong = 40;
-    ContainForbiddenCharacters = 41;
-    UserNameIsEmpty = 42;
-    UserWorkspaceInvalid = 50;
-    UserIdInvalid = 51;
-    UserUnauthorized = 54;
-    UserNotExist = 55;
+    EmailIsEmpty = 0;
+    EmailFormatInvalid = 1;
+    EmailAlreadyExists = 2;
+    PasswordIsEmpty = 10;
+    PasswordTooLong = 11;
+    PasswordContainsForbidCharacters = 12;
+    PasswordFormatInvalid = 13;
+    PasswordNotMatch = 14;
+    UserNameTooLong = 20;
+    UserNameContainForbiddenCharacters = 21;
+    UserNameIsEmpty = 22;
+    UserIdInvalid = 23;
+    UserUnauthorized = 24;
+    UserNotExist = 25;
     InternalError = 100;
 }

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

@@ -1,6 +1,6 @@
 use crate::{
     entities::{SignInParams, SignInResponse, SignUpParams, SignUpResponse, UpdateUserParams, UserProfile},
-    errors::{ErrorBuilder, ErrorCode, UserError},
+    errors::UserError,
 };
 
 use crate::services::server::UserServerAPI;
@@ -40,6 +40,6 @@ impl UserServerAPI for UserServerMock {
     fn update_user(&self, _token: &str, _params: UpdateUserParams) -> ResultFuture<(), UserError> { ResultFuture::new(async { Ok(()) }) }
 
     fn get_user(&self, _token: &str) -> ResultFuture<UserProfile, UserError> {
-        ResultFuture::new(async { Err(ErrorBuilder::new(ErrorCode::Unknown).msg("mock data, ignore this error").build()) })
+        ResultFuture::new(async { Err(UserError::internal().context("mock data, ignore this error")) })
     }
 }

+ 7 - 15
rust-lib/flowy-user/src/services/user/database.rs

@@ -1,4 +1,4 @@
-use crate::errors::{ErrorBuilder, ErrorCode, UserError};
+use crate::errors::UserError;
 use flowy_database::{DBConnection, Database};
 use flowy_sqlite::ConnectionPool;
 use lazy_static::lazy_static;
@@ -18,20 +18,18 @@ impl UserDB {
 
     fn open_user_db(&self, user_id: &str) -> Result<(), UserError> {
         if user_id.is_empty() {
-            return Err(ErrorBuilder::new(ErrorCode::UserDatabaseInitFailed).msg("user id is empty").build());
+            return Err(UserError::internal().context("user id is empty"));
         }
 
         log::info!("open user db {}", user_id);
         let dir = format!("{}/{}", self.db_dir, user_id);
         let db = flowy_database::init(&dir).map_err(|e| {
             log::error!("init user db failed, {:?}, user_id: {}", e, user_id);
-            ErrorBuilder::new(ErrorCode::UserDatabaseInitFailed).error(e).build()
+            UserError::internal().context(e)
         })?;
 
         match DB_MAP.try_write_for(Duration::from_millis(300)) {
-            None => Err(ErrorBuilder::new(ErrorCode::AcquireWriteLockedFailed)
-                .msg(format!("Open user db failed"))
-                .build()),
+            None => Err(UserError::internal().context(format!("Acquire write lock to save user db failed"))),
             Some(mut write_guard) => {
                 write_guard.insert(user_id.to_owned(), db);
                 Ok(())
@@ -41,9 +39,7 @@ impl UserDB {
 
     pub(crate) fn close_user_db(&self, user_id: &str) -> Result<(), UserError> {
         match DB_MAP.try_write_for(Duration::from_millis(300)) {
-            None => Err(ErrorBuilder::new(ErrorCode::AcquireWriteLockedFailed)
-                .msg(format!("Close user db failed"))
-                .build()),
+            None => Err(UserError::internal().context(format!("Acquire write lock to close user db failed"))),
             Some(mut write_guard) => {
                 set_user_db_init(false, user_id);
                 write_guard.remove(user_id);
@@ -71,13 +67,9 @@ impl UserDB {
         }
 
         match DB_MAP.try_read_for(Duration::from_millis(300)) {
-            None => Err(ErrorBuilder::new(ErrorCode::AcquireReadLockedFailed)
-                .msg(format!("Read user db failed"))
-                .build()),
+            None => Err(UserError::internal().context(format!("Acquire read lock to read user db failed"))),
             Some(read_guard) => match read_guard.get(user_id) {
-                None => Err(ErrorBuilder::new(ErrorCode::UserDatabaseInitFailed)
-                    .msg("Get connection failed. The database is not initialization")
-                    .build()),
+                None => Err(UserError::internal().context("Get connection failed. The database is not initialization")),
                 Some(database) => Ok(database.get_pool()),
             },
         }

+ 2 - 2
rust-lib/flowy-user/src/services/user/user_session.rs

@@ -1,6 +1,6 @@
 use crate::{
     entities::{SignInParams, SignUpParams, UpdateUserParams, UserProfile},
-    errors::{ErrorBuilder, ErrorCode, UserError},
+    errors::{ErrorCode, UserError},
     services::user::database::UserDB,
     sql_tables::{UserTable, UserTableChangeset},
 };
@@ -214,7 +214,7 @@ impl UserSession {
         }
 
         match session {
-            None => Err(ErrorBuilder::new(ErrorCode::UserUnauthorized).build()),
+            None => Err(UserError::unauthorized()),
             Some(session) => Ok(session),
         }
     }

+ 3 - 4
rust-lib/flowy-workspace/src/entities/app/app_create.rs

@@ -51,12 +51,11 @@ impl TryInto<CreateAppParams> for CreateAppRequest {
     type Error = WorkspaceError;
 
     fn try_into(self) -> Result<CreateAppParams, Self::Error> {
-        let name = AppName::parse(self.name).map_err(|e| ErrorBuilder::new(ErrorCode::AppNameInvalid).msg(e).build())?;
+        let name = AppName::parse(self.name).map_err(|e| WorkspaceError::app_name().context(e))?;
 
-        let id = WorkspaceId::parse(self.workspace_id).map_err(|e| ErrorBuilder::new(ErrorCode::WorkspaceIdInvalid).msg(e).build())?;
+        let id = WorkspaceId::parse(self.workspace_id).map_err(|e| WorkspaceError::workspace_id().context(e))?;
 
-        let color_style =
-            AppColorStyle::parse(self.color_style).map_err(|e| ErrorBuilder::new(ErrorCode::AppColorStyleInvalid).msg(e).build())?;
+        let color_style = AppColorStyle::parse(self.color_style).map_err(|e| WorkspaceError::color_style().context(e))?;
 
         Ok(CreateAppParams {
             workspace_id: id.0,

+ 2 - 7
rust-lib/flowy-workspace/src/entities/app/app_delete.rs

@@ -1,7 +1,4 @@
-use crate::{
-    entities::app::parser::AppId,
-    errors::{ErrorBuilder, ErrorCode, WorkspaceError},
-};
+use crate::{entities::app::parser::AppId, errors::WorkspaceError};
 use flowy_derive::ProtoBuf;
 use std::convert::TryInto;
 
@@ -21,9 +18,7 @@ impl TryInto<DeleteAppParams> for DeleteAppRequest {
     type Error = WorkspaceError;
 
     fn try_into(self) -> Result<DeleteAppParams, Self::Error> {
-        let app_id = AppId::parse(self.app_id)
-            .map_err(|e| ErrorBuilder::new(ErrorCode::AppIdInvalid).msg(e).build())?
-            .0;
+        let app_id = AppId::parse(self.app_id).map_err(|e| WorkspaceError::app_id().context(e))?.0;
 
         Ok(DeleteAppParams { app_id })
     }

+ 1 - 3
rust-lib/flowy-workspace/src/entities/app/app_query.rs

@@ -69,9 +69,7 @@ impl TryInto<QueryAppParams> for QueryAppRequest {
     type Error = WorkspaceError;
 
     fn try_into(self) -> Result<QueryAppParams, Self::Error> {
-        let app_id = AppId::parse(self.app_id)
-            .map_err(|e| ErrorBuilder::new(ErrorCode::AppIdInvalid).msg(e).build())?
-            .0;
+        let app_id = AppId::parse(self.app_id).map_err(|e| WorkspaceError::app_id().context(e))?.0;
 
         Ok(QueryAppParams {
             app_id,

+ 4 - 10
rust-lib/flowy-workspace/src/entities/app/app_update.rs

@@ -3,7 +3,7 @@ use crate::{
         parser::{AppColorStyle, AppId, AppName},
         ColorStyle,
     },
-    errors::{ErrorBuilder, ErrorCode, WorkspaceError},
+    errors::WorkspaceError,
 };
 use flowy_derive::ProtoBuf;
 use std::convert::TryInto;
@@ -72,24 +72,18 @@ impl TryInto<UpdateAppParams> for UpdateAppRequest {
     type Error = WorkspaceError;
 
     fn try_into(self) -> Result<UpdateAppParams, Self::Error> {
-        let app_id = AppId::parse(self.app_id)
-            .map_err(|e| ErrorBuilder::new(ErrorCode::AppIdInvalid).msg(e).build())?
-            .0;
+        let app_id = AppId::parse(self.app_id).map_err(|e| WorkspaceError::app_id().context(e))?.0;
 
         let name = match self.name {
             None => None,
-            Some(name) => Some(
-                AppName::parse(name)
-                    .map_err(|e| ErrorBuilder::new(ErrorCode::WorkspaceNameInvalid).msg(e).build())?
-                    .0,
-            ),
+            Some(name) => Some(AppName::parse(name).map_err(|e| WorkspaceError::workspace_name().context(e))?.0),
         };
 
         let color_style = match self.color_style {
             None => None,
             Some(color_style) => Some(
                 AppColorStyle::parse(color_style)
-                    .map_err(|e| ErrorBuilder::new(ErrorCode::AppColorStyleInvalid).msg(e).build())?
+                    .map_err(|e| WorkspaceError::color_style().context(e))?
                     .0,
             ),
         };

+ 0 - 2
rust-lib/flowy-workspace/src/entities/view/parser/delta_data.rs

@@ -1,5 +1,3 @@
-use flowy_ot::core::Delta;
-
 #[derive(Debug)]
 pub struct DeltaData(pub Vec<u8>);
 

+ 4 - 8
rust-lib/flowy-workspace/src/entities/view/view_create.rs

@@ -1,6 +1,6 @@
 use crate::{
     entities::{app::parser::AppId, view::parser::*},
-    errors::{ErrorBuilder, ErrorCode, WorkspaceError},
+    errors::WorkspaceError,
     impl_def_and_def_mut,
 };
 use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
@@ -88,19 +88,15 @@ impl TryInto<CreateViewParams> for CreateViewRequest {
     type Error = WorkspaceError;
 
     fn try_into(self) -> Result<CreateViewParams, Self::Error> {
-        let name = ViewName::parse(self.name)
-            .map_err(|e| ErrorBuilder::new(ErrorCode::ViewNameInvalid).msg(e).build())?
-            .0;
+        let name = ViewName::parse(self.name).map_err(|e| WorkspaceError::view_name().context(e))?.0;
 
-        let belong_to_id = AppId::parse(self.belong_to_id)
-            .map_err(|e| ErrorBuilder::new(ErrorCode::AppIdInvalid).msg(e).build())?
-            .0;
+        let belong_to_id = AppId::parse(self.belong_to_id).map_err(|e| WorkspaceError::app_id().context(e))?.0;
 
         let thumbnail = match self.thumbnail {
             None => "".to_string(),
             Some(thumbnail) => {
                 ViewThumbnail::parse(thumbnail)
-                    .map_err(|e| ErrorBuilder::new(ErrorCode::ViewThumbnailInvalid).msg(e).build())?
+                    .map_err(|e| WorkspaceError::view_thumbnail().context(e))?
                     .0
             },
         };

+ 2 - 7
rust-lib/flowy-workspace/src/entities/view/view_delete.rs

@@ -1,7 +1,4 @@
-use crate::{
-    entities::view::parser::ViewId,
-    errors::{ErrorBuilder, ErrorCode, WorkspaceError},
-};
+use crate::{entities::view::parser::ViewId, errors::WorkspaceError};
 use flowy_derive::ProtoBuf;
 use flowy_document::entities::doc::QueryDocParams;
 use std::convert::TryInto;
@@ -22,9 +19,7 @@ impl TryInto<DeleteViewParams> for DeleteViewRequest {
     type Error = WorkspaceError;
 
     fn try_into(self) -> Result<DeleteViewParams, Self::Error> {
-        let view_id = ViewId::parse(self.view_id)
-            .map_err(|e| ErrorBuilder::new(ErrorCode::ViewIdInvalid).msg(e).build())?
-            .0;
+        let view_id = ViewId::parse(self.view_id).map_err(|e| WorkspaceError::view_id().context(e))?.0;
 
         Ok(DeleteViewParams { view_id })
     }

+ 3 - 10
rust-lib/flowy-workspace/src/entities/view/view_query.rs

@@ -1,7 +1,4 @@
-use crate::{
-    entities::view::parser::ViewId,
-    errors::{ErrorBuilder, ErrorCode, WorkspaceError},
-};
+use crate::{entities::view::parser::ViewId, errors::WorkspaceError};
 use flowy_derive::ProtoBuf;
 use flowy_document::entities::doc::QueryDocParams;
 use std::convert::TryInto;
@@ -71,9 +68,7 @@ impl std::convert::Into<QueryDocParams> for QueryViewParams {
 impl TryInto<QueryViewParams> for QueryViewRequest {
     type Error = WorkspaceError;
     fn try_into(self) -> Result<QueryViewParams, Self::Error> {
-        let view_id = ViewId::parse(self.view_id)
-            .map_err(|e| ErrorBuilder::new(ErrorCode::ViewIdInvalid).msg(e).build())?
-            .0;
+        let view_id = ViewId::parse(self.view_id).map_err(|e| WorkspaceError::view_id().context(e))?.0;
 
         Ok(QueryViewParams {
             view_id,
@@ -93,9 +88,7 @@ impl std::convert::TryInto<QueryDocParams> for OpenViewRequest {
     type Error = WorkspaceError;
 
     fn try_into(self) -> Result<QueryDocParams, Self::Error> {
-        let view_id = ViewId::parse(self.view_id)
-            .map_err(|e| ErrorBuilder::new(ErrorCode::ViewIdInvalid).msg(e).build())?
-            .0;
+        let view_id = ViewId::parse(self.view_id).map_err(|e| WorkspaceError::view_id().context(e))?.0;
         Ok(QueryDocParams { doc_id: view_id })
     }
 }

+ 9 - 27
rust-lib/flowy-workspace/src/entities/view/view_update.rs

@@ -1,6 +1,6 @@
 use crate::{
     entities::view::parser::{ViewId, *},
-    errors::{ErrorBuilder, ErrorCode, WorkspaceError},
+    errors::WorkspaceError,
 };
 use flowy_derive::ProtoBuf;
 use flowy_document::entities::doc::{ApplyChangesetParams, SaveDocParams};
@@ -69,33 +69,23 @@ impl TryInto<UpdateViewParams> for UpdateViewRequest {
     type Error = WorkspaceError;
 
     fn try_into(self) -> Result<UpdateViewParams, Self::Error> {
-        let view_id = ViewId::parse(self.view_id)
-            .map_err(|e| ErrorBuilder::new(ErrorCode::ViewIdInvalid).msg(e).build())?
-            .0;
+        let view_id = ViewId::parse(self.view_id).map_err(|e| WorkspaceError::view_id().context(e))?.0;
 
         let name = match self.name {
             None => None,
-            Some(name) => Some(
-                ViewName::parse(name)
-                    .map_err(|e| ErrorBuilder::new(ErrorCode::ViewNameInvalid).msg(e).build())?
-                    .0,
-            ),
+            Some(name) => Some(ViewName::parse(name).map_err(|e| WorkspaceError::view_name().context(e))?.0),
         };
 
         let desc = match self.desc {
             None => None,
-            Some(desc) => Some(
-                ViewDesc::parse(desc)
-                    .map_err(|e| ErrorBuilder::new(ErrorCode::ViewDescInvalid).msg(e).build())?
-                    .0,
-            ),
+            Some(desc) => Some(ViewDesc::parse(desc).map_err(|e| WorkspaceError::view_desc().context(e))?.0),
         };
 
         let thumbnail = match self.thumbnail {
             None => None,
             Some(thumbnail) => Some(
                 ViewThumbnail::parse(thumbnail)
-                    .map_err(|e| ErrorBuilder::new(ErrorCode::ViewThumbnailInvalid).msg(e).build())?
+                    .map_err(|e| WorkspaceError::view_thumbnail().context(e))?
                     .0,
             ),
         };
@@ -123,14 +113,10 @@ impl TryInto<SaveDocParams> for SaveViewDataRequest {
     type Error = WorkspaceError;
 
     fn try_into(self) -> Result<SaveDocParams, Self::Error> {
-        let view_id = ViewId::parse(self.view_id)
-            .map_err(|e| ErrorBuilder::new(ErrorCode::ViewIdInvalid).msg(e).build())?
-            .0;
+        let view_id = ViewId::parse(self.view_id).map_err(|e| WorkspaceError::view_id().context(e))?.0;
 
         // Opti: Vec<u8> -> Delta -> Vec<u8>
-        let data = DeltaData::parse(self.data)
-            .map_err(|e| ErrorBuilder::new(ErrorCode::ViewDataInvalid).msg(e).build())?
-            .0;
+        let data = DeltaData::parse(self.data).map_err(|e| WorkspaceError::view_data().context(e))?.0;
 
         Ok(SaveDocParams { id: view_id, data })
     }
@@ -149,14 +135,10 @@ impl TryInto<ApplyChangesetParams> for ApplyChangesetRequest {
     type Error = WorkspaceError;
 
     fn try_into(self) -> Result<ApplyChangesetParams, Self::Error> {
-        let view_id = ViewId::parse(self.view_id)
-            .map_err(|e| ErrorBuilder::new(ErrorCode::ViewIdInvalid).msg(e).build())?
-            .0;
+        let view_id = ViewId::parse(self.view_id).map_err(|e| WorkspaceError::view_id().context(e))?.0;
 
         // Opti: Vec<u8> -> Delta -> Vec<u8>
-        let data = DeltaData::parse(self.data)
-            .map_err(|e| ErrorBuilder::new(ErrorCode::ViewDataInvalid).msg(e).build())?
-            .0;
+        let data = DeltaData::parse(self.data).map_err(|e| WorkspaceError::view_data().context(e))?.0;
 
         Ok(ApplyChangesetParams { id: view_id, data })
     }

+ 2 - 2
rust-lib/flowy-workspace/src/entities/workspace/workspace_create.rs

@@ -28,8 +28,8 @@ impl TryInto<CreateWorkspaceParams> for CreateWorkspaceRequest {
     type Error = WorkspaceError;
 
     fn try_into(self) -> Result<CreateWorkspaceParams, Self::Error> {
-        let name = WorkspaceName::parse(self.name).map_err(|e| ErrorBuilder::new(ErrorCode::WorkspaceNameInvalid).msg(e).build())?;
-        let desc = WorkspaceDesc::parse(self.desc).map_err(|e| ErrorBuilder::new(ErrorCode::WorkspaceDescInvalid).msg(e).build())?;
+        let name = WorkspaceName::parse(self.name).map_err(|e| WorkspaceError::workspace_name().context(e))?;
+        let desc = WorkspaceDesc::parse(self.desc).map_err(|e| WorkspaceError::workspace_desc().context(e))?;
 
         Ok(CreateWorkspaceParams {
             name: name.0,

+ 2 - 5
rust-lib/flowy-workspace/src/entities/workspace/workspace_delete.rs

@@ -1,7 +1,4 @@
-use crate::{
-    entities::workspace::parser::WorkspaceId,
-    errors::{ErrorBuilder, ErrorCode, WorkspaceError},
-};
+use crate::{entities::workspace::parser::WorkspaceId, errors::WorkspaceError};
 use flowy_derive::ProtoBuf;
 use std::convert::TryInto;
 
@@ -22,7 +19,7 @@ impl TryInto<DeleteWorkspaceParams> for DeleteWorkspaceRequest {
 
     fn try_into(self) -> Result<DeleteWorkspaceParams, Self::Error> {
         let workspace_id = WorkspaceId::parse(self.workspace_id)
-            .map_err(|e| ErrorBuilder::new(ErrorCode::WorkspaceIdInvalid).msg(e).build())?
+            .map_err(|e| WorkspaceError::workspace_id().context(e))?
             .0;
 
         Ok(DeleteWorkspaceParams { workspace_id })

+ 1 - 1
rust-lib/flowy-workspace/src/entities/workspace/workspace_query.rs

@@ -47,7 +47,7 @@ impl TryInto<QueryWorkspaceParams> for QueryWorkspaceRequest {
             None => None,
             Some(workspace_id) => Some(
                 WorkspaceId::parse(workspace_id)
-                    .map_err(|e| ErrorBuilder::new(ErrorCode::WorkspaceIdInvalid).msg(e).build())?
+                    .map_err(|e| WorkspaceError::workspace_id().context(e))?
                     .0,
             ),
         };

+ 2 - 2
rust-lib/flowy-workspace/src/entities/workspace/workspace_update.rs

@@ -36,12 +36,12 @@ impl TryInto<UpdateWorkspaceParams> for UpdateWorkspaceRequest {
             None => None,
             Some(name) => Some(
                 WorkspaceName::parse(name)
-                    .map_err(|e| ErrorBuilder::new(ErrorCode::WorkspaceNameInvalid).msg(e).build())?
+                    .map_err(|e| WorkspaceError::workspace_name().context(e))?
                     .0,
             ),
         };
 
-        let id = WorkspaceId::parse(self.id).map_err(|e| ErrorBuilder::new(ErrorCode::WorkspaceIdInvalid).msg(e).build())?;
+        let id = WorkspaceId::parse(self.id).map_err(|e| WorkspaceError::workspace_id().context(e))?;
 
         Ok(UpdateWorkspaceParams {
             id: id.0,

+ 42 - 28
rust-lib/flowy-workspace/src/errors.rs

@@ -4,7 +4,7 @@ use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
 use flowy_dispatch::prelude::{EventResponse, ResponseBuilder};
 use flowy_document::errors::DocError;
 use flowy_net::errors::ErrorCode as ServerErrorCode;
-use std::{convert::TryInto, fmt};
+use std::{convert::TryInto, fmt, fmt::Debug};
 
 #[derive(Debug, Default, Clone, ProtoBuf)]
 pub struct WorkspaceError {
@@ -15,29 +15,55 @@ pub struct WorkspaceError {
     pub msg: String,
 }
 
+macro_rules! static_workspace_error {
+    ($name:ident, $status:expr) => {
+        #[allow(non_snake_case, missing_docs)]
+        pub fn $name() -> WorkspaceError {
+            WorkspaceError {
+                code: $status,
+                msg: format!("{}", $status),
+            }
+        }
+    };
+}
+
 impl WorkspaceError {
     pub fn new(code: ErrorCode, msg: &str) -> Self { Self { code, msg: msg.to_owned() } }
+
+    static_workspace_error!(workspace_name, ErrorCode::WorkspaceNameInvalid);
+    static_workspace_error!(workspace_id, ErrorCode::WorkspaceIdInvalid);
+    static_workspace_error!(color_style, ErrorCode::AppColorStyleInvalid);
+    static_workspace_error!(workspace_desc, ErrorCode::WorkspaceDescInvalid);
+    static_workspace_error!(app_name, ErrorCode::AppNameInvalid);
+    static_workspace_error!(app_id, ErrorCode::AppIdInvalid);
+    static_workspace_error!(view_name, ErrorCode::ViewNameInvalid);
+    static_workspace_error!(view_thumbnail, ErrorCode::ViewThumbnailInvalid);
+    static_workspace_error!(view_id, ErrorCode::ViewIdInvalid);
+    static_workspace_error!(view_desc, ErrorCode::ViewDescInvalid);
+    static_workspace_error!(view_data, ErrorCode::ViewDataInvalid);
+    static_workspace_error!(unauthorized, ErrorCode::UserUnauthorized);
+    static_workspace_error!(internal, ErrorCode::InternalError);
+    static_workspace_error!(not_found, ErrorCode::RecordNotFound);
+
+    pub fn context<T: Debug>(mut self, error: T) -> Self {
+        self.msg = format!("{:?}", error);
+        self
+    }
 }
 
 #[derive(Debug, Clone, ProtoBuf_Enum, Display, PartialEq, Eq)]
 pub enum ErrorCode {
-    #[display(fmt = "Unknown")]
-    Unknown              = 0,
-
     #[display(fmt = "Workspace name is invalid")]
-    WorkspaceNameInvalid = 1,
+    WorkspaceNameInvalid = 0,
 
     #[display(fmt = "Workspace id is invalid")]
-    WorkspaceIdInvalid   = 2,
+    WorkspaceIdInvalid   = 1,
 
     #[display(fmt = "Color style of the App is invalid")]
-    AppColorStyleInvalid = 3,
+    AppColorStyleInvalid = 2,
 
     #[display(fmt = "Workspace desc is invalid")]
-    WorkspaceDescInvalid = 4,
-
-    #[display(fmt = "Current workspace not found")]
-    CurrentWorkspaceNotFound = 5,
+    WorkspaceDescInvalid = 3,
 
     #[display(fmt = "Id of the App  is invalid")]
     AppIdInvalid         = 10,
@@ -60,11 +86,8 @@ pub enum ErrorCode {
     #[display(fmt = "View data is invalid")]
     ViewDataInvalid      = 24,
 
-    #[display(fmt = "UserIn is empty")]
-    UserIdIsEmpty        = 100,
-
     #[display(fmt = "User unauthorized")]
-    UserUnauthorized     = 101,
+    UserUnauthorized     = 100,
 
     #[display(fmt = "Server error")]
     InternalError        = 1000,
@@ -73,22 +96,22 @@ pub enum ErrorCode {
 }
 
 impl std::default::Default for ErrorCode {
-    fn default() -> Self { ErrorCode::Unknown }
+    fn default() -> Self { ErrorCode::InternalError }
 }
 
 impl std::convert::From<flowy_document::errors::DocError> for WorkspaceError {
-    fn from(error: DocError) -> Self { ErrorBuilder::new(ErrorCode::InternalError).error(error).build() }
+    fn from(error: DocError) -> Self { WorkspaceError::internal().context(error) }
 }
 
 impl std::convert::From<flowy_net::errors::ServerError> for WorkspaceError {
     fn from(error: flowy_net::errors::ServerError) -> Self {
         let code = server_error_to_workspace_error(error.code);
-        ErrorBuilder::new(code).error(error.msg).build()
+        WorkspaceError::new(code, &error.msg)
     }
 }
 
 impl std::convert::From<flowy_database::Error> for WorkspaceError {
-    fn from(error: flowy_database::Error) -> Self { ErrorBuilder::new(ErrorCode::InternalError).error(error).build() }
+    fn from(error: flowy_database::Error) -> Self { WorkspaceError::internal().context(error) }
 }
 
 impl flowy_dispatch::Error for WorkspaceError {
@@ -102,15 +125,6 @@ impl fmt::Display for WorkspaceError {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{:?}: {}", &self.code, &self.msg) }
 }
 
-pub type ErrorBuilder = flowy_infra::errors::Builder<ErrorCode, WorkspaceError>;
-
-impl flowy_infra::errors::Build<ErrorCode> for WorkspaceError {
-    fn build(code: ErrorCode, msg: String) -> Self {
-        let msg = if msg.is_empty() { format!("{}", code) } else { msg };
-        WorkspaceError::new(code, &msg)
-    }
-}
-
 fn server_error_to_workspace_error(code: ServerErrorCode) -> ErrorCode {
     match code {
         ServerErrorCode::UserUnauthorized => ErrorCode::UserUnauthorized,

+ 2 - 4
rust-lib/flowy-workspace/src/module.rs

@@ -1,5 +1,5 @@
 use crate::{
-    errors::{ErrorBuilder, ErrorCode, WorkspaceError},
+    errors::WorkspaceError,
     event::WorkspaceEvent,
     handlers::*,
     services::{server::construct_workspace_server, AppController, ViewController, WorkspaceController},
@@ -22,9 +22,7 @@ pub trait WorkspaceDatabase: Send + Sync {
 
     fn db_connection(&self) -> Result<DBConnection, WorkspaceError> {
         let pool = self.db_pool()?;
-        let conn = pool
-            .get()
-            .map_err(|e| ErrorBuilder::new(ErrorCode::InternalError).error(e).build())?;
+        let conn = pool.get().map_err(|e| WorkspaceError::internal().context(e))?;
         Ok(conn)
     }
 }

+ 0 - 2
rust-lib/flowy-workspace/src/protobuf/mod.rs

@@ -1,4 +1,2 @@
-
 mod model;
 pub use model::*;
-        

+ 57 - 74
rust-lib/flowy-workspace/src/protobuf/model/errors.rs

@@ -51,7 +51,7 @@ impl WorkspaceError {
         self.code
     }
     pub fn clear_code(&mut self) {
-        self.code = ErrorCode::Unknown;
+        self.code = ErrorCode::WorkspaceNameInvalid;
     }
 
     // Param is passed by value, moved
@@ -113,7 +113,7 @@ impl ::protobuf::Message for WorkspaceError {
     #[allow(unused_variables)]
     fn compute_size(&self) -> u32 {
         let mut my_size = 0;
-        if self.code != ErrorCode::Unknown {
+        if self.code != ErrorCode::WorkspaceNameInvalid {
             my_size += ::protobuf::rt::enum_size(1, self.code);
         }
         if !self.msg.is_empty() {
@@ -125,7 +125,7 @@ impl ::protobuf::Message for WorkspaceError {
     }
 
     fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::ProtobufResult<()> {
-        if self.code != ErrorCode::Unknown {
+        if self.code != ErrorCode::WorkspaceNameInvalid {
             os.write_enum(1, ::protobuf::ProtobufEnum::value(&self.code))?;
         }
         if !self.msg.is_empty() {
@@ -195,7 +195,7 @@ impl ::protobuf::Message for WorkspaceError {
 
 impl ::protobuf::Clear for WorkspaceError {
     fn clear(&mut self) {
-        self.code = ErrorCode::Unknown;
+        self.code = ErrorCode::WorkspaceNameInvalid;
         self.msg.clear();
         self.unknown_fields.clear();
     }
@@ -215,12 +215,10 @@ impl ::protobuf::reflect::ProtobufValue for WorkspaceError {
 
 #[derive(Clone,PartialEq,Eq,Debug,Hash)]
 pub enum ErrorCode {
-    Unknown = 0,
-    WorkspaceNameInvalid = 1,
-    WorkspaceIdInvalid = 2,
-    AppColorStyleInvalid = 3,
-    WorkspaceDescInvalid = 4,
-    CurrentWorkspaceNotFound = 5,
+    WorkspaceNameInvalid = 0,
+    WorkspaceIdInvalid = 1,
+    AppColorStyleInvalid = 2,
+    WorkspaceDescInvalid = 3,
     AppIdInvalid = 10,
     AppNameInvalid = 11,
     ViewNameInvalid = 20,
@@ -228,8 +226,7 @@ pub enum ErrorCode {
     ViewIdInvalid = 22,
     ViewDescInvalid = 23,
     ViewDataInvalid = 24,
-    UserIdIsEmpty = 100,
-    UserUnauthorized = 101,
+    UserUnauthorized = 100,
     InternalError = 1000,
     RecordNotFound = 1001,
 }
@@ -241,12 +238,10 @@ impl ::protobuf::ProtobufEnum for ErrorCode {
 
     fn from_i32(value: i32) -> ::std::option::Option<ErrorCode> {
         match value {
-            0 => ::std::option::Option::Some(ErrorCode::Unknown),
-            1 => ::std::option::Option::Some(ErrorCode::WorkspaceNameInvalid),
-            2 => ::std::option::Option::Some(ErrorCode::WorkspaceIdInvalid),
-            3 => ::std::option::Option::Some(ErrorCode::AppColorStyleInvalid),
-            4 => ::std::option::Option::Some(ErrorCode::WorkspaceDescInvalid),
-            5 => ::std::option::Option::Some(ErrorCode::CurrentWorkspaceNotFound),
+            0 => ::std::option::Option::Some(ErrorCode::WorkspaceNameInvalid),
+            1 => ::std::option::Option::Some(ErrorCode::WorkspaceIdInvalid),
+            2 => ::std::option::Option::Some(ErrorCode::AppColorStyleInvalid),
+            3 => ::std::option::Option::Some(ErrorCode::WorkspaceDescInvalid),
             10 => ::std::option::Option::Some(ErrorCode::AppIdInvalid),
             11 => ::std::option::Option::Some(ErrorCode::AppNameInvalid),
             20 => ::std::option::Option::Some(ErrorCode::ViewNameInvalid),
@@ -254,8 +249,7 @@ impl ::protobuf::ProtobufEnum for ErrorCode {
             22 => ::std::option::Option::Some(ErrorCode::ViewIdInvalid),
             23 => ::std::option::Option::Some(ErrorCode::ViewDescInvalid),
             24 => ::std::option::Option::Some(ErrorCode::ViewDataInvalid),
-            100 => ::std::option::Option::Some(ErrorCode::UserIdIsEmpty),
-            101 => ::std::option::Option::Some(ErrorCode::UserUnauthorized),
+            100 => ::std::option::Option::Some(ErrorCode::UserUnauthorized),
             1000 => ::std::option::Option::Some(ErrorCode::InternalError),
             1001 => ::std::option::Option::Some(ErrorCode::RecordNotFound),
             _ => ::std::option::Option::None
@@ -264,12 +258,10 @@ impl ::protobuf::ProtobufEnum for ErrorCode {
 
     fn values() -> &'static [Self] {
         static values: &'static [ErrorCode] = &[
-            ErrorCode::Unknown,
             ErrorCode::WorkspaceNameInvalid,
             ErrorCode::WorkspaceIdInvalid,
             ErrorCode::AppColorStyleInvalid,
             ErrorCode::WorkspaceDescInvalid,
-            ErrorCode::CurrentWorkspaceNotFound,
             ErrorCode::AppIdInvalid,
             ErrorCode::AppNameInvalid,
             ErrorCode::ViewNameInvalid,
@@ -277,7 +269,6 @@ impl ::protobuf::ProtobufEnum for ErrorCode {
             ErrorCode::ViewIdInvalid,
             ErrorCode::ViewDescInvalid,
             ErrorCode::ViewDataInvalid,
-            ErrorCode::UserIdIsEmpty,
             ErrorCode::UserUnauthorized,
             ErrorCode::InternalError,
             ErrorCode::RecordNotFound,
@@ -298,7 +289,7 @@ impl ::std::marker::Copy for ErrorCode {
 
 impl ::std::default::Default for ErrorCode {
     fn default() -> Self {
-        ErrorCode::Unknown
+        ErrorCode::WorkspaceNameInvalid
     }
 }
 
@@ -311,59 +302,51 @@ impl ::protobuf::reflect::ProtobufValue for ErrorCode {
 static file_descriptor_proto_data: &'static [u8] = b"\
     \n\x0cerrors.proto\"B\n\x0eWorkspaceError\x12\x1e\n\x04code\x18\x01\x20\
     \x01(\x0e2\n.ErrorCodeR\x04code\x12\x10\n\x03msg\x18\x02\x20\x01(\tR\x03\
-    msg*\x80\x03\n\tErrorCode\x12\x0b\n\x07Unknown\x10\0\x12\x18\n\x14Worksp\
-    aceNameInvalid\x10\x01\x12\x16\n\x12WorkspaceIdInvalid\x10\x02\x12\x18\n\
-    \x14AppColorStyleInvalid\x10\x03\x12\x18\n\x14WorkspaceDescInvalid\x10\
-    \x04\x12\x1c\n\x18CurrentWorkspaceNotFound\x10\x05\x12\x10\n\x0cAppIdInv\
+    msg*\xc2\x02\n\tErrorCode\x12\x18\n\x14WorkspaceNameInvalid\x10\0\x12\
+    \x16\n\x12WorkspaceIdInvalid\x10\x01\x12\x18\n\x14AppColorStyleInvalid\
+    \x10\x02\x12\x18\n\x14WorkspaceDescInvalid\x10\x03\x12\x10\n\x0cAppIdInv\
     alid\x10\n\x12\x12\n\x0eAppNameInvalid\x10\x0b\x12\x13\n\x0fViewNameInva\
     lid\x10\x14\x12\x18\n\x14ViewThumbnailInvalid\x10\x15\x12\x11\n\rViewIdI\
     nvalid\x10\x16\x12\x13\n\x0fViewDescInvalid\x10\x17\x12\x13\n\x0fViewDat\
-    aInvalid\x10\x18\x12\x11\n\rUserIdIsEmpty\x10d\x12\x14\n\x10UserUnauthor\
-    ized\x10e\x12\x12\n\rInternalError\x10\xe8\x07\x12\x13\n\x0eRecordNotFou\
-    nd\x10\xe9\x07J\xe9\x06\n\x06\x12\x04\0\0\x18\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\x16\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\
-    \x18\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\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\x1d\n\x0c\n\x05\x05\0\x02\x01\x01\x12\x03\x08\x04\x18\n\
-    \x0c\n\x05\x05\0\x02\x01\x02\x12\x03\x08\x1b\x1c\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\x1d\n\x0c\n\x05\x05\0\x02\x03\x01\x12\x03\n\x04\x18\n\x0c\
-    \n\x05\x05\0\x02\x03\x02\x12\x03\n\x1b\x1c\n\x0b\n\x04\x05\0\x02\x04\x12\
-    \x03\x0b\x04\x1d\n\x0c\n\x05\x05\0\x02\x04\x01\x12\x03\x0b\x04\x18\n\x0c\
-    \n\x05\x05\0\x02\x04\x02\x12\x03\x0b\x1b\x1c\n\x0b\n\x04\x05\0\x02\x05\
-    \x12\x03\x0c\x04!\n\x0c\n\x05\x05\0\x02\x05\x01\x12\x03\x0c\x04\x1c\n\
-    \x0c\n\x05\x05\0\x02\x05\x02\x12\x03\x0c\x1f\x20\n\x0b\n\x04\x05\0\x02\
-    \x06\x12\x03\r\x04\x16\n\x0c\n\x05\x05\0\x02\x06\x01\x12\x03\r\x04\x10\n\
-    \x0c\n\x05\x05\0\x02\x06\x02\x12\x03\r\x13\x15\n\x0b\n\x04\x05\0\x02\x07\
-    \x12\x03\x0e\x04\x18\n\x0c\n\x05\x05\0\x02\x07\x01\x12\x03\x0e\x04\x12\n\
-    \x0c\n\x05\x05\0\x02\x07\x02\x12\x03\x0e\x15\x17\n\x0b\n\x04\x05\0\x02\
-    \x08\x12\x03\x0f\x04\x19\n\x0c\n\x05\x05\0\x02\x08\x01\x12\x03\x0f\x04\
-    \x13\n\x0c\n\x05\x05\0\x02\x08\x02\x12\x03\x0f\x16\x18\n\x0b\n\x04\x05\0\
-    \x02\t\x12\x03\x10\x04\x1e\n\x0c\n\x05\x05\0\x02\t\x01\x12\x03\x10\x04\
-    \x18\n\x0c\n\x05\x05\0\x02\t\x02\x12\x03\x10\x1b\x1d\n\x0b\n\x04\x05\0\
-    \x02\n\x12\x03\x11\x04\x17\n\x0c\n\x05\x05\0\x02\n\x01\x12\x03\x11\x04\
-    \x11\n\x0c\n\x05\x05\0\x02\n\x02\x12\x03\x11\x14\x16\n\x0b\n\x04\x05\0\
-    \x02\x0b\x12\x03\x12\x04\x19\n\x0c\n\x05\x05\0\x02\x0b\x01\x12\x03\x12\
-    \x04\x13\n\x0c\n\x05\x05\0\x02\x0b\x02\x12\x03\x12\x16\x18\n\x0b\n\x04\
-    \x05\0\x02\x0c\x12\x03\x13\x04\x19\n\x0c\n\x05\x05\0\x02\x0c\x01\x12\x03\
-    \x13\x04\x13\n\x0c\n\x05\x05\0\x02\x0c\x02\x12\x03\x13\x16\x18\n\x0b\n\
-    \x04\x05\0\x02\r\x12\x03\x14\x04\x18\n\x0c\n\x05\x05\0\x02\r\x01\x12\x03\
-    \x14\x04\x11\n\x0c\n\x05\x05\0\x02\r\x02\x12\x03\x14\x14\x17\n\x0b\n\x04\
-    \x05\0\x02\x0e\x12\x03\x15\x04\x1b\n\x0c\n\x05\x05\0\x02\x0e\x01\x12\x03\
-    \x15\x04\x14\n\x0c\n\x05\x05\0\x02\x0e\x02\x12\x03\x15\x17\x1a\n\x0b\n\
-    \x04\x05\0\x02\x0f\x12\x03\x16\x04\x19\n\x0c\n\x05\x05\0\x02\x0f\x01\x12\
-    \x03\x16\x04\x11\n\x0c\n\x05\x05\0\x02\x0f\x02\x12\x03\x16\x14\x18\n\x0b\
-    \n\x04\x05\0\x02\x10\x12\x03\x17\x04\x1a\n\x0c\n\x05\x05\0\x02\x10\x01\
-    \x12\x03\x17\x04\x12\n\x0c\n\x05\x05\0\x02\x10\x02\x12\x03\x17\x15\x19b\
-    \x06proto3\
+    aInvalid\x10\x18\x12\x14\n\x10UserUnauthorized\x10d\x12\x12\n\rInternalE\
+    rror\x10\xe8\x07\x12\x13\n\x0eRecordNotFound\x10\xe9\x07J\xee\x05\n\x06\
+    \x12\x04\0\0\x15\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\x16\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\x15\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\x1d\n\x0c\n\
+    \x05\x05\0\x02\0\x01\x12\x03\x07\x04\x18\n\x0c\n\x05\x05\0\x02\0\x02\x12\
+    \x03\x07\x1b\x1c\n\x0b\n\x04\x05\0\x02\x01\x12\x03\x08\x04\x1b\n\x0c\n\
+    \x05\x05\0\x02\x01\x01\x12\x03\x08\x04\x16\n\x0c\n\x05\x05\0\x02\x01\x02\
+    \x12\x03\x08\x19\x1a\n\x0b\n\x04\x05\0\x02\x02\x12\x03\t\x04\x1d\n\x0c\n\
+    \x05\x05\0\x02\x02\x01\x12\x03\t\x04\x18\n\x0c\n\x05\x05\0\x02\x02\x02\
+    \x12\x03\t\x1b\x1c\n\x0b\n\x04\x05\0\x02\x03\x12\x03\n\x04\x1d\n\x0c\n\
+    \x05\x05\0\x02\x03\x01\x12\x03\n\x04\x18\n\x0c\n\x05\x05\0\x02\x03\x02\
+    \x12\x03\n\x1b\x1c\n\x0b\n\x04\x05\0\x02\x04\x12\x03\x0b\x04\x16\n\x0c\n\
+    \x05\x05\0\x02\x04\x01\x12\x03\x0b\x04\x10\n\x0c\n\x05\x05\0\x02\x04\x02\
+    \x12\x03\x0b\x13\x15\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\x19\n\
+    \x0c\n\x05\x05\0\x02\x06\x01\x12\x03\r\x04\x13\n\x0c\n\x05\x05\0\x02\x06\
+    \x02\x12\x03\r\x16\x18\n\x0b\n\x04\x05\0\x02\x07\x12\x03\x0e\x04\x1e\n\
+    \x0c\n\x05\x05\0\x02\x07\x01\x12\x03\x0e\x04\x18\n\x0c\n\x05\x05\0\x02\
+    \x07\x02\x12\x03\x0e\x1b\x1d\n\x0b\n\x04\x05\0\x02\x08\x12\x03\x0f\x04\
+    \x17\n\x0c\n\x05\x05\0\x02\x08\x01\x12\x03\x0f\x04\x11\n\x0c\n\x05\x05\0\
+    \x02\x08\x02\x12\x03\x0f\x14\x16\n\x0b\n\x04\x05\0\x02\t\x12\x03\x10\x04\
+    \x19\n\x0c\n\x05\x05\0\x02\t\x01\x12\x03\x10\x04\x13\n\x0c\n\x05\x05\0\
+    \x02\t\x02\x12\x03\x10\x16\x18\n\x0b\n\x04\x05\0\x02\n\x12\x03\x11\x04\
+    \x19\n\x0c\n\x05\x05\0\x02\n\x01\x12\x03\x11\x04\x13\n\x0c\n\x05\x05\0\
+    \x02\n\x02\x12\x03\x11\x16\x18\n\x0b\n\x04\x05\0\x02\x0b\x12\x03\x12\x04\
+    \x1b\n\x0c\n\x05\x05\0\x02\x0b\x01\x12\x03\x12\x04\x14\n\x0c\n\x05\x05\0\
+    \x02\x0b\x02\x12\x03\x12\x17\x1a\n\x0b\n\x04\x05\0\x02\x0c\x12\x03\x13\
+    \x04\x19\n\x0c\n\x05\x05\0\x02\x0c\x01\x12\x03\x13\x04\x11\n\x0c\n\x05\
+    \x05\0\x02\x0c\x02\x12\x03\x13\x14\x18\n\x0b\n\x04\x05\0\x02\r\x12\x03\
+    \x14\x04\x1a\n\x0c\n\x05\x05\0\x02\r\x01\x12\x03\x14\x04\x12\n\x0c\n\x05\
+    \x05\0\x02\r\x02\x12\x03\x14\x15\x19b\x06proto3\
 ";
 
 static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;

+ 33 - 33
rust-lib/flowy-workspace/src/protobuf/model/mod.rs

@@ -1,49 +1,49 @@
-// Auto-generated, do not edit 
+// Auto-generated, do not edit
 
-mod view_update; 
-pub use view_update::*; 
+mod view_update;
+pub use view_update::*;
 
-mod view_delete; 
-pub use view_delete::*; 
+mod view_delete;
+pub use view_delete::*;
 
-mod app_query; 
-pub use app_query::*; 
+mod app_query;
+pub use app_query::*;
 
-mod workspace_delete; 
-pub use workspace_delete::*; 
+mod workspace_delete;
+pub use workspace_delete::*;
 
-mod observable; 
-pub use observable::*; 
+mod observable;
+pub use observable::*;
 
-mod errors; 
-pub use errors::*; 
+mod errors;
+pub use errors::*;
 
-mod workspace_update; 
-pub use workspace_update::*; 
+mod workspace_update;
+pub use workspace_update::*;
 
-mod app_create; 
-pub use app_create::*; 
+mod app_create;
+pub use app_create::*;
 
-mod workspace_query; 
-pub use workspace_query::*; 
+mod workspace_query;
+pub use workspace_query::*;
 
-mod event; 
-pub use event::*; 
+mod event;
+pub use event::*;
 
-mod view_create; 
-pub use view_create::*; 
+mod view_create;
+pub use view_create::*;
 
-mod workspace_user_detail; 
-pub use workspace_user_detail::*; 
+mod workspace_user_detail;
+pub use workspace_user_detail::*;
 
-mod workspace_create; 
-pub use workspace_create::*; 
+mod workspace_create;
+pub use workspace_create::*;
 
-mod app_update; 
-pub use app_update::*; 
+mod app_update;
+pub use app_update::*;
 
-mod view_query; 
-pub use view_query::*; 
+mod view_query;
+pub use view_query::*;
 
-mod app_delete; 
-pub use app_delete::*; 
+mod app_delete;
+pub use app_delete::*;

+ 5 - 8
rust-lib/flowy-workspace/src/protobuf/proto/errors.proto

@@ -5,12 +5,10 @@ message WorkspaceError {
     string msg = 2;
 }
 enum ErrorCode {
-    Unknown = 0;
-    WorkspaceNameInvalid = 1;
-    WorkspaceIdInvalid = 2;
-    AppColorStyleInvalid = 3;
-    WorkspaceDescInvalid = 4;
-    CurrentWorkspaceNotFound = 5;
+    WorkspaceNameInvalid = 0;
+    WorkspaceIdInvalid = 1;
+    AppColorStyleInvalid = 2;
+    WorkspaceDescInvalid = 3;
     AppIdInvalid = 10;
     AppNameInvalid = 11;
     ViewNameInvalid = 20;
@@ -18,8 +16,7 @@ enum ErrorCode {
     ViewIdInvalid = 22;
     ViewDescInvalid = 23;
     ViewDataInvalid = 24;
-    UserIdIsEmpty = 100;
-    UserUnauthorized = 101;
+    UserUnauthorized = 100;
     InternalError = 1000;
     RecordNotFound = 1001;
 }

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

@@ -117,9 +117,7 @@ impl WorkspaceController {
             set_current_workspace(&workspace.id);
             Ok(workspace)
         } else {
-            return Err(ErrorBuilder::new(ErrorCode::WorkspaceIdInvalid)
-                .msg("Opened workspace id should not be empty")
-                .build());
+            return Err(WorkspaceError::workspace_id().context("Opened workspace id should not be empty"));
         }
     }
 
@@ -172,9 +170,9 @@ impl WorkspaceController {
 
     fn read_local_workspace(&self, workspace_id: String, user_id: &str, conn: &SqliteConnection) -> Result<Workspace, WorkspaceError> {
         // Opti: fetch single workspace from local db
-        let mut repeated_workspace = self.read_local_workspaces(Some(workspace_id), user_id, conn)?;
+        let mut repeated_workspace = self.read_local_workspaces(Some(workspace_id.clone()), user_id, conn)?;
         if repeated_workspace.is_empty() {
-            return Err(ErrorBuilder::new(ErrorCode::RecordNotFound).build());
+            return Err(WorkspaceError::not_found().context(format!("{} workspace not found", workspace_id)));
         }
 
         debug_assert_eq!(repeated_workspace.len(), 1);
@@ -294,7 +292,7 @@ fn set_current_workspace(workspace: &str) { KV::set_str(CURRENT_WORKSPACE_ID, wo
 
 fn get_current_workspace() -> Result<String, WorkspaceError> {
     match KV::get_str(CURRENT_WORKSPACE_ID) {
-        None => Err(ErrorBuilder::new(ErrorCode::CurrentWorkspaceNotFound).build()),
+        None => Err(WorkspaceError::not_found().context("Current workspace not found or should call open workspace first")),
         Some(workspace_id) => Ok(workspace_id),
     }
 }

+ 7 - 6
rust-lib/flowy-workspace/tests/workspace/view_test.rs

@@ -1,5 +1,6 @@
 use crate::helper::*;
 
+use flowy_ot::core::DeltaBuilder;
 use flowy_workspace::entities::view::*;
 
 #[test]
@@ -34,11 +35,10 @@ fn view_open_doc() {
 #[test]
 fn view_update_doc() {
     let test = ViewTest::new();
-
-    let new_data = "123";
+    let new_data = DeltaBuilder::new().insert("flutter ❤️ rust").build().into_bytes();
     let request = SaveViewDataRequest {
         view_id: test.view.id.clone(),
-        data: new_data.to_string(),
+        data: new_data.clone(),
     };
 
     update_view_data(&test.sdk, request);
@@ -47,16 +47,17 @@ fn view_update_doc() {
         view_id: test.view.id.clone(),
     };
     let doc = open_view(&test.sdk, request);
-    assert_eq!(&doc.data, new_data);
+    assert_eq!(doc.data, new_data);
 }
 
 #[test]
 fn view_update_big_doc() {
     let test = ViewTest::new();
-    let new_data = "flutter ❤️ rust".repeat(1000000);
+    let new_data = DeltaBuilder::new().insert(&"flutter ❤️ rust".repeat(1000000)).build().into_bytes();
+
     let request = SaveViewDataRequest {
         view_id: test.view.id.clone(),
-        data: new_data.to_string(),
+        data: new_data.clone(),
     };
 
     update_view_data(&test.sdk, request);