diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 6c89e47281..69bf0ed2a7 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -26,7 +26,6 @@ jobs: flutter channel stable flutter config --enable-macos-desktop flutter doctor - dart pub global activate protoc_plugin - name: Deps working-directory: frontend run: | @@ -68,7 +67,6 @@ jobs: flutter channel stable flutter config --enable-linux-desktop flutter doctor - dart pub global activate protoc_plugin - name: Deps working-directory: frontend run: | diff --git a/.github/workflows/frontend_dart.yml b/.github/workflows/dart_lint.yml similarity index 69% rename from .github/workflows/frontend_dart.yml rename to .github/workflows/dart_lint.yml index c2e8b6b2d0..c986aa1e16 100644 --- a/.github/workflows/frontend_dart.yml +++ b/.github/workflows/dart_lint.yml @@ -3,18 +3,13 @@ # separate terms of service, privacy policy, and support # documentation. -name: Frontend_Dart +name: DartLint on: push: branches: [ main ] - paths: - - 'frontend/app_flowy' pull_request: branches: [ main ] - paths: - - 'frontend/app_flowy' - env: @@ -29,10 +24,14 @@ jobs: uses: actions/checkout@v2 - uses: subosito/flutter-action@v1 with: - channel: "dev" - - name: flutter pub get - working-directory: frontend/app_flowy + channel: "stable" + - name: Flutter pub get run: flutter pub get + working-directory: frontend/app_flowy + - name: Generate language files + working-directory: frontend/app_flowy + run: + flutter pub run easy_localization:generate --source-dir ./assets/translations -f keys -O lib/generated -o locale_keys.g.dart - name: flutter analyze working-directory: frontend/app_flowy run: flutter analyze diff --git a/.github/workflows/frontend_rust.yml b/.github/workflows/rust_lint.yml similarity index 59% rename from .github/workflows/frontend_rust.yml rename to .github/workflows/rust_lint.yml index c334073507..23a24d1c06 100644 --- a/.github/workflows/frontend_rust.yml +++ b/.github/workflows/rust_lint.yml @@ -1,4 +1,4 @@ -name: Frontend_Rust +name: RustLint on: push: @@ -12,6 +12,7 @@ on: - 'frontend/rust-lib' - 'shared-lib' + env: CARGO_TERM_COLOR: always @@ -40,26 +41,10 @@ jobs: with: toolchain: stable override: true + - name: Install cargo-make + run: cargo install --force cargo-make + working-directory: frontend - run: rustup component add clippy working-directory: frontend/rust-lib - - run: cargo clippy - working-directory: frontend/rust-lib - - tests: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v2 - - name: Install Rust - run: | - curl \ - --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y - source $HOME/.cargo/env - rustup toolchain install stable - rustup default stable - - name: Frontend tests - working-directory: frontend/rust-lib - run: cargo test - - name: Shared-lib tests - working-directory: shared-lib - run: cargo test + - run: cargo clippy --no-default-features + working-directory: frontend/rust-lib \ No newline at end of file diff --git a/.github/workflows/rust_test.yml b/.github/workflows/rust_test.yml new file mode 100644 index 0000000000..a45f694196 --- /dev/null +++ b/.github/workflows/rust_test.yml @@ -0,0 +1,42 @@ +name: RustUnitTest + +on: + push: + branches: [ main ] +# paths: +# - 'frontend/rust-lib' +# - 'shared-lib' + pull_request: + branches: [ main ] +# paths: +# - 'frontend/rust-lib' +# - 'shared-lib' + +env: + CARGO_TERM_COLOR: always + +jobs: + tests: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + - name: Install Rust + run: | + curl \ + --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y + source $HOME/.cargo/env + rustup toolchain install stable + rustup default stable + - name: Install cargo-make + run: cargo install --force cargo-make + working-directory: frontend + - name: Install protobuf tool + run: brew install protobuf + working-directory: frontend + - name: RustLib tests + run: cargo test --no-default-features + working-directory: frontend/rust-lib + - name: Sharedlib tests + run: cargo test --no-default-features + working-directory: shared-lib diff --git a/.gitignore b/.gitignore index 517b5e2f75..b74dd0a47e 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,5 @@ package-lock.json yarn.lock node_modules +**/.proto_cache +**/.cache \ No newline at end of file diff --git a/frontend/Makefile.toml b/frontend/Makefile.toml index 7c90c54189..46f7279240 100644 --- a/frontend/Makefile.toml +++ b/frontend/Makefile.toml @@ -22,6 +22,7 @@ CRATE_TYPE = "staticlib" SDK_EXT = "a" APP_ENVIRONMENT = "local" FLUTTER_FLOWY_SDK_PATH="app_flowy/packages/flowy_sdk/lib/protobuf" +PROTOBUF_DERIVE_CACHE="../shared-lib/flowy-derive/src/derive_cache/derive_cache.rs" [env.development-mac] RUST_LOG = "trace" @@ -157,7 +158,7 @@ script_runner = "@duckscript" condition = { env_set = [ "FLUTTER_FLOWY_SDK_PATH"] } script = [ """ - cd ${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/rust-lib/dart-ffi + cd ${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/../shared-lib/error-code cargo build -vv """, ] diff --git a/frontend/app_flowy/lib/workspace/presentation/widgets/edit_pannel/edit_pannel.dart b/frontend/app_flowy/lib/workspace/presentation/widgets/edit_pannel/edit_pannel.dart index a81cd73c54..c55d405b76 100644 --- a/frontend/app_flowy/lib/workspace/presentation/widgets/edit_pannel/edit_pannel.dart +++ b/frontend/app_flowy/lib/workspace/presentation/widgets/edit_pannel/edit_pannel.dart @@ -24,7 +24,7 @@ class EditPannel extends StatelessWidget { @override Widget build(BuildContext context) { return Container( - color: Theme.of(context).colorScheme.primaryVariant, + color: Theme.of(context).colorScheme.secondary, child: BlocProvider( create: (context) => getIt(), child: BlocBuilder( diff --git a/frontend/app_flowy/packages/flowy_infra/lib/theme.dart b/frontend/app_flowy/packages/flowy_infra/lib/theme.dart index c29cd644ed..04b4a19fdb 100644 --- a/frontend/app_flowy/packages/flowy_infra/lib/theme.dart +++ b/frontend/app_flowy/packages/flowy_infra/lib/theme.dart @@ -161,9 +161,7 @@ class AppTheme { colorScheme: ColorScheme( brightness: isDark ? Brightness.dark : Brightness.light, primary: main1, - primaryVariant: main2, secondary: main2, - secondaryVariant: main2, background: surface, surface: surface, onBackground: surface, diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error-code/code.pb.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error-code/code.pb.dart new file mode 100644 index 0000000000..02ae41c056 --- /dev/null +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error-code/code.pb.dart @@ -0,0 +1,11 @@ +/// +// Generated code. Do not modify. +// source: code.proto +// +// @dart = 2.12 +// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields + +import 'dart:core' as $core; + +export 'code.pbenum.dart'; + diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error-code/code.pbenum.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error-code/code.pbenum.dart new file mode 100644 index 0000000000..dcf1e69936 --- /dev/null +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error-code/code.pbenum.dart @@ -0,0 +1,82 @@ +/// +// Generated code. Do not modify. +// source: code.proto +// +// @dart = 2.12 +// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields + +// ignore_for_file: UNDEFINED_SHOWN_NAME +import 'dart:core' as $core; +import 'package:protobuf/protobuf.dart' as $pb; + +class ErrorCode extends $pb.ProtobufEnum { + static const ErrorCode Internal = ErrorCode._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Internal'); + static const ErrorCode UserUnauthorized = ErrorCode._(2, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserUnauthorized'); + static const ErrorCode RecordNotFound = ErrorCode._(3, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'RecordNotFound'); + static const ErrorCode WorkspaceNameInvalid = ErrorCode._(100, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'WorkspaceNameInvalid'); + static const ErrorCode WorkspaceIdInvalid = ErrorCode._(101, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'WorkspaceIdInvalid'); + static const ErrorCode AppColorStyleInvalid = ErrorCode._(102, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'AppColorStyleInvalid'); + static const ErrorCode WorkspaceDescTooLong = ErrorCode._(103, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'WorkspaceDescTooLong'); + static const ErrorCode WorkspaceNameTooLong = ErrorCode._(104, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'WorkspaceNameTooLong'); + static const ErrorCode AppIdInvalid = ErrorCode._(110, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'AppIdInvalid'); + static const ErrorCode AppNameInvalid = ErrorCode._(111, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'AppNameInvalid'); + static const ErrorCode ViewNameInvalid = ErrorCode._(120, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ViewNameInvalid'); + static const ErrorCode ViewThumbnailInvalid = ErrorCode._(121, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ViewThumbnailInvalid'); + static const ErrorCode ViewIdInvalid = ErrorCode._(122, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ViewIdInvalid'); + static const ErrorCode ViewDescTooLong = ErrorCode._(123, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ViewDescTooLong'); + static const ErrorCode ViewDataInvalid = ErrorCode._(124, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ViewDataInvalid'); + static const ErrorCode ViewNameTooLong = ErrorCode._(125, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ViewNameTooLong'); + static const ErrorCode ConnectError = ErrorCode._(200, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ConnectError'); + static const ErrorCode EmailIsEmpty = ErrorCode._(300, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'EmailIsEmpty'); + static const ErrorCode EmailFormatInvalid = ErrorCode._(301, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'EmailFormatInvalid'); + static const ErrorCode EmailAlreadyExists = ErrorCode._(302, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'EmailAlreadyExists'); + static const ErrorCode PasswordIsEmpty = ErrorCode._(303, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'PasswordIsEmpty'); + static const ErrorCode PasswordTooLong = ErrorCode._(304, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'PasswordTooLong'); + static const ErrorCode PasswordContainsForbidCharacters = ErrorCode._(305, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'PasswordContainsForbidCharacters'); + static const ErrorCode PasswordFormatInvalid = ErrorCode._(306, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'PasswordFormatInvalid'); + static const ErrorCode PasswordNotMatch = ErrorCode._(307, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'PasswordNotMatch'); + static const ErrorCode UserNameTooLong = ErrorCode._(308, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserNameTooLong'); + static const ErrorCode UserNameContainForbiddenCharacters = ErrorCode._(309, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserNameContainForbiddenCharacters'); + static const ErrorCode UserNameIsEmpty = ErrorCode._(310, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserNameIsEmpty'); + static const ErrorCode UserIdInvalid = ErrorCode._(311, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserIdInvalid'); + static const ErrorCode UserNotExist = ErrorCode._(312, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserNotExist'); + + static const $core.List values = [ + Internal, + UserUnauthorized, + RecordNotFound, + WorkspaceNameInvalid, + WorkspaceIdInvalid, + AppColorStyleInvalid, + WorkspaceDescTooLong, + WorkspaceNameTooLong, + AppIdInvalid, + AppNameInvalid, + ViewNameInvalid, + ViewThumbnailInvalid, + ViewIdInvalid, + ViewDescTooLong, + ViewDataInvalid, + ViewNameTooLong, + ConnectError, + EmailIsEmpty, + EmailFormatInvalid, + EmailAlreadyExists, + PasswordIsEmpty, + PasswordTooLong, + PasswordContainsForbidCharacters, + PasswordFormatInvalid, + PasswordNotMatch, + UserNameTooLong, + UserNameContainForbiddenCharacters, + UserNameIsEmpty, + UserIdInvalid, + UserNotExist, + ]; + + static final $core.Map<$core.int, ErrorCode> _byValue = $pb.ProtobufEnum.initByValue(values); + static ErrorCode? valueOf($core.int value) => _byValue[value]; + + const ErrorCode._($core.int v, $core.String n) : super(v, n); +} + diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error-code/code.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error-code/code.pbjson.dart new file mode 100644 index 0000000000..c8d7191d54 --- /dev/null +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error-code/code.pbjson.dart @@ -0,0 +1,49 @@ +/// +// Generated code. Do not modify. +// source: code.proto +// +// @dart = 2.12 +// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields,deprecated_member_use_from_same_package + +import 'dart:core' as $core; +import 'dart:convert' as $convert; +import 'dart:typed_data' as $typed_data; +@$core.Deprecated('Use errorCodeDescriptor instead') +const ErrorCode$json = const { + '1': 'ErrorCode', + '2': const [ + const {'1': 'Internal', '2': 0}, + const {'1': 'UserUnauthorized', '2': 2}, + const {'1': 'RecordNotFound', '2': 3}, + const {'1': 'WorkspaceNameInvalid', '2': 100}, + const {'1': 'WorkspaceIdInvalid', '2': 101}, + const {'1': 'AppColorStyleInvalid', '2': 102}, + const {'1': 'WorkspaceDescTooLong', '2': 103}, + const {'1': 'WorkspaceNameTooLong', '2': 104}, + const {'1': 'AppIdInvalid', '2': 110}, + const {'1': 'AppNameInvalid', '2': 111}, + const {'1': 'ViewNameInvalid', '2': 120}, + const {'1': 'ViewThumbnailInvalid', '2': 121}, + const {'1': 'ViewIdInvalid', '2': 122}, + const {'1': 'ViewDescTooLong', '2': 123}, + const {'1': 'ViewDataInvalid', '2': 124}, + const {'1': 'ViewNameTooLong', '2': 125}, + const {'1': 'ConnectError', '2': 200}, + const {'1': 'EmailIsEmpty', '2': 300}, + const {'1': 'EmailFormatInvalid', '2': 301}, + const {'1': 'EmailAlreadyExists', '2': 302}, + const {'1': 'PasswordIsEmpty', '2': 303}, + const {'1': 'PasswordTooLong', '2': 304}, + const {'1': 'PasswordContainsForbidCharacters', '2': 305}, + const {'1': 'PasswordFormatInvalid', '2': 306}, + const {'1': 'PasswordNotMatch', '2': 307}, + const {'1': 'UserNameTooLong', '2': 308}, + const {'1': 'UserNameContainForbiddenCharacters', '2': 309}, + const {'1': 'UserNameIsEmpty', '2': 310}, + const {'1': 'UserIdInvalid', '2': 311}, + const {'1': 'UserNotExist', '2': 312}, + ], +}; + +/// Descriptor for `ErrorCode`. Decode as a `google.protobuf.EnumDescriptorProto`. +final $typed_data.Uint8List errorCodeDescriptor = $convert.base64Decode('CglFcnJvckNvZGUSDAoISW50ZXJuYWwQABIUChBVc2VyVW5hdXRob3JpemVkEAISEgoOUmVjb3JkTm90Rm91bmQQAxIYChRXb3Jrc3BhY2VOYW1lSW52YWxpZBBkEhYKEldvcmtzcGFjZUlkSW52YWxpZBBlEhgKFEFwcENvbG9yU3R5bGVJbnZhbGlkEGYSGAoUV29ya3NwYWNlRGVzY1Rvb0xvbmcQZxIYChRXb3Jrc3BhY2VOYW1lVG9vTG9uZxBoEhAKDEFwcElkSW52YWxpZBBuEhIKDkFwcE5hbWVJbnZhbGlkEG8SEwoPVmlld05hbWVJbnZhbGlkEHgSGAoUVmlld1RodW1ibmFpbEludmFsaWQQeRIRCg1WaWV3SWRJbnZhbGlkEHoSEwoPVmlld0Rlc2NUb29Mb25nEHsSEwoPVmlld0RhdGFJbnZhbGlkEHwSEwoPVmlld05hbWVUb29Mb25nEH0SEQoMQ29ubmVjdEVycm9yEMgBEhEKDEVtYWlsSXNFbXB0eRCsAhIXChJFbWFpbEZvcm1hdEludmFsaWQQrQISFwoSRW1haWxBbHJlYWR5RXhpc3RzEK4CEhQKD1Bhc3N3b3JkSXNFbXB0eRCvAhIUCg9QYXNzd29yZFRvb0xvbmcQsAISJQogUGFzc3dvcmRDb250YWluc0ZvcmJpZENoYXJhY3RlcnMQsQISGgoVUGFzc3dvcmRGb3JtYXRJbnZhbGlkELICEhUKEFBhc3N3b3JkTm90TWF0Y2gQswISFAoPVXNlck5hbWVUb29Mb25nELQCEicKIlVzZXJOYW1lQ29udGFpbkZvcmJpZGRlbkNoYXJhY3RlcnMQtQISFAoPVXNlck5hbWVJc0VtcHR5ELYCEhIKDVVzZXJJZEludmFsaWQQtwISEQoMVXNlck5vdEV4aXN0ELgC'); diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error-code/code.pbserver.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error-code/code.pbserver.dart new file mode 100644 index 0000000000..c42f9c4c50 --- /dev/null +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error-code/code.pbserver.dart @@ -0,0 +1,9 @@ +/// +// Generated code. Do not modify. +// source: code.proto +// +// @dart = 2.12 +// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields,deprecated_member_use_from_same_package + +export 'code.pb.dart'; + diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error-code/protobuf.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error-code/protobuf.dart new file mode 100644 index 0000000000..de33b9d615 --- /dev/null +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error-code/protobuf.dart @@ -0,0 +1,2 @@ +// Auto-generated, do not edit +export './code.pb.dart'; diff --git a/frontend/rust-lib/Cargo.lock b/frontend/rust-lib/Cargo.lock index 13675046cc..f0181e0e07 100755 --- a/frontend/rust-lib/Cargo.lock +++ b/frontend/rust-lib/Cargo.lock @@ -166,13 +166,34 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "block-buffer" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" +dependencies = [ + "block-padding", + "byte-tools", + "byteorder", + "generic-array 0.12.4", +] + [[package]] name = "block-buffer" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" dependencies = [ - "generic-array", + "generic-array 0.14.5", +] + +[[package]] +name = "block-padding" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" +dependencies = [ + "byte-tools", ] [[package]] @@ -193,6 +214,12 @@ version = "3.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4a45a46ab1f2412e53d3a0ade76ffad2025804294569aae387231a0cd6e0899" +[[package]] +name = "byte-tools" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" + [[package]] name = "bytecount" version = "0.6.2" @@ -248,6 +275,28 @@ dependencies = [ "winapi", ] +[[package]] +name = "chrono-tz" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58549f1842da3080ce63002102d5bc954c7bc843d4f47818e642abdc36253552" +dependencies = [ + "chrono", + "chrono-tz-build", + "phf 0.10.1", +] + +[[package]] +name = "chrono-tz-build" +version = "0.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db058d493fb2f65f41861bfed7e3fe6335264a9f0f92710cab5bdf01fef09069" +dependencies = [ + "parse-zoneinfo", + "phf 0.10.1", + "phf_codegen", +] + [[package]] name = "claim" version = "0.4.0" @@ -327,6 +376,21 @@ dependencies = [ "yaml-rust", ] +[[package]] +name = "console" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3993e6445baa160675931ec041a5e03ca84b9c6e32a056150d3aa2bdda0a1f45" +dependencies = [ + "encode_unicode", + "lazy_static", + "libc", + "regex", + "terminal_size", + "unicode-width", + "winapi", +] + [[package]] name = "convert_case" version = "0.4.0" @@ -588,6 +652,12 @@ dependencies = [ "syn", ] +[[package]] +name = "deunicode" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "850878694b7933ca4c9569d30a34b55031b9b139ee1fc7b94a527c4ef960d690" + [[package]] name = "diesel" version = "1.4.8" @@ -620,13 +690,22 @@ dependencies = [ "migrations_macros", ] +[[package]] +name = "digest" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" +dependencies = [ + "generic-array 0.12.4", +] + [[package]] name = "digest" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" dependencies = [ - "generic-array", + "generic-array 0.14.5", ] [[package]] @@ -647,6 +726,12 @@ version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" +[[package]] +name = "encode_unicode" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" + [[package]] name = "encoding_rs" version = "0.8.30" @@ -688,16 +773,6 @@ dependencies = [ "backtrace", ] -[[package]] -name = "error-code" -version = "0.1.0" -dependencies = [ - "derive_more", - "flowy-derive", - "lib-infra", - "protobuf", -] - [[package]] name = "eyre" version = "0.6.5" @@ -728,6 +803,12 @@ dependencies = [ "rand 0.7.3", ] +[[package]] +name = "fake-simd" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" + [[package]] name = "fancy-regex" version = "0.5.0" @@ -809,10 +890,15 @@ dependencies = [ name = "flowy-derive" version = "0.1.0" dependencies = [ + "dashmap", "flowy-ast", + "lazy_static", + "lib-infra", "proc-macro2", "quote", + "serde_json", "syn", + "walkdir", ] [[package]] @@ -865,10 +951,10 @@ name = "flowy-error" version = "0.1.0" dependencies = [ "bytes", - "error-code", "flowy-collaboration", "flowy-database", "flowy-derive", + "flowy-error-code", "http-flowy", "lib-dispatch", "lib-infra", @@ -879,6 +965,16 @@ dependencies = [ "serde_json", ] +[[package]] +name = "flowy-error-code" +version = "0.1.0" +dependencies = [ + "derive_more", + "flowy-derive", + "lib-infra", + "protobuf", +] + [[package]] name = "flowy-folder" version = "0.1.0" @@ -928,8 +1024,8 @@ dependencies = [ "bytes", "chrono", "derive_more", - "error-code", "flowy-derive", + "flowy-error-code", "lib-infra", "log", "protobuf", @@ -1107,9 +1203,9 @@ version = "0.1.0" dependencies = [ "bytes", "derive_more", - "error-code", "fancy-regex", "flowy-derive", + "flowy-error-code", "lazy_static", "lib-infra", "log", @@ -1239,6 +1335,15 @@ dependencies = [ "slab", ] +[[package]] +name = "generic-array" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd" +dependencies = [ + "typenum", +] + [[package]] name = "generic-array" version = "0.14.5" @@ -1287,6 +1392,30 @@ version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78cc372d058dcf6d5ecd98510e7fbc9e5aec4d21de70f65fea8fecebcd881bd4" +[[package]] +name = "globset" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10463d9ff00a2a068db14231982f5132edebad0d7660cd956a1c30292dbcbfbd" +dependencies = [ + "aho-corasick", + "bstr", + "fnv", + "log", + "regex", +] + +[[package]] +name = "globwalk" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93e3af942408868f6934a7b85134a3230832b9977cf66125df2f9edcfce4ddcc" +dependencies = [ + "bitflags", + "ignore", + "walkdir", +] + [[package]] name = "h2" version = "0.3.10" @@ -1388,6 +1517,12 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" +[[package]] +name = "humansize" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02296996cb8796d7c6e3bc2d9211b7802812d36999a51bb754123ead7d37d026" + [[package]] name = "humantime" version = "2.1.0" @@ -1448,6 +1583,24 @@ dependencies = [ "unicode-normalization", ] +[[package]] +name = "ignore" +version = "0.4.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "713f1b139373f96a2e0ce3ac931cd01ee973c3c5dd7c40c0c2efe96ad2b6751d" +dependencies = [ + "crossbeam-utils", + "globset", + "lazy_static", + "log", + "memchr", + "regex", + "same-file", + "thread_local", + "walkdir", + "winapi-util", +] + [[package]] name = "indenter" version = "0.3.3" @@ -1563,12 +1716,24 @@ dependencies = [ "bytes", "chrono", "cmd_lib", + "console", + "fancy-regex", + "flowy-ast", "futures-core", + "itertools", + "lazy_static", "log", + "phf 0.8.0", "pin-project", "protoc-rust", "rand 0.8.4", + "serde", + "serde_json", + "similar", + "syn", + "tera", "tokio", + "toml", "uuid", "walkdir", ] @@ -1693,6 +1858,12 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "maplit" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" + [[package]] name = "matchers" version = "0.0.1" @@ -1876,6 +2047,12 @@ version = "11.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" +[[package]] +name = "opaque-debug" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" + [[package]] name = "opaque-debug" version = "0.3.0" @@ -1956,6 +2133,15 @@ dependencies = [ "winapi", ] +[[package]] +name = "parse-zoneinfo" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c705f256449c60da65e11ff6626e0c16a0a0b96aaa348de61376b249bc340f41" +dependencies = [ + "regex", +] + [[package]] name = "paste" version = "1.0.6" @@ -1968,6 +2154,132 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" +[[package]] +name = "pest" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53" +dependencies = [ + "ucd-trie", +] + +[[package]] +name = "pest_derive" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "833d1ae558dc601e9a60366421196a8d94bc0ac980476d0b67e1d0988d72b2d0" +dependencies = [ + "pest", + "pest_generator", +] + +[[package]] +name = "pest_generator" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99b8db626e31e5b81787b9783425769681b347011cc59471e33ea46d2ea0cf55" +dependencies = [ + "pest", + "pest_meta", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "pest_meta" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54be6e404f5317079812fc8f9f5279de376d8856929e21c184ecf6bbd692a11d" +dependencies = [ + "maplit", + "pest", + "sha-1 0.8.2", +] + +[[package]] +name = "phf" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12" +dependencies = [ + "phf_macros", + "phf_shared 0.8.0", + "proc-macro-hack", +] + +[[package]] +name = "phf" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259" +dependencies = [ + "phf_shared 0.10.0", +] + +[[package]] +name = "phf_codegen" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb1c3a8bc4dd4e5cfce29b44ffc14bedd2ee294559a294e2a4d4c9e9a6a13cd" +dependencies = [ + "phf_generator 0.10.0", + "phf_shared 0.10.0", +] + +[[package]] +name = "phf_generator" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17367f0cc86f2d25802b2c26ee58a7b23faeccf78a396094c13dced0d0182526" +dependencies = [ + "phf_shared 0.8.0", + "rand 0.7.3", +] + +[[package]] +name = "phf_generator" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6" +dependencies = [ + "phf_shared 0.10.0", + "rand 0.8.4", +] + +[[package]] +name = "phf_macros" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f6fde18ff429ffc8fe78e2bf7f8b7a5a5a6e2a8b58bc5a9ac69198bbda9189c" +dependencies = [ + "phf_generator 0.8.0", + "phf_shared 0.8.0", + "proc-macro-hack", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "phf_shared" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c00cf8b9eafe68dde5e9eaa2cef8ee84a9336a47d566ec55ca16589633b65af7" +dependencies = [ + "siphasher", +] + +[[package]] +name = "phf_shared" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" +dependencies = [ + "siphasher", + "uncased", +] + [[package]] name = "pin-project" version = "1.0.10" @@ -2064,6 +2376,12 @@ dependencies = [ "version_check", ] +[[package]] +name = "proc-macro-hack" +version = "0.5.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" + [[package]] name = "proc-macro2" version = "1.0.36" @@ -2164,6 +2482,7 @@ dependencies = [ "rand_chacha 0.2.2", "rand_core 0.5.1", "rand_hc 0.2.0", + "rand_pcg", ] [[package]] @@ -2234,6 +2553,15 @@ dependencies = [ "rand_core 0.6.3", ] +[[package]] +name = "rand_pcg" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16abd0c1b639e9eb4d7c50c0b8100b0d0f849be2349829c740fe8e6eb4816429" +dependencies = [ + "rand_core 0.5.1", +] + [[package]] name = "rayon" version = "1.5.1" @@ -2555,17 +2883,29 @@ dependencies = [ "syn", ] +[[package]] +name = "sha-1" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df" +dependencies = [ + "block-buffer 0.7.3", + "digest 0.8.1", + "fake-simd", + "opaque-debug 0.2.3", +] + [[package]] name = "sha-1" version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "99cd6713db3cf16b6c84e06321e049a9b9f699826e16096d23bbcc44d15d51a6" dependencies = [ - "block-buffer", + "block-buffer 0.9.0", "cfg-if", "cpufeatures", - "digest", - "opaque-debug", + "digest 0.9.0", + "opaque-debug 0.3.0", ] [[package]] @@ -2586,12 +2926,33 @@ dependencies = [ "libc", ] +[[package]] +name = "similar" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ad1d488a557b235fc46dae55512ffbfc429d2482b08b4d9435ab07384ca8aec" + +[[package]] +name = "siphasher" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a86232ab60fa71287d7f2ddae4a7073f6b7aac33631c3015abb556f08c6d0a3e" + [[package]] name = "slab" version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5" +[[package]] +name = "slug" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3bc762e6a4b6c6fcaade73e77f9ebc6991b676f88bb2358bddb56560f073373" +dependencies = [ + "deunicode", +] + [[package]] name = "smallvec" version = "1.7.0" @@ -2663,6 +3024,28 @@ dependencies = [ "winapi", ] +[[package]] +name = "tera" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3cac831b615c25bcef632d1cabf864fa05813baad3d526829db18eb70e8b58d" +dependencies = [ + "chrono", + "chrono-tz", + "globwalk", + "humansize", + "lazy_static", + "percent-encoding", + "pest", + "pest_derive", + "rand 0.8.4", + "regex", + "serde", + "serde_json", + "slug", + "unic-segment", +] + [[package]] name = "termcolor" version = "1.1.2" @@ -2672,6 +3055,16 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "terminal_size" +version = "0.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "633c1a546cee861a1a6d0dc69ebeca693bf4296661ba7852b9d21d159e0506df" +dependencies = [ + "libc", + "winapi", +] + [[package]] name = "textwrap" version = "0.11.0" @@ -2824,6 +3217,15 @@ dependencies = [ "tokio", ] +[[package]] +name = "toml" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa" +dependencies = [ + "serde", +] + [[package]] name = "tower-service" version = "0.3.1" @@ -2963,7 +3365,7 @@ dependencies = [ "httparse", "log", "rand 0.8.4", - "sha-1", + "sha-1 0.9.8", "thiserror", "url", "utf-8", @@ -2975,6 +3377,71 @@ version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" +[[package]] +name = "ucd-trie" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c" + +[[package]] +name = "uncased" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5baeed7327e25054889b9bd4f975f32e5f4c5d434042d59ab6cd4142c0a76ed0" +dependencies = [ + "version_check", +] + +[[package]] +name = "unic-char-property" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8c57a407d9b6fa02b4795eb81c5b6652060a15a7903ea981f3d723e6c0be221" +dependencies = [ + "unic-char-range", +] + +[[package]] +name = "unic-char-range" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0398022d5f700414f6b899e10b8348231abf9173fa93144cbc1a43b9793c1fbc" + +[[package]] +name = "unic-common" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80d7ff825a6a654ee85a63e80f92f054f904f21e7d12da4e22f9834a4aaa35bc" + +[[package]] +name = "unic-segment" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4ed5d26be57f84f176157270c112ef57b86debac9cd21daaabbe56db0f88f23" +dependencies = [ + "unic-ucd-segment", +] + +[[package]] +name = "unic-ucd-segment" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2079c122a62205b421f499da10f3ee0f7697f012f55b675e002483c73ea34700" +dependencies = [ + "unic-char-property", + "unic-char-range", + "unic-ucd-version", +] + +[[package]] +name = "unic-ucd-version" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96bd2f2237fe450fcd0a1d2f5f4e91711124f7857ba2e964247776ebeeb7b0c4" +dependencies = [ + "unic-common", +] + [[package]] name = "unicode-bidi" version = "0.3.7" diff --git a/frontend/rust-lib/dart-ffi/Cargo.toml b/frontend/rust-lib/dart-ffi/Cargo.toml index 9d733b13e5..7bbd53f824 100644 --- a/frontend/rust-lib/dart-ffi/Cargo.toml +++ b/frontend/rust-lib/dart-ffi/Cargo.toml @@ -24,11 +24,12 @@ bytes = { version = "1.0" } once_cell = "1" lib-dispatch = {path = "../lib-dispatch" } -flowy-sdk = {path = "../flowy-sdk", features = ["dart"]} +flowy-sdk = {path = "../flowy-sdk"} dart-notify = {path = "../dart-notify" } flowy-derive = {path = "../../../shared-lib/flowy-derive" } [features] +default = ["flowy-sdk/dart"] flutter = ["dart-notify/dart"] http_server = ["flowy-sdk/http_server", "flowy-sdk/use_bunyan"] #use_serde = ["bincode"] diff --git a/frontend/rust-lib/dart-ffi/build.rs b/frontend/rust-lib/dart-ffi/build.rs index 3fe5e908d3..ef2b12f93d 100644 --- a/frontend/rust-lib/dart-ffi/build.rs +++ b/frontend/rust-lib/dart-ffi/build.rs @@ -1,5 +1,5 @@ -use lib_infra::pb_gen; +use lib_infra::pb; fn main() { - pb_gen::gen("dart-ffi", "./src/protobuf/proto"); + pb::gen_files(env!("CARGO_PKG_NAME"), "./src/protobuf/proto"); } diff --git a/frontend/rust-lib/dart-notify/build.rs b/frontend/rust-lib/dart-notify/build.rs index 83043c402f..ef2b12f93d 100644 --- a/frontend/rust-lib/dart-notify/build.rs +++ b/frontend/rust-lib/dart-notify/build.rs @@ -1,5 +1,5 @@ -use lib_infra::pb_gen; +use lib_infra::pb; fn main() { - pb_gen::gen("dart-notify", "./src/protobuf/proto"); + pb::gen_files(env!("CARGO_PKG_NAME"), "./src/protobuf/proto"); } diff --git a/frontend/rust-lib/flowy-error/Cargo.toml b/frontend/rust-lib/flowy-error/Cargo.toml index a93776894b..cf2a48e2e2 100644 --- a/frontend/rust-lib/flowy-error/Cargo.toml +++ b/frontend/rust-lib/flowy-error/Cargo.toml @@ -7,7 +7,7 @@ edition = "2018" [dependencies] flowy-derive = { path = "../../../shared-lib/flowy-derive" } -error-code = { path = "../../../shared-lib/error-code"} +flowy-error-code = { path = "../../../shared-lib/flowy-error-code"} lib-dispatch = { path = "../lib-dispatch" } protobuf = {version = "2.20.0"} bytes = "1.0" @@ -27,7 +27,7 @@ ot = ["lib-ot"] serde = ["serde_json"] http_server = ["http-flowy"] db = ["flowy-database", "lib-sqlite", "r2d2"] -dart = ["error-code/dart", "lib-infra/dart"] +dart = ["flowy-error-code/dart", "lib-infra/dart"] [build-dependencies] lib-infra = { path = "../../../shared-lib/lib-infra", features = ["pb_gen"] } \ No newline at end of file diff --git a/frontend/rust-lib/flowy-error/build.rs b/frontend/rust-lib/flowy-error/build.rs index 2e2596840b..ca23d51872 100644 --- a/frontend/rust-lib/flowy-error/build.rs +++ b/frontend/rust-lib/flowy-error/build.rs @@ -1,5 +1,5 @@ -use lib_infra::pb_gen; +use lib_infra::pb; fn main() { - pb_gen::gen("flowy-error", "./src/protobuf/proto"); + pb::gen_files("flowy-error", "./src/protobuf/proto"); } diff --git a/frontend/rust-lib/flowy-error/src/errors.rs b/frontend/rust-lib/flowy-error/src/errors.rs index a0c2cc129f..956df16fa5 100644 --- a/frontend/rust-lib/flowy-error/src/errors.rs +++ b/frontend/rust-lib/flowy-error/src/errors.rs @@ -1,6 +1,6 @@ use bytes::Bytes; -use error_code::ErrorCode; use flowy_derive::ProtoBuf; +use flowy_error_code::ErrorCode; use lib_dispatch::prelude::{EventResponse, ResponseBuilder}; use std::{convert::TryInto, fmt, fmt::Debug}; diff --git a/frontend/rust-lib/flowy-error/src/ext/http_server.rs b/frontend/rust-lib/flowy-error/src/ext/http_server.rs index 4515eddf1f..25154d0072 100644 --- a/frontend/rust-lib/flowy-error/src/ext/http_server.rs +++ b/frontend/rust-lib/flowy-error/src/ext/http_server.rs @@ -1,5 +1,5 @@ use crate::FlowyError; -use error_code::ErrorCode; +use flowy_error_code::ErrorCode; use http_flowy::errors::{ErrorCode as ServerErrorCode, ServerError}; impl std::convert::From for FlowyError { diff --git a/frontend/rust-lib/flowy-error/src/lib.rs b/frontend/rust-lib/flowy-error/src/lib.rs index 756eb4e82c..a72422d1fa 100644 --- a/frontend/rust-lib/flowy-error/src/lib.rs +++ b/frontend/rust-lib/flowy-error/src/lib.rs @@ -2,5 +2,5 @@ mod errors; mod ext; pub mod protobuf; -pub use error_code::ErrorCode; pub use errors::*; +pub use flowy_error_code::ErrorCode; diff --git a/frontend/rust-lib/flowy-folder/Cargo.toml b/frontend/rust-lib/flowy-folder/Cargo.toml index 43d259dd4b..f51c3fb4eb 100644 --- a/frontend/rust-lib/flowy-folder/Cargo.toml +++ b/frontend/rust-lib/flowy-folder/Cargo.toml @@ -56,4 +56,4 @@ flowy_unit_test = ["lib-ot/flowy_unit_test", "flowy-sync/flowy_unit_test"] dart = ["lib-infra/dart", "flowy-folder/dart", "flowy-folder/dart",] [build-dependencies] -lib-infra = { path = "../../../shared-lib/lib-infra", features = ["pb_gen"] } \ No newline at end of file +lib-infra = { path = "../../../shared-lib/lib-infra", features = ["pb_gen", "proto_gen"] } \ No newline at end of file diff --git a/frontend/rust-lib/flowy-folder/build.rs b/frontend/rust-lib/flowy-folder/build.rs index 75e6a617c3..ef2b12f93d 100644 --- a/frontend/rust-lib/flowy-folder/build.rs +++ b/frontend/rust-lib/flowy-folder/build.rs @@ -1,5 +1,5 @@ -use lib_infra::pb_gen; +use lib_infra::pb; fn main() { - pb_gen::gen("flowy-folder", "./src/protobuf/proto"); + pb::gen_files(env!("CARGO_PKG_NAME"), "./src/protobuf/proto"); } diff --git a/frontend/rust-lib/flowy-net/build.rs b/frontend/rust-lib/flowy-net/build.rs index 27cb230e29..ef2b12f93d 100644 --- a/frontend/rust-lib/flowy-net/build.rs +++ b/frontend/rust-lib/flowy-net/build.rs @@ -1,5 +1,5 @@ -use lib_infra::pb_gen; +use lib_infra::pb; fn main() { - pb_gen::gen("flowy-net", "./src/protobuf/proto"); + pb::gen_files(env!("CARGO_PKG_NAME"), "./src/protobuf/proto"); } diff --git a/frontend/rust-lib/flowy-sdk/Cargo.toml b/frontend/rust-lib/flowy-sdk/Cargo.toml index be4aaabeaa..b303f89b30 100644 --- a/frontend/rust-lib/flowy-sdk/Cargo.toml +++ b/frontend/rust-lib/flowy-sdk/Cargo.toml @@ -39,4 +39,4 @@ futures-util = "0.3.15" [features] http_server = ["flowy-user/http_server", "flowy-folder/http_server", "flowy-document/http_server"] use_bunyan = ["lib-log/use_bunyan"] -dart = ["flowy-user/dart", "flowy-net/dart", "flowy-folder/dart", "flowy-collaboration/dart"] \ No newline at end of file +dart = ["flowy-user/dart", "flowy-net/dart", "flowy-folder/dart", "flowy-collaboration/dart"] diff --git a/frontend/rust-lib/flowy-user/build.rs b/frontend/rust-lib/flowy-user/build.rs index 19d5124f70..ef2b12f93d 100644 --- a/frontend/rust-lib/flowy-user/build.rs +++ b/frontend/rust-lib/flowy-user/build.rs @@ -1,5 +1,5 @@ -use lib_infra::pb_gen; +use lib_infra::pb; fn main() { - pb_gen::gen("flowy-user", "./src/protobuf/proto"); + pb::gen_files(env!("CARGO_PKG_NAME"), "./src/protobuf/proto"); } diff --git a/frontend/scripts/flowy-tool/src/dart_event/dart_event.rs b/frontend/scripts/flowy-tool/src/dart_event/dart_event.rs index e4288033af..167663a6b2 100644 --- a/frontend/scripts/flowy-tool/src/dart_event/dart_event.rs +++ b/frontend/scripts/flowy-tool/src/dart_event/dart_event.rs @@ -15,7 +15,7 @@ impl DartEventCodeGen { let event_crates = parse_dart_event_files(self.rust_sources.clone()); let event_ast = event_crates .iter() - .map(|event_crate| parse_event_crate(event_crate)) + .map(parse_event_crate) .flatten() .collect::>(); @@ -62,7 +62,7 @@ pub fn parse_dart_event_files(roots: Vec) -> Vec { .into_iter() .filter_entry(|e| !is_hidden(e)) .filter_map(|e| e.ok()) - .filter(|e| is_crate_dir(e)) + .filter(is_crate_dir) .flat_map(|e| parse_crate_config_from(&e)) .map(|crate_config| DartEventCrate::from_config(&crate_config)) .collect::>(); diff --git a/frontend/scripts/flowy-tool/src/main.rs b/frontend/scripts/flowy-tool/src/main.rs index c25b0041b5..7b23f2d00a 100644 --- a/frontend/scripts/flowy-tool/src/main.rs +++ b/frontend/scripts/flowy-tool/src/main.rs @@ -10,7 +10,7 @@ fn main() { let matches = app().get_matches(); - if let Some(ref matches) = matches.subcommand_matches("pb-gen") { + if let Some(matches) = matches.subcommand_matches("pb-gen") { let rust_sources: Vec = matches .values_of("rust_sources") .unwrap() @@ -27,7 +27,7 @@ fn main() { .gen(); } - if let Some(ref matches) = matches.subcommand_matches("dart-event") { + if let Some(matches) = matches.subcommand_matches("dart-event") { let rust_sources: Vec = matches .values_of("rust_sources") .unwrap() diff --git a/frontend/scripts/flowy-tool/src/proto/ast.rs b/frontend/scripts/flowy-tool/src/proto/ast.rs index e03fd9a3a2..ba02480685 100644 --- a/frontend/scripts/flowy-tool/src/proto/ast.rs +++ b/frontend/scripts/flowy-tool/src/proto/ast.rs @@ -59,7 +59,7 @@ fn parse_files_protobuf(proto_crate_path: &str, proto_output_dir: &str) -> Vec

Vec

TypeCategory { - match type_str { - "Vec" => TypeCategory::Array, - "HashMap" => TypeCategory::Map, - "u8" => TypeCategory::Bytes, - "String" => TypeCategory::Str, - "FFIRequest" - | "FFIResponse" - | "FlowyError" - | "SubscribeObject" - | "NetworkState" - | "SignInRequest" - | "SignInParams" - | "SignInResponse" - | "SignUpRequest" - | "SignUpParams" - | "SignUpResponse" - | "UserToken" - | "UserProfile" - | "UpdateUserRequest" - | "UpdateUserParams" - | "UserPreferences" - | "AppearanceSettings" - | "LocaleSettings" - | "ClientRevisionWSData" - | "ServerRevisionWSData" - | "NewDocumentUser" - | "FolderInfo" - | "Revision" - | "RepeatedRevision" - | "RevId" - | "RevisionRange" - | "CreateDocParams" - | "DocumentInfo" - | "ResetDocumentParams" - | "DocumentDelta" - | "NewDocUser" - | "DocumentId" - | "WSError" - | "WebSocketRawMessage" - | "Workspace" - | "RepeatedWorkspace" - | "CreateWorkspaceRequest" - | "CreateWorkspaceParams" - | "QueryWorkspaceRequest" - | "WorkspaceId" - | "CurrentWorkspaceSetting" - | "UpdateWorkspaceRequest" - | "UpdateWorkspaceParams" - | "ExportRequest" - | "ExportData" - | "App" - | "RepeatedApp" - | "CreateAppRequest" - | "ColorStyle" - | "CreateAppParams" - | "QueryAppRequest" - | "AppId" - | "UpdateAppRequest" - | "UpdateAppParams" - | "Trash" - | "RepeatedTrash" - | "RepeatedTrashId" - | "TrashId" - | "View" - | "RepeatedView" - | "CreateViewRequest" - | "CreateViewParams" - | "QueryViewRequest" - | "ViewId" - | "RepeatedViewId" - | "UpdateViewRequest" - | "UpdateViewParams" - => TypeCategory::Protobuf, - "FFIStatusCode" - | "FolderEvent" - | "FolderNotification" - | "NetworkEvent" - | "NetworkType" - | "UserEvent" - | "UserNotification" - | "ClientRevisionWSDataType" - | "ServerRevisionWSDataType" - | "RevisionState" - | "RevType" - | "ErrorCode" - | "WSChannel" - | "ExportType" - | "TrashType" - | "ViewType" - => TypeCategory::Enum, - - "Option" => TypeCategory::Opt, - _ => TypeCategory::Primitive, - } -} diff --git a/shared-lib/flowy-derive/src/derive_cache/mod.rs b/shared-lib/flowy-derive/src/derive_cache/mod.rs deleted file mode 100644 index 1b48d15980..0000000000 --- a/shared-lib/flowy-derive/src/derive_cache/mod.rs +++ /dev/null @@ -1,4 +0,0 @@ -#![allow(clippy::module_inception)] -mod derive_cache; - -pub use derive_cache::*; diff --git a/shared-lib/flowy-derive/src/lib.rs b/shared-lib/flowy-derive/src/lib.rs index 82f0002fb3..71ff82b5ad 100644 --- a/shared-lib/flowy-derive/src/lib.rs +++ b/shared-lib/flowy-derive/src/lib.rs @@ -9,7 +9,6 @@ use syn::{parse_macro_input, DeriveInput}; extern crate quote; mod dart_event; -mod derive_cache; mod proto_buf; // Inspired by https://serde.rs/attributes.html diff --git a/shared-lib/flowy-derive/src/proto_buf/deserialize.rs b/shared-lib/flowy-derive/src/proto_buf/deserialize.rs index 80b37e3dcd..af4b7f7345 100644 --- a/shared-lib/flowy-derive/src/proto_buf/deserialize.rs +++ b/shared-lib/flowy-derive/src/proto_buf/deserialize.rs @@ -1,4 +1,4 @@ -use crate::{derive_cache::TypeCategory, proto_buf::util::*}; +use crate::proto_buf::util::*; use flowy_ast::*; use proc_macro2::{Span, TokenStream}; diff --git a/shared-lib/flowy-derive/src/proto_buf/serialize.rs b/shared-lib/flowy-derive/src/proto_buf/serialize.rs index 7d1ce44a45..d0162c90d3 100644 --- a/shared-lib/flowy-derive/src/proto_buf/serialize.rs +++ b/shared-lib/flowy-derive/src/proto_buf/serialize.rs @@ -1,8 +1,5 @@ #![allow(clippy::while_let_on_iterator)] -use crate::{ - derive_cache::TypeCategory, - proto_buf::util::{get_member_ident, ident_category}, -}; +use crate::proto_buf::util::{get_member_ident, ident_category, TypeCategory}; use flowy_ast::*; use proc_macro2::TokenStream; diff --git a/shared-lib/flowy-derive/src/proto_buf/util.rs b/shared-lib/flowy-derive/src/proto_buf/util.rs index aec13e7358..7260d97844 100644 --- a/shared-lib/flowy-derive/src/proto_buf/util.rs +++ b/shared-lib/flowy-derive/src/proto_buf/util.rs @@ -1,8 +1,14 @@ -use crate::derive_cache::*; +use dashmap::{DashMap, DashSet}; use flowy_ast::{Ctxt, TyInfo}; +use lazy_static::lazy_static; +use lib_infra::proto_gen::ProtoCache; +use std::fs::File; +use std::io::Read; +use std::sync::atomic::{AtomicBool, Ordering}; +use walkdir::WalkDir; pub fn ident_category(ident: &syn::Ident) -> TypeCategory { - let ident_str: &str = &ident.to_string(); + let ident_str = ident.to_string(); category_from_str(ident_str) } @@ -20,3 +26,84 @@ pub fn assert_bracket_ty_is_some(ctxt: &Ctxt, ty_info: &TyInfo) { ctxt.error_spanned_by(ty_info.ty, "Invalid bracketed type when gen de token steam".to_string()); } } + +lazy_static! { + static ref READ_FLAG: DashSet = DashSet::new(); + static ref CACHE_INFO: DashMap> = DashMap::new(); + static ref IS_LOAD: AtomicBool = AtomicBool::new(false); +} + +#[derive(Eq, Hash, PartialEq)] +pub enum TypeCategory { + Array, + Map, + Str, + Protobuf, + Bytes, + Enum, + Opt, + Primitive, +} +// auto generate, do not edit +pub fn category_from_str(type_str: String) -> TypeCategory { + if !IS_LOAD.load(Ordering::SeqCst) { + IS_LOAD.store(true, Ordering::SeqCst); + // Dependents on another crate file is not good, just leave it here. + // Maybe find another way to read the .cache in the future. + let cache_dir = format!("{}/../lib-infra/.cache", env!("CARGO_MANIFEST_DIR")); + for path in WalkDir::new(cache_dir) + .into_iter() + .filter_map(|e| e.ok()) + .map(|e| e.path().to_str().unwrap().to_string()) + { + match read_file(&path) { + None => {} + Some(s) => { + let cache: ProtoCache = serde_json::from_str(&s).unwrap(); + CACHE_INFO + .entry(TypeCategory::Protobuf) + .or_insert(vec![]) + .extend(cache.structs); + CACHE_INFO + .entry(TypeCategory::Enum) + .or_insert(vec![]) + .extend(cache.enums); + } + } + } + } + + if let Some(protobuf) = CACHE_INFO.get(&TypeCategory::Protobuf) { + if protobuf.contains(&type_str) { + return TypeCategory::Protobuf; + } + } + + if let Some(protobuf) = CACHE_INFO.get(&TypeCategory::Enum) { + if protobuf.contains(&type_str) { + return TypeCategory::Enum; + } + } + + match type_str.as_str() { + "Vec" => TypeCategory::Array, + "HashMap" => TypeCategory::Map, + "u8" => TypeCategory::Bytes, + "String" => TypeCategory::Str, + "Option" => TypeCategory::Opt, + _ => TypeCategory::Primitive, + } +} + +fn read_file(path: &str) -> Option { + match File::open(path) { + Ok(mut file) => { + let mut content = String::new(); + match file.read_to_string(&mut content) { + Ok(_) => Some(content), + Err(_) => None, + } + } + Err(_) => None, + } +} diff --git a/shared-lib/error-code/Cargo.toml b/shared-lib/flowy-error-code/Cargo.toml similarity index 88% rename from shared-lib/error-code/Cargo.toml rename to shared-lib/flowy-error-code/Cargo.toml index 404da61a41..691230c2eb 100644 --- a/shared-lib/error-code/Cargo.toml +++ b/shared-lib/flowy-error-code/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "error-code" +name = "flowy-error-code" version = "0.1.0" edition = "2018" diff --git a/shared-lib/flowy-error-code/Flowy.toml b/shared-lib/flowy-error-code/Flowy.toml new file mode 100644 index 0000000000..7d6706b430 --- /dev/null +++ b/shared-lib/flowy-error-code/Flowy.toml @@ -0,0 +1,3 @@ + +proto_crates = ["src/code.rs"] +event_files = [] \ No newline at end of file diff --git a/shared-lib/flowy-error-code/build.rs b/shared-lib/flowy-error-code/build.rs new file mode 100644 index 0000000000..ef2b12f93d --- /dev/null +++ b/shared-lib/flowy-error-code/build.rs @@ -0,0 +1,5 @@ +use lib_infra::pb; + +fn main() { + pb::gen_files(env!("CARGO_PKG_NAME"), "./src/protobuf/proto"); +} diff --git a/shared-lib/error-code/src/error_code.rs b/shared-lib/flowy-error-code/src/code.rs similarity index 100% rename from shared-lib/error-code/src/error_code.rs rename to shared-lib/flowy-error-code/src/code.rs diff --git a/shared-lib/flowy-error-code/src/lib.rs b/shared-lib/flowy-error-code/src/lib.rs new file mode 100644 index 0000000000..4970c163f7 --- /dev/null +++ b/shared-lib/flowy-error-code/src/lib.rs @@ -0,0 +1,4 @@ +mod code; +mod protobuf; + +pub use code::*; diff --git a/shared-lib/error-code/src/protobuf/mod.rs b/shared-lib/flowy-error-code/src/protobuf/mod.rs similarity index 100% rename from shared-lib/error-code/src/protobuf/mod.rs rename to shared-lib/flowy-error-code/src/protobuf/mod.rs diff --git a/shared-lib/error-code/src/protobuf/model/error_code.rs b/shared-lib/flowy-error-code/src/protobuf/model/code.rs similarity index 86% rename from shared-lib/error-code/src/protobuf/model/error_code.rs rename to shared-lib/flowy-error-code/src/protobuf/model/code.rs index 412b935aab..f70c1eb49d 100644 --- a/shared-lib/error-code/src/protobuf/model/error_code.rs +++ b/shared-lib/flowy-error-code/src/protobuf/model/code.rs @@ -17,7 +17,7 @@ #![allow(trivial_casts)] #![allow(unused_imports)] #![allow(unused_results)] -//! Generated file from `error_code.proto` +//! Generated file from `code.proto` /// Generated files are compatible only with the same version /// of protobuf runtime. @@ -158,20 +158,20 @@ impl ::protobuf::reflect::ProtobufValue for ErrorCode { } static file_descriptor_proto_data: &'static [u8] = b"\ - \n\x10error_code.proto*\xc4\x05\n\tErrorCode\x12\x0c\n\x08Internal\x10\0\ - \x12\x14\n\x10UserUnauthorized\x10\x02\x12\x12\n\x0eRecordNotFound\x10\ - \x03\x12\x18\n\x14WorkspaceNameInvalid\x10d\x12\x16\n\x12WorkspaceIdInva\ - lid\x10e\x12\x18\n\x14AppColorStyleInvalid\x10f\x12\x18\n\x14WorkspaceDe\ - scTooLong\x10g\x12\x18\n\x14WorkspaceNameTooLong\x10h\x12\x10\n\x0cAppId\ - Invalid\x10n\x12\x12\n\x0eAppNameInvalid\x10o\x12\x13\n\x0fViewNameInval\ - id\x10x\x12\x18\n\x14ViewThumbnailInvalid\x10y\x12\x11\n\rViewIdInvalid\ - \x10z\x12\x13\n\x0fViewDescTooLong\x10{\x12\x13\n\x0fViewDataInvalid\x10\ - |\x12\x13\n\x0fViewNameTooLong\x10}\x12\x11\n\x0cConnectError\x10\xc8\ - \x01\x12\x11\n\x0cEmailIsEmpty\x10\xac\x02\x12\x17\n\x12EmailFormatInval\ - id\x10\xad\x02\x12\x17\n\x12EmailAlreadyExists\x10\xae\x02\x12\x14\n\x0f\ - PasswordIsEmpty\x10\xaf\x02\x12\x14\n\x0fPasswordTooLong\x10\xb0\x02\x12\ - %\n\x20PasswordContainsForbidCharacters\x10\xb1\x02\x12\x1a\n\x15Passwor\ - dFormatInvalid\x10\xb2\x02\x12\x15\n\x10PasswordNotMatch\x10\xb3\x02\x12\ + \n\ncode.proto*\xc4\x05\n\tErrorCode\x12\x0c\n\x08Internal\x10\0\x12\x14\ + \n\x10UserUnauthorized\x10\x02\x12\x12\n\x0eRecordNotFound\x10\x03\x12\ + \x18\n\x14WorkspaceNameInvalid\x10d\x12\x16\n\x12WorkspaceIdInvalid\x10e\ + \x12\x18\n\x14AppColorStyleInvalid\x10f\x12\x18\n\x14WorkspaceDescTooLon\ + g\x10g\x12\x18\n\x14WorkspaceNameTooLong\x10h\x12\x10\n\x0cAppIdInvalid\ + \x10n\x12\x12\n\x0eAppNameInvalid\x10o\x12\x13\n\x0fViewNameInvalid\x10x\ + \x12\x18\n\x14ViewThumbnailInvalid\x10y\x12\x11\n\rViewIdInvalid\x10z\ + \x12\x13\n\x0fViewDescTooLong\x10{\x12\x13\n\x0fViewDataInvalid\x10|\x12\ + \x13\n\x0fViewNameTooLong\x10}\x12\x11\n\x0cConnectError\x10\xc8\x01\x12\ + \x11\n\x0cEmailIsEmpty\x10\xac\x02\x12\x17\n\x12EmailFormatInvalid\x10\ + \xad\x02\x12\x17\n\x12EmailAlreadyExists\x10\xae\x02\x12\x14\n\x0fPasswo\ + rdIsEmpty\x10\xaf\x02\x12\x14\n\x0fPasswordTooLong\x10\xb0\x02\x12%\n\ + \x20PasswordContainsForbidCharacters\x10\xb1\x02\x12\x1a\n\x15PasswordFo\ + rmatInvalid\x10\xb2\x02\x12\x15\n\x10PasswordNotMatch\x10\xb3\x02\x12\ \x14\n\x0fUserNameTooLong\x10\xb4\x02\x12'\n\"UserNameContainForbiddenCh\ aracters\x10\xb5\x02\x12\x14\n\x0fUserNameIsEmpty\x10\xb6\x02\x12\x12\n\ \rUserIdInvalid\x10\xb7\x02\x12\x11\n\x0cUserNotExist\x10\xb8\x02b\x06pr\ diff --git a/shared-lib/error-code/src/protobuf/document b/shared-lib/flowy-error-code/src/protobuf/model/mod.rs similarity index 70% rename from shared-lib/error-code/src/protobuf/document rename to shared-lib/flowy-error-code/src/protobuf/model/mod.rs index da97aad28a..191b80e077 100644 --- a/shared-lib/error-code/src/protobuf/document +++ b/shared-lib/flowy-error-code/src/protobuf/model/mod.rs @@ -1,4 +1,5 @@ #![cfg_attr(rustfmt, rustfmt::skip)] // Auto-generated, do not edit -mod model; -pub use model::*; \ No newline at end of file + +mod code; +pub use code::*; diff --git a/shared-lib/error-code/src/protobuf/proto/error_code.proto b/shared-lib/flowy-error-code/src/protobuf/proto/code.proto similarity index 100% rename from shared-lib/error-code/src/protobuf/proto/error_code.proto rename to shared-lib/flowy-error-code/src/protobuf/proto/code.proto diff --git a/shared-lib/flowy-folder-data-model/Cargo.toml b/shared-lib/flowy-folder-data-model/Cargo.toml index 23695e9947..44cd3412b3 100644 --- a/shared-lib/flowy-folder-data-model/Cargo.toml +++ b/shared-lib/flowy-folder-data-model/Cargo.toml @@ -16,7 +16,7 @@ derive_more = {version = "0.99", features = ["display"]} log = "0.4.14" uuid = { version = "0.8", features = ["serde", "v4"] } chrono = { version = "0.4" } -error-code = { path = "../error-code"} +flowy-error-code = { path = "../flowy-error-code"} serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" @@ -27,4 +27,4 @@ lib-infra = { path = "../lib-infra", features = ["pb_gen"] } default = [] backend = [] frontend = [] -dart = ["lib-infra/dart", "error-code/dart"] \ No newline at end of file +dart = ["lib-infra/dart", "flowy-error-code/dart"] \ No newline at end of file diff --git a/shared-lib/flowy-folder-data-model/build.rs b/shared-lib/flowy-folder-data-model/build.rs index 876f89a90f..ef2b12f93d 100644 --- a/shared-lib/flowy-folder-data-model/build.rs +++ b/shared-lib/flowy-folder-data-model/build.rs @@ -1,5 +1,5 @@ -use lib_infra::pb_gen; +use lib_infra::pb; fn main() { - pb_gen::gen("flowy-folder-data-model", "./src/protobuf/proto"); + pb::gen_files(env!("CARGO_PKG_NAME"), "./src/protobuf/proto"); } diff --git a/shared-lib/flowy-folder-data-model/src/lib.rs b/shared-lib/flowy-folder-data-model/src/lib.rs index 841c93b8d7..0621902466 100644 --- a/shared-lib/flowy-folder-data-model/src/lib.rs +++ b/shared-lib/flowy-folder-data-model/src/lib.rs @@ -9,5 +9,5 @@ pub mod protobuf; pub mod user_default; pub mod errors { - pub use error_code::ErrorCode; + pub use flowy_error_code::ErrorCode; } diff --git a/shared-lib/flowy-user-data-model/Cargo.toml b/shared-lib/flowy-user-data-model/Cargo.toml index b8bdc9760d..561764adea 100644 --- a/shared-lib/flowy-user-data-model/Cargo.toml +++ b/shared-lib/flowy-user-data-model/Cargo.toml @@ -7,7 +7,7 @@ edition = "2018" [dependencies] flowy-derive = { path = "../flowy-derive" } -error-code = { path = "../error-code" } +flowy-error-code = { path = "../flowy-error-code" } protobuf = {version = "2.18.0"} bytes = "1.0" unicode-segmentation = "1.8" @@ -30,4 +30,4 @@ futures = "0.3.15" serial_test = "0.5.1" [features] -dart = ["lib-infra/dart", "error-code/dart"] +dart = ["lib-infra/dart", "flowy-error-code/dart"] diff --git a/shared-lib/flowy-user-data-model/build.rs b/shared-lib/flowy-user-data-model/build.rs index f9897cc349..ef2b12f93d 100644 --- a/shared-lib/flowy-user-data-model/build.rs +++ b/shared-lib/flowy-user-data-model/build.rs @@ -1,5 +1,5 @@ -use lib_infra::pb_gen; +use lib_infra::pb; fn main() { - pb_gen::gen("flowy-user-data-model", "./src/protobuf/proto"); + pb::gen_files(env!("CARGO_PKG_NAME"), "./src/protobuf/proto"); } diff --git a/shared-lib/flowy-user-data-model/src/lib.rs b/shared-lib/flowy-user-data-model/src/lib.rs index 706b26a74f..eb967a2520 100644 --- a/shared-lib/flowy-user-data-model/src/lib.rs +++ b/shared-lib/flowy-user-data-model/src/lib.rs @@ -3,5 +3,5 @@ pub mod parser; pub mod protobuf; pub mod errors { - pub use error_code::ErrorCode; + pub use flowy_error_code::ErrorCode; } diff --git a/shared-lib/lib-infra/Cargo.toml b/shared-lib/lib-infra/Cargo.toml index ee39ead175..6d3c5a2f1d 100644 --- a/shared-lib/lib-infra/Cargo.toml +++ b/shared-lib/lib-infra/Cargo.toml @@ -14,11 +14,38 @@ pin-project = "1.0" futures-core = { version = "0.3" } tokio = { version = "1.0", features = ["time", "rt"] } rand = "0.8.3" +serde = { version = "1.0", features = ["derive"]} +serde_json = "1.0" cmd_lib = { version = "1", optional = true } protoc-rust = { version = "2", optional = true } walkdir = { version = "2", optional = true } +flowy-ast = { path = "../flowy-ast", optional = true} +similar = { version = "1.2.2", optional = true } +syn = { version = "1.0.60", features = ["extra-traits", "parsing", "derive", "full"], optional = true } +fancy-regex = { version = "0.5.0", optional = true } +lazy_static = { version = "1.4.0", optional = true } +tera = { version = "1.5.0", optional = true} +itertools = { version = "0.10", optional = true } +phf = { version = "0.8.0", features = ["macros"], optional = true } +console = {version = "0.14.0", optional = true} + +toml = {version = "0.5.8", optional = true} + [features] +proto_gen = [ + "flowy-ast", + "similar", + "syn", + "fancy-regex", + "lazy_static", + "tera", + "itertools", + "phf", + "walkdir", + "console", + "toml" +] pb_gen = ["cmd_lib", "protoc-rust", "walkdir"] -dart = [] \ No newline at end of file +dart = ["proto_gen"] \ No newline at end of file diff --git a/shared-lib/lib-infra/src/lib.rs b/shared-lib/lib-infra/src/lib.rs index dabb895f51..fbe9b11486 100644 --- a/shared-lib/lib-infra/src/lib.rs +++ b/shared-lib/lib-infra/src/lib.rs @@ -2,7 +2,10 @@ pub mod future; pub mod retry; #[cfg(feature = "pb_gen")] -pub mod pb_gen; +pub mod pb; + +#[cfg(feature = "proto_gen")] +pub mod proto_gen; #[allow(dead_code)] pub fn uuid_string() -> String { diff --git a/shared-lib/lib-infra/src/pb_gen.rs b/shared-lib/lib-infra/src/pb.rs similarity index 67% rename from shared-lib/lib-infra/src/pb_gen.rs rename to shared-lib/lib-infra/src/pb.rs index 33e2179b0a..650d233ef7 100644 --- a/shared-lib/lib-infra/src/pb_gen.rs +++ b/shared-lib/lib-infra/src/pb.rs @@ -1,15 +1,22 @@ -#![allow(clippy::all)] #![allow(unused_imports)] #![allow(unused_attributes)] #![allow(dead_code)] + +#[cfg(feature = "proto_gen")] +use crate::proto_gen::*; +use log::info; use std::fs::File; use std::io::Write; use std::process::Command; use walkdir::WalkDir; -pub fn gen(name: &str, root: &str) { +pub fn gen_files(crate_name: &str, root: &str) { + #[cfg(feature = "proto_gen")] + let _ = gen_protos(crate_name); + let mut paths = vec![]; let mut file_names = vec![]; + for (path, file_name) in WalkDir::new(root).into_iter().filter_map(|e| e.ok()).map(|e| { let path = e.path().to_str().unwrap().to_string(); let file_name = e.path().file_stem().unwrap().to_str().unwrap().to_string(); @@ -23,9 +30,8 @@ pub fn gen(name: &str, root: &str) { } } println!("cargo:rerun-if-changed=build.rs"); - #[cfg(feature = "dart")] - gen_pb_for_dart(name, root, &paths, &file_names); + gen_pb_for_dart(crate_name, root, &paths, &file_names); protoc_rust::Codegen::new() .out_dir("./src/protobuf/model") @@ -37,12 +43,19 @@ pub fn gen(name: &str, root: &str) { #[cfg(feature = "dart")] fn gen_pb_for_dart(name: &str, root: &str, paths: &Vec, file_names: &Vec) { - let output = format!( - "{}/{}/{}", - env!("CARGO_MAKE_WORKING_DIRECTORY"), - env!("FLUTTER_FLOWY_SDK_PATH"), - name - ); + if std::env::var("CARGO_MAKE_WORKING_DIRECTORY").is_err() { + log::warn!("CARGO_MAKE_WORKING_DIRECTORY was not set, skip generate dart pb"); + return; + } + + if std::env::var("FLUTTER_FLOWY_SDK_PATH").is_err() { + log::warn!("FLUTTER_FLOWY_SDK_PATH was not set, skip generate dart pb"); + return; + } + + let workspace_dir = std::env::var("CARGO_MAKE_WORKING_DIRECTORY").unwrap(); + let flutter_sdk_path = std::env::var("FLUTTER_FLOWY_SDK_PATH").unwrap(); + let output = format!("{}/{}/{}", workspace_dir, flutter_sdk_path, name); if !std::path::Path::new(&output).exists() { std::fs::create_dir_all(&output).unwrap(); } @@ -112,3 +125,24 @@ fn run_command(cmd: &str) -> bool { }; output.success() } + +#[cfg(feature = "proto_gen")] +fn gen_protos(crate_name: &str) -> Vec { + let cache_path = env!("CARGO_MANIFEST_DIR"); + let root = std::fs::canonicalize(".").unwrap().as_path().display().to_string(); + let crate_context = ProtoGenerator::gen(crate_name, &root, cache_path); + let proto_crates = crate_context + .iter() + .map(|info| info.protobuf_crate.clone()) + .collect::>(); + + crate_context + .into_iter() + .map(|info| info.files) + .flatten() + .for_each(|file| { + println!("cargo:rerun-if-changed={}", file.file_path); + }); + + proto_crates +} diff --git a/shared-lib/lib-infra/src/proto_gen/ast.rs b/shared-lib/lib-infra/src/proto_gen/ast.rs new file mode 100644 index 0000000000..d61d454240 --- /dev/null +++ b/shared-lib/lib-infra/src/proto_gen/ast.rs @@ -0,0 +1,184 @@ +#![allow(unused_attributes)] +#![allow(dead_code)] +#![allow(unused_imports)] +#![allow(unused_results)] +use crate::proto_gen::template::{EnumTemplate, StructTemplate}; +use crate::proto_gen::util::*; +use crate::proto_gen::{parse_crate_info_from_path, ProtoFile, ProtobufCrateContext}; +use fancy_regex::Regex; +use flowy_ast::*; +use lazy_static::lazy_static; +use std::{fs::File, io::Read, path::Path}; +use syn::Item; +use walkdir::WalkDir; + +pub fn parse_crate_protobuf(roots: Vec) -> Vec { + let crate_infos = parse_crate_info_from_path(roots); + crate_infos + .into_iter() + .map(|crate_info| { + let proto_output_dir = crate_info.proto_output_dir(); + let files = crate_info + .proto_paths + .iter() + .map(|proto_crate_path| parse_files_protobuf(proto_crate_path, &proto_output_dir)) + .flatten() + .collect::>(); + + ProtobufCrateContext::from_crate_info(crate_info, files) + }) + .collect::>() +} + +fn parse_files_protobuf(proto_crate_path: &str, proto_output_dir: &str) -> Vec { + let mut gen_proto_vec: Vec = vec![]; + // file_stem https://doc.rust-lang.org/std/path/struct.Path.html#method.file_stem + for (path, file_name) in WalkDir::new(proto_crate_path) + .into_iter() + .filter_entry(|e| !is_hidden(e)) + .filter_map(|e| e.ok()) + .filter(|e| !e.file_type().is_dir()) + .map(|e| { + let path = e.path().to_str().unwrap().to_string(); + let file_name = e.path().file_stem().unwrap().to_str().unwrap().to_string(); + (path, file_name) + }) + { + if file_name == "mod" { + continue; + } + + // https://docs.rs/syn/1.0.54/syn/struct.File.html + let ast = syn::parse_file(read_file(&path).unwrap().as_ref()) + .unwrap_or_else(|_| panic!("Unable to parse file at {}", path)); + let structs = get_ast_structs(&ast); + let proto_file_path = format!("{}/{}.proto", &proto_output_dir, &file_name); + let mut proto_file_content = parse_or_init_proto_file(proto_file_path.as_ref()); + + structs.iter().for_each(|s| { + let mut struct_template = StructTemplate::new(); + struct_template.set_message_struct_name(&s.name); + + s.fields.iter().filter(|f| f.attrs.pb_index().is_some()).for_each(|f| { + struct_template.set_field(f); + }); + + let s = struct_template.render().unwrap(); + proto_file_content.push_str(s.as_ref()); + proto_file_content.push('\n'); + }); + + let enums = get_ast_enums(&ast); + enums.iter().for_each(|e| { + let mut enum_template = EnumTemplate::new(); + enum_template.set_message_enum(e); + let s = enum_template.render().unwrap(); + proto_file_content.push_str(s.as_ref()); + proto_file_content.push('\n'); + }); + + if !enums.is_empty() || !structs.is_empty() { + let info = ProtoFile { + file_path: path.clone(), + file_name: file_name.clone(), + structs: structs.iter().map(|s| s.name.clone()).collect(), + enums: enums.iter().map(|e| e.name.clone()).collect(), + generated_content: proto_file_content.clone(), + }; + gen_proto_vec.push(info); + } + } + + gen_proto_vec +} + +pub fn parse_or_init_proto_file(path: &str) -> String { + let mut proto_file_content = String::new(); + let imported_content = find_proto_file_import(path); + proto_file_content.push_str(imported_content.as_ref()); + proto_file_content.push('\n'); + proto_file_content +} + +pub fn get_ast_structs(ast: &syn::File) -> Vec { + // let mut content = format!("{:#?}", &ast); + // let mut file = File::create("./foo.txt").unwrap(); + // file.write_all(content.as_bytes()).unwrap(); + let ctxt = Ctxt::new(); + let mut proto_structs: Vec = vec![]; + ast.items.iter().for_each(|item| { + if let Item::Struct(item_struct) = item { + let (_, fields) = struct_from_ast(&ctxt, &item_struct.fields); + + if fields.iter().filter(|f| f.attrs.pb_index().is_some()).count() > 0 { + proto_structs.push(Struct { + name: item_struct.ident.to_string(), + fields, + }); + } + } + }); + ctxt.check().unwrap(); + proto_structs +} + +pub fn get_ast_enums(ast: &syn::File) -> Vec { + let mut flowy_enums: Vec = vec![]; + let ctxt = Ctxt::new(); + + ast.items.iter().for_each(|item| { + // https://docs.rs/syn/1.0.54/syn/enum.Item.html + if let Item::Enum(item_enum) = item { + let attrs = flowy_ast::enum_from_ast(&ctxt, &item_enum.ident, &item_enum.variants, &ast.attrs); + flowy_enums.push(FlowyEnum { + name: item_enum.ident.to_string(), + attrs, + }); + } + }); + ctxt.check().unwrap(); + flowy_enums +} + +pub struct FlowyEnum<'a> { + pub name: String, + pub attrs: Vec>, +} + +pub struct Struct<'a> { + pub name: String, + pub fields: Vec>, +} + +lazy_static! { + static ref SYNTAX_REGEX: Regex = Regex::new("syntax.*;").unwrap(); + static ref IMPORT_REGEX: Regex = Regex::new("(import\\s).*;").unwrap(); +} + +fn find_proto_file_import(path: &str) -> String { + let mut result = String::new(); + if !Path::new(path).exists() { + // log::error!("{} not exist", path); + result = String::from("syntax = \"proto3\";"); + return result; + } + + let mut file = File::open(path).unwrap(); + let mut content = String::new(); + file.read_to_string(&mut content).unwrap(); + + content.lines().for_each(|line| { + ////Result>> + if let Ok(Some(m)) = SYNTAX_REGEX.find(line) { + result.push_str(m.as_str()); + result.push('\n'); + } + + if let Ok(Some(m)) = IMPORT_REGEX.find(line) { + result.push_str(m.as_str()); + result.push('\n'); + } + }); + + result +} diff --git a/shared-lib/lib-infra/src/proto_gen/flowy_toml.rs b/shared-lib/lib-infra/src/proto_gen/flowy_toml.rs new file mode 100644 index 0000000000..0c38166fcb --- /dev/null +++ b/shared-lib/lib-infra/src/proto_gen/flowy_toml.rs @@ -0,0 +1,52 @@ +use std::fs; + +#[derive(serde::Deserialize)] +pub struct FlowyConfig { + pub proto_crates: Vec, + pub event_files: Vec, +} + +impl FlowyConfig { + pub fn from_toml_file(path: &str) -> Self { + let content = fs::read_to_string(path).unwrap(); + let config: FlowyConfig = toml::from_str(content.as_ref()).unwrap(); + config + } +} + +pub struct CrateConfig { + pub(crate) crate_path: String, + pub(crate) folder_name: String, + pub(crate) flowy_config: FlowyConfig, +} + +impl CrateConfig { + pub fn proto_paths(&self) -> Vec { + let proto_paths = self + .flowy_config + .proto_crates + .iter() + .map(|name| format!("{}/{}", self.crate_path, name)) + .collect::>(); + proto_paths + } +} + +pub fn parse_crate_config_from(entry: &walkdir::DirEntry) -> Option { + let path = entry.path().parent().unwrap(); + let crate_path = path.to_str().unwrap().to_string(); + let folder_name = path.file_stem().unwrap().to_str().unwrap().to_string(); + let config_path = format!("{}/Flowy.toml", crate_path); + + if !std::path::Path::new(&config_path).exists() { + return None; + } + + let flowy_config = FlowyConfig::from_toml_file(config_path.as_ref()); + + Some(CrateConfig { + crate_path, + folder_name, + flowy_config, + }) +} diff --git a/shared-lib/lib-infra/src/proto_gen/mod.rs b/shared-lib/lib-infra/src/proto_gen/mod.rs new file mode 100644 index 0000000000..4d2f7c902b --- /dev/null +++ b/shared-lib/lib-infra/src/proto_gen/mod.rs @@ -0,0 +1,10 @@ +#![allow(clippy::module_inception)] +mod ast; +mod flowy_toml; +mod proto_gen; +mod proto_info; +mod template; +pub mod util; + +pub use proto_gen::*; +pub use proto_info::*; diff --git a/shared-lib/lib-infra/src/proto_gen/proto_gen.rs b/shared-lib/lib-infra/src/proto_gen/proto_gen.rs new file mode 100644 index 0000000000..bbeea67299 --- /dev/null +++ b/shared-lib/lib-infra/src/proto_gen/proto_gen.rs @@ -0,0 +1,113 @@ +#![allow(unused_attributes)] +#![allow(dead_code)] +#![allow(unused_imports)] +#![allow(unused_results)] +use crate::proto_gen::ast::parse_crate_protobuf; +use crate::proto_gen::proto_info::ProtobufCrateContext; +use crate::proto_gen::util::*; +use crate::proto_gen::ProtoFile; +use std::fs::File; +use std::path::Path; +use std::{fs::OpenOptions, io::Write}; + +pub(crate) struct ProtoGenerator(); +impl ProtoGenerator { + pub(crate) fn gen(crate_name: &str, crate_path: &str, cache_path: &str) -> Vec { + let crate_contexts = parse_crate_protobuf(vec![crate_path.to_owned()]); + write_proto_files(&crate_contexts); + write_rust_crate_mod_file(&crate_contexts); + for crate_info in &crate_contexts { + let _ = crate_info.protobuf_crate.create_output_dir(); + let _ = crate_info.protobuf_crate.proto_output_dir(); + crate_info.create_crate_mod_file(); + } + + let cache = ProtoCache::from_crate_contexts(&crate_contexts); + let cache_str = serde_json::to_string(&cache).unwrap(); + let cache_dir = format!("{}/.cache/{}", cache_path, crate_name); + if !Path::new(&cache_dir).exists() { + std::fs::create_dir_all(&cache_dir).unwrap(); + } + + let protobuf_cache_path = format!("{}/proto_cache", cache_dir); + match std::fs::OpenOptions::new() + .create(true) + .write(true) + .append(false) + .truncate(true) + .open(&protobuf_cache_path) + { + Ok(ref mut file) => { + file.write_all(cache_str.as_bytes()).unwrap(); + File::flush(file).unwrap(); + } + Err(_err) => { + panic!("Failed to open file: {}", protobuf_cache_path); + } + } + + crate_contexts + } +} + +fn write_proto_files(crate_contexts: &[ProtobufCrateContext]) { + for context in crate_contexts { + let dir = context.protobuf_crate.proto_output_dir(); + context.files.iter().for_each(|info| { + let proto_file_path = format!("{}/{}.proto", dir, &info.file_name); + save_content_to_file_with_diff_prompt(&info.generated_content, proto_file_path.as_ref()); + }); + } +} + +fn write_rust_crate_mod_file(crate_contexts: &[ProtobufCrateContext]) { + for context in crate_contexts { + let mod_path = context.protobuf_crate.proto_model_mod_file(); + match OpenOptions::new() + .create(true) + .write(true) + .append(false) + .truncate(true) + .open(&mod_path) + { + Ok(ref mut file) => { + let mut mod_file_content = String::new(); + + mod_file_content.push_str("#![cfg_attr(rustfmt, rustfmt::skip)]\n"); + mod_file_content.push_str("// Auto-generated, do not edit\n"); + walk_dir( + context.protobuf_crate.proto_output_dir().as_ref(), + |e| !e.file_type().is_dir(), + |_, name| { + let c = format!("\nmod {};\npub use {}::*;\n", &name, &name); + mod_file_content.push_str(c.as_ref()); + }, + ); + file.write_all(mod_file_content.as_bytes()).unwrap(); + } + Err(err) => { + panic!("Failed to open file: {}", err); + } + } + } +} + +#[derive(serde::Serialize, serde::Deserialize)] +pub struct ProtoCache { + pub structs: Vec, + pub enums: Vec, +} + +impl ProtoCache { + fn from_crate_contexts(crate_contexts: &[ProtobufCrateContext]) -> Self { + let proto_files = crate_contexts + .iter() + .map(|crate_info| &crate_info.files) + .flatten() + .collect::>(); + + let structs: Vec = proto_files.iter().map(|info| info.structs.clone()).flatten().collect(); + let enums: Vec = proto_files.iter().map(|info| info.enums.clone()).flatten().collect(); + Self { structs, enums } + } +} diff --git a/shared-lib/lib-infra/src/proto_gen/proto_info.rs b/shared-lib/lib-infra/src/proto_gen/proto_info.rs new file mode 100644 index 0000000000..32b05e106c --- /dev/null +++ b/shared-lib/lib-infra/src/proto_gen/proto_info.rs @@ -0,0 +1,142 @@ +#![allow(dead_code)] +use crate::proto_gen::flowy_toml::{parse_crate_config_from, CrateConfig}; +use crate::proto_gen::util::*; +use std::fs::OpenOptions; +use std::io::Write; +use walkdir::WalkDir; + +#[derive(Debug)] +pub struct ProtobufCrateContext { + pub files: Vec, + pub protobuf_crate: ProtobufCrate, +} + +impl ProtobufCrateContext { + pub fn from_crate_info(inner: ProtobufCrate, files: Vec) -> Self { + Self { + files, + protobuf_crate: inner, + } + } + + pub fn create_crate_mod_file(&self) { + // mod model; + // pub use model::*; + let mod_file_path = format!("{}/mod.rs", self.protobuf_crate.protobuf_crate_name()); + let mut content = "#![cfg_attr(rustfmt, rustfmt::skip)]\n".to_owned(); + content.push_str("// Auto-generated, do not edit\n"); + content.push_str("mod model;\npub use model::*;"); + match OpenOptions::new() + .create(true) + .write(true) + .append(false) + .truncate(true) + .open(&mod_file_path) + { + Ok(ref mut file) => { + file.write_all(content.as_bytes()).unwrap(); + } + Err(err) => { + panic!("Failed to open protobuf mod file: {}", err); + } + } + } + + #[allow(dead_code)] + pub fn flutter_mod_dir(&self, root: &str) -> String { + let crate_module_dir = format!("{}/{}", root, self.protobuf_crate.folder_name); + crate_module_dir + } + + #[allow(dead_code)] + pub fn flutter_mod_file(&self, root: &str) -> String { + let crate_module_dir = format!("{}/{}/protobuf.dart", root, self.protobuf_crate.folder_name); + crate_module_dir + } +} + +#[derive(Clone, Debug)] +pub struct ProtobufCrate { + pub folder_name: String, + pub proto_paths: Vec, + pub crate_path: String, +} + +impl ProtobufCrate { + pub fn from_config(config: CrateConfig) -> Self { + let proto_paths = config.proto_paths(); + ProtobufCrate { + folder_name: config.folder_name, + proto_paths, + crate_path: config.crate_path, + } + } + + fn protobuf_crate_name(&self) -> String { + format!("{}/src/protobuf", self.crate_path) + } + + pub fn proto_output_dir(&self) -> String { + let dir = format!("{}/proto", self.protobuf_crate_name()); + create_dir_if_not_exist(dir.as_ref()); + dir + } + + pub fn create_output_dir(&self) -> String { + let dir = format!("{}/model", self.protobuf_crate_name()); + create_dir_if_not_exist(dir.as_ref()); + dir + } + + pub fn proto_model_mod_file(&self) -> String { + format!("{}/mod.rs", self.create_output_dir()) + } +} + +#[derive(Debug)] +pub struct ProtoFile { + pub file_path: String, + pub file_name: String, + pub structs: Vec, + pub enums: Vec, + pub generated_content: String, +} + +pub fn parse_crate_info_from_path(roots: Vec) -> Vec { + let mut protobuf_crates: Vec = vec![]; + roots.iter().for_each(|root| { + let crates = WalkDir::new(root) + .into_iter() + .filter_entry(|e| !is_hidden(e)) + .filter_map(|e| e.ok()) + .filter(is_crate_dir) + .flat_map(|e| parse_crate_config_from(&e)) + .map(ProtobufCrate::from_config) + .collect::>(); + protobuf_crates.extend(crates); + }); + protobuf_crates +} + +pub struct FlutterProtobufInfo { + package_path: String, +} +impl FlutterProtobufInfo { + pub fn new(root: &str) -> Self { + FlutterProtobufInfo { + package_path: root.to_owned(), + } + } + + pub fn model_dir(&self) -> String { + let model_dir = format!("{}/protobuf", self.package_path); + create_dir_if_not_exist(model_dir.as_ref()); + model_dir + } + + #[allow(dead_code)] + pub fn mod_file_path(&self) -> String { + let mod_file_path = format!("{}/protobuf.dart", self.package_path); + mod_file_path + } +} diff --git a/shared-lib/lib-infra/src/proto_gen/template/derive_meta/derive_meta.rs b/shared-lib/lib-infra/src/proto_gen/template/derive_meta/derive_meta.rs new file mode 100644 index 0000000000..336e5c201c --- /dev/null +++ b/shared-lib/lib-infra/src/proto_gen/template/derive_meta/derive_meta.rs @@ -0,0 +1,35 @@ +use crate::proto_gen::template::get_tera; +use itertools::Itertools; +use tera::Context; + +pub struct ProtobufDeriveMeta { + context: Context, + structs: Vec, + enums: Vec, +} + +#[allow(dead_code)] +impl ProtobufDeriveMeta { + pub fn new(structs: Vec, enums: Vec) -> Self { + let enums: Vec<_> = enums.into_iter().unique().collect(); + ProtobufDeriveMeta { + context: Context::new(), + structs, + enums, + } + } + + pub fn render(&mut self) -> Option { + self.context.insert("names", &self.structs); + self.context.insert("enums", &self.enums); + + let tera = get_tera("derive_meta"); + match tera.render("derive_meta.tera", &self.context) { + Ok(r) => Some(r), + Err(e) => { + log::error!("{:?}", e); + None + } + } + } +} diff --git a/shared-lib/lib-infra/src/proto_gen/template/derive_meta/derive_meta.tera b/shared-lib/lib-infra/src/proto_gen/template/derive_meta/derive_meta.tera new file mode 100644 index 0000000000..a5204fbf41 --- /dev/null +++ b/shared-lib/lib-infra/src/proto_gen/template/derive_meta/derive_meta.tera @@ -0,0 +1,45 @@ +#![cfg_attr(rustfmt, rustfmt::skip)] +pub enum TypeCategory { + Array, + Map, + Str, + Protobuf, + Bytes, + Enum, + Opt, + Primitive, +} +// auto generate, do not edit +pub fn category_from_str(type_str: &str) -> TypeCategory { + match type_str { + "Vec" => TypeCategory::Array, + "HashMap" => TypeCategory::Map, + "u8" => TypeCategory::Bytes, + "String" => TypeCategory::Str, +{%- for name in names -%} + {%- if loop.first %} + "{{ name }}" + {%- else %} + | "{{ name }}" + {%- endif -%} + {%- if loop.last %} + => TypeCategory::Protobuf, + {%- endif %} + +{%- endfor %} + +{%- for enum in enums -%} + {%- if loop.first %} + "{{ enum }}" + {%- else %} + | "{{ enum }}" + {%- endif -%} + {%- if loop.last %} + => TypeCategory::Enum, + {%- endif %} +{%- endfor %} + + "Option" => TypeCategory::Opt, + _ => TypeCategory::Primitive, + } +} diff --git a/shared-lib/lib-infra/src/proto_gen/template/derive_meta/mod.rs b/shared-lib/lib-infra/src/proto_gen/template/derive_meta/mod.rs new file mode 100644 index 0000000000..70c2f17b55 --- /dev/null +++ b/shared-lib/lib-infra/src/proto_gen/template/derive_meta/mod.rs @@ -0,0 +1,4 @@ +#![allow(clippy::module_inception)] +mod derive_meta; + +pub use derive_meta::*; diff --git a/shared-lib/lib-infra/src/proto_gen/template/mod.rs b/shared-lib/lib-infra/src/proto_gen/template/mod.rs new file mode 100644 index 0000000000..a2ef4da1d5 --- /dev/null +++ b/shared-lib/lib-infra/src/proto_gen/template/mod.rs @@ -0,0 +1,47 @@ +mod derive_meta; +mod proto_file; + +pub use derive_meta::*; +pub use proto_file::*; +use std::fs::File; +use std::io::Read; +use tera::Tera; + +pub fn get_tera(directory: &str) -> Tera { + let mut root = format!("{}/src/proto_gen/template/", env!("CARGO_MANIFEST_DIR")); + root.push_str(directory); + + let root_absolute_path = match std::fs::canonicalize(&root) { + Ok(p) => p.as_path().display().to_string(), + Err(e) => { + panic!("❌ Canonicalize file path {} failed {:?}", root, e); + } + }; + + let mut template_path = format!("{}/**/*.tera", root_absolute_path); + if cfg!(windows) { + // remove "\\?\" prefix on windows + template_path = format!("{}/**/*.tera", &root_absolute_path[4..]); + } + + match Tera::new(template_path.as_ref()) { + Ok(t) => t, + Err(e) => { + log::error!("Parsing error(s): {}", e); + ::std::process::exit(1); + } + } +} + +#[allow(dead_code)] +pub fn read_file(path: &str) -> Option { + let mut file = File::open(path).unwrap_or_else(|_| panic!("Unable to open file at {}", path)); + let mut content = String::new(); + match file.read_to_string(&mut content) { + Ok(_) => Some(content), + Err(e) => { + log::error!("{}, with error: {:?}", path, e); + Some("".to_string()) + } + } +} diff --git a/shared-lib/lib-infra/src/proto_gen/template/proto_file/enum.tera b/shared-lib/lib-infra/src/proto_gen/template/proto_file/enum.tera new file mode 100644 index 0000000000..fd6878a7ec --- /dev/null +++ b/shared-lib/lib-infra/src/proto_gen/template/proto_file/enum.tera @@ -0,0 +1,5 @@ +enum {{ enum_name }} { + {%- for item in items %} + {{ item }} + {%- endfor %} +} \ No newline at end of file diff --git a/shared-lib/lib-infra/src/proto_gen/template/proto_file/enum_template.rs b/shared-lib/lib-infra/src/proto_gen/template/proto_file/enum_template.rs new file mode 100644 index 0000000000..404b3eb88b --- /dev/null +++ b/shared-lib/lib-infra/src/proto_gen/template/proto_file/enum_template.rs @@ -0,0 +1,38 @@ +use crate::proto_gen::ast::FlowyEnum; +use crate::proto_gen::template::get_tera; +use tera::Context; + +pub struct EnumTemplate { + context: Context, + items: Vec, +} + +#[allow(dead_code)] +impl EnumTemplate { + pub fn new() -> Self { + EnumTemplate { + context: Context::new(), + items: vec![], + } + } + + pub fn set_message_enum(&mut self, flowy_enum: &FlowyEnum) { + self.context.insert("enum_name", &flowy_enum.name); + flowy_enum.attrs.iter().for_each(|item| { + self.items + .push(format!("{} = {};", item.attrs.enum_item_name, item.attrs.value)) + }) + } + + pub fn render(&mut self) -> Option { + self.context.insert("items", &self.items); + let tera = get_tera("proto_file"); + match tera.render("enum.tera", &self.context) { + Ok(r) => Some(r), + Err(e) => { + log::error!("{:?}", e); + None + } + } + } +} diff --git a/shared-lib/lib-infra/src/proto_gen/template/proto_file/mod.rs b/shared-lib/lib-infra/src/proto_gen/template/proto_file/mod.rs new file mode 100644 index 0000000000..bcdd287ce5 --- /dev/null +++ b/shared-lib/lib-infra/src/proto_gen/template/proto_file/mod.rs @@ -0,0 +1,5 @@ +mod enum_template; +mod struct_template; + +pub use enum_template::*; +pub use struct_template::*; diff --git a/shared-lib/lib-infra/src/proto_gen/template/proto_file/struct.tera b/shared-lib/lib-infra/src/proto_gen/template/proto_file/struct.tera new file mode 100644 index 0000000000..ddeb49153a --- /dev/null +++ b/shared-lib/lib-infra/src/proto_gen/template/proto_file/struct.tera @@ -0,0 +1,5 @@ +message {{ struct_name }} { + {%- for field in fields %} + {{ field }} + {%- endfor %} +} \ No newline at end of file diff --git a/shared-lib/lib-infra/src/proto_gen/template/proto_file/struct_template.rs b/shared-lib/lib-infra/src/proto_gen/template/proto_file/struct_template.rs new file mode 100644 index 0000000000..d7c0568561 --- /dev/null +++ b/shared-lib/lib-infra/src/proto_gen/template/proto_file/struct_template.rs @@ -0,0 +1,107 @@ +use flowy_ast::*; +use phf::phf_map; + +use crate::proto_gen::template::get_tera; +use tera::Context; + +// Protobuf data type : https://developers.google.com/protocol-buffers/docs/proto3 +static RUST_TYPE_MAP: phf::Map<&'static str, &'static str> = phf_map! { + "String" => "string", + "i64" => "int64", + "i32" => "int32", + "u64" => "uint64", + "u32" => "uint32", + "Vec" => "repeated", + "f64" => "double", + "HashMap" => "map", +}; + +pub struct StructTemplate { + context: Context, + fields: Vec, +} + +#[allow(dead_code)] +impl StructTemplate { + pub fn new() -> Self { + StructTemplate { + context: Context::new(), + fields: vec![], + } + } + + pub fn set_message_struct_name(&mut self, name: &str) { + self.context.insert("struct_name", name); + } + + pub fn set_field(&mut self, field: &ASTField) { + // {{ field_type }} {{ field_name }} = {{index}}; + let name = field.name().unwrap().to_string(); + let index = field.attrs.pb_index().unwrap(); + + let ty: &str = &field.ty_as_str(); + let mut mapped_ty: &str = ty; + + if RUST_TYPE_MAP.contains_key(ty) { + mapped_ty = RUST_TYPE_MAP[ty]; + } + + if let Some(ref category) = field.bracket_category { + match category { + BracketCategory::Opt => match &field.bracket_inner_ty { + None => {} + Some(inner_ty) => match inner_ty.to_string().as_str() { + //TODO: support hashmap or something else wrapped by Option + "Vec" => { + self.fields + .push(format!("oneof one_of_{} {{ bytes {} = {}; }};", name, name, index)); + } + _ => { + self.fields.push(format!( + "oneof one_of_{} {{ {} {} = {}; }};", + name, mapped_ty, name, index + )); + } + }, + }, + BracketCategory::Map((k, v)) => { + let key: &str = k; + let value: &str = v; + self.fields.push(format!( + // map attrs = 1; + "map<{}, {}> {} = {};", + RUST_TYPE_MAP.get(key).unwrap_or(&key), + RUST_TYPE_MAP.get(value).unwrap_or(&value), + name, + index + )); + } + BracketCategory::Vec => { + let bracket_ty: &str = &field.bracket_ty.as_ref().unwrap().to_string(); + // Vec + if mapped_ty == "u8" && bracket_ty == "Vec" { + self.fields.push(format!("bytes {} = {};", name, index)) + } else { + self.fields.push(format!( + "{} {} {} = {};", + RUST_TYPE_MAP[bracket_ty], mapped_ty, name, index + )) + } + } + BracketCategory::Other => self.fields.push(format!("{} {} = {};", mapped_ty, name, index)), + } + } + } + + pub fn render(&mut self) -> Option { + self.context.insert("fields", &self.fields); + let tera = get_tera("proto_file"); + match tera.render("struct.tera", &self.context) { + Ok(r) => Some(r), + Err(e) => { + log::error!("{:?}", e); + None + } + } + } +} diff --git a/shared-lib/lib-infra/src/proto_gen/util.rs b/shared-lib/lib-infra/src/proto_gen/util.rs new file mode 100644 index 0000000000..8c8f8282f1 --- /dev/null +++ b/shared-lib/lib-infra/src/proto_gen/util.rs @@ -0,0 +1,128 @@ +use console::Style; + +use similar::{ChangeTag, TextDiff}; +use std::{ + fs::{File, OpenOptions}, + io::{Read, Write}, + path::Path, +}; +use walkdir::WalkDir; + +pub fn read_file(path: &str) -> Option { + let mut file = File::open(path).unwrap_or_else(|_| panic!("Unable to open file at {}", path)); + let mut content = String::new(); + match file.read_to_string(&mut content) { + Ok(_) => Some(content), + Err(e) => { + log::error!("{}, with error: {:?}", path, e); + Some("".to_string()) + } + } +} + +pub fn save_content_to_file_with_diff_prompt(content: &str, output_file: &str) { + if Path::new(output_file).exists() { + let old_content = read_file(output_file).unwrap(); + let new_content = content.to_owned(); + let write_to_file = || match OpenOptions::new() + .create(true) + .write(true) + .append(false) + .truncate(true) + .open(output_file) + { + Ok(ref mut file) => { + file.write_all(new_content.as_bytes()).unwrap(); + } + Err(err) => { + panic!("Failed to open log file: {}", err); + } + }; + if new_content != old_content { + print_diff(old_content, new_content.clone()); + write_to_file() + } + } else { + match OpenOptions::new().create(true).write(true).open(output_file) { + Ok(ref mut file) => file.write_all(content.as_bytes()).unwrap(), + Err(err) => panic!("Open or create to {} fail: {}", output_file, err), + } + } +} + +pub fn print_diff(old_content: String, new_content: String) { + let diff = TextDiff::from_lines(&old_content, &new_content); + for op in diff.ops() { + for change in diff.iter_changes(op) { + let (sign, style) = match change.tag() { + ChangeTag::Delete => ("-", Style::new().red()), + ChangeTag::Insert => ("+", Style::new().green()), + ChangeTag::Equal => (" ", Style::new()), + }; + + match change.tag() { + ChangeTag::Delete => { + print!("{}{}", style.apply_to(sign).bold(), style.apply_to(change)); + } + ChangeTag::Insert => { + print!("{}{}", style.apply_to(sign).bold(), style.apply_to(change)); + } + ChangeTag::Equal => {} + }; + } + println!("---------------------------------------------------"); + } +} + +#[allow(dead_code)] +pub fn is_crate_dir(e: &walkdir::DirEntry) -> bool { + let cargo = e.path().file_stem().unwrap().to_str().unwrap().to_string(); + cargo == *"Cargo" +} + +#[allow(dead_code)] +pub fn is_proto_file(e: &walkdir::DirEntry) -> bool { + if e.path().extension().is_none() { + return false; + } + let ext = e.path().extension().unwrap().to_str().unwrap().to_string(); + ext == *"proto" +} + +pub fn is_hidden(entry: &walkdir::DirEntry) -> bool { + entry.file_name().to_str().map(|s| s.starts_with('.')).unwrap_or(false) +} + +pub fn create_dir_if_not_exist(dir: &str) { + if !std::path::Path::new(&dir).exists() { + std::fs::create_dir_all(&dir).unwrap(); + } +} + +#[allow(dead_code)] +pub(crate) fn walk_dir(dir: &str, filter: F2, mut path_and_name: F1) +where + F1: FnMut(String, String), + F2: Fn(&walkdir::DirEntry) -> bool, +{ + for (path, name) in WalkDir::new(dir) + .into_iter() + .filter_map(|e| e.ok()) + .filter(|e| filter(e)) + .map(|e| { + ( + e.path().to_str().unwrap().to_string(), + e.path().file_stem().unwrap().to_str().unwrap().to_string(), + ) + }) + { + path_and_name(path, name); + } +} + +#[allow(dead_code)] +pub fn suffix_relative_to_path(path: &str, base: &str) -> String { + let base = Path::new(base); + let path = Path::new(path); + path.strip_prefix(base).unwrap().to_str().unwrap().to_owned() +} diff --git a/shared-lib/lib-ws/build.rs b/shared-lib/lib-ws/build.rs index aebe8041a2..ef2b12f93d 100644 --- a/shared-lib/lib-ws/build.rs +++ b/shared-lib/lib-ws/build.rs @@ -1,5 +1,5 @@ -use lib_infra::pb_gen; +use lib_infra::pb; fn main() { - pb_gen::gen("lib-ws", "./src/protobuf/proto"); + pb::gen_files(env!("CARGO_PKG_NAME"), "./src/protobuf/proto"); }