Pārlūkot izejas kodu

auto generate crate protobuf file and model

appflowy 3 gadi atpakaļ
vecāks
revīzija
f64bd55a33

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


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

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

+ 295 - 0
rust-lib/flowy-user/src/protobuf/model/user.rs

@@ -0,0 +1,295 @@
+// This file is generated by rust-protobuf 2.22.1. Do not edit
+// @generated
+
+// https://github.com/rust-lang/rust-clippy/issues/702
+#![allow(unknown_lints)]
+#![allow(clippy::all)]
+
+#![allow(unused_attributes)]
+#![cfg_attr(rustfmt, rustfmt::skip)]
+
+#![allow(box_pointers)]
+#![allow(dead_code)]
+#![allow(missing_docs)]
+#![allow(non_camel_case_types)]
+#![allow(non_snake_case)]
+#![allow(non_upper_case_globals)]
+#![allow(trivial_casts)]
+#![allow(unused_imports)]
+#![allow(unused_results)]
+//! Generated file from `user.proto`
+
+/// Generated files are compatible only with the same version
+/// of protobuf runtime.
+// const _PROTOBUF_VERSION_CHECK: () = ::protobuf::VERSION_2_22_1;
+
+#[derive(PartialEq,Clone,Default)]
+pub struct App {
+    // message fields
+    pub id: ::std::string::String,
+    pub workspace_id: ::std::string::String,
+    pub name: ::std::string::String,
+    // special fields
+    pub unknown_fields: ::protobuf::UnknownFields,
+    pub cached_size: ::protobuf::CachedSize,
+}
+
+impl<'a> ::std::default::Default for &'a App {
+    fn default() -> &'a App {
+        <App as ::protobuf::Message>::default_instance()
+    }
+}
+
+impl App {
+    pub fn new() -> App {
+        ::std::default::Default::default()
+    }
+
+    // string id = 1;
+
+
+    pub fn get_id(&self) -> &str {
+        &self.id
+    }
+    pub fn clear_id(&mut self) {
+        self.id.clear();
+    }
+
+    // Param is passed by value, moved
+    pub fn set_id(&mut self, v: ::std::string::String) {
+        self.id = v;
+    }
+
+    // Mutable pointer to the field.
+    // If field is not initialized, it is initialized with default value first.
+    pub fn mut_id(&mut self) -> &mut ::std::string::String {
+        &mut self.id
+    }
+
+    // Take field
+    pub fn take_id(&mut self) -> ::std::string::String {
+        ::std::mem::replace(&mut self.id, ::std::string::String::new())
+    }
+
+    // string workspace_id = 2;
+
+
+    pub fn get_workspace_id(&self) -> &str {
+        &self.workspace_id
+    }
+    pub fn clear_workspace_id(&mut self) {
+        self.workspace_id.clear();
+    }
+
+    // Param is passed by value, moved
+    pub fn set_workspace_id(&mut self, v: ::std::string::String) {
+        self.workspace_id = v;
+    }
+
+    // Mutable pointer to the field.
+    // If field is not initialized, it is initialized with default value first.
+    pub fn mut_workspace_id(&mut self) -> &mut ::std::string::String {
+        &mut self.workspace_id
+    }
+
+    // Take field
+    pub fn take_workspace_id(&mut self) -> ::std::string::String {
+        ::std::mem::replace(&mut self.workspace_id, ::std::string::String::new())
+    }
+
+    // string name = 3;
+
+
+    pub fn get_name(&self) -> &str {
+        &self.name
+    }
+    pub fn clear_name(&mut self) {
+        self.name.clear();
+    }
+
+    // Param is passed by value, moved
+    pub fn set_name(&mut self, v: ::std::string::String) {
+        self.name = v;
+    }
+
+    // Mutable pointer to the field.
+    // If field is not initialized, it is initialized with default value first.
+    pub fn mut_name(&mut self) -> &mut ::std::string::String {
+        &mut self.name
+    }
+
+    // Take field
+    pub fn take_name(&mut self) -> ::std::string::String {
+        ::std::mem::replace(&mut self.name, ::std::string::String::new())
+    }
+}
+
+impl ::protobuf::Message for App {
+    fn is_initialized(&self) -> bool {
+        true
+    }
+
+    fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::ProtobufResult<()> {
+        while !is.eof()? {
+            let (field_number, wire_type) = is.read_tag_unpack()?;
+            match field_number {
+                1 => {
+                    ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.id)?;
+                },
+                2 => {
+                    ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.workspace_id)?;
+                },
+                3 => {
+                    ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.name)?;
+                },
+                _ => {
+                    ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?;
+                },
+            };
+        }
+        ::std::result::Result::Ok(())
+    }
+
+    // Compute sizes of nested messages
+    #[allow(unused_variables)]
+    fn compute_size(&self) -> u32 {
+        let mut my_size = 0;
+        if !self.id.is_empty() {
+            my_size += ::protobuf::rt::string_size(1, &self.id);
+        }
+        if !self.workspace_id.is_empty() {
+            my_size += ::protobuf::rt::string_size(2, &self.workspace_id);
+        }
+        if !self.name.is_empty() {
+            my_size += ::protobuf::rt::string_size(3, &self.name);
+        }
+        my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields());
+        self.cached_size.set(my_size);
+        my_size
+    }
+
+    fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::ProtobufResult<()> {
+        if !self.id.is_empty() {
+            os.write_string(1, &self.id)?;
+        }
+        if !self.workspace_id.is_empty() {
+            os.write_string(2, &self.workspace_id)?;
+        }
+        if !self.name.is_empty() {
+            os.write_string(3, &self.name)?;
+        }
+        os.write_unknown_fields(self.get_unknown_fields())?;
+        ::std::result::Result::Ok(())
+    }
+
+    fn get_cached_size(&self) -> u32 {
+        self.cached_size.get()
+    }
+
+    fn get_unknown_fields(&self) -> &::protobuf::UnknownFields {
+        &self.unknown_fields
+    }
+
+    fn mut_unknown_fields(&mut self) -> &mut ::protobuf::UnknownFields {
+        &mut self.unknown_fields
+    }
+
+    fn as_any(&self) -> &dyn (::std::any::Any) {
+        self as &dyn (::std::any::Any)
+    }
+    fn as_any_mut(&mut self) -> &mut dyn (::std::any::Any) {
+        self as &mut dyn (::std::any::Any)
+    }
+    fn into_any(self: ::std::boxed::Box<Self>) -> ::std::boxed::Box<dyn (::std::any::Any)> {
+        self
+    }
+
+    fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor {
+        Self::descriptor_static()
+    }
+
+    fn new() -> App {
+        App::new()
+    }
+
+    fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor {
+        static descriptor: ::protobuf::rt::LazyV2<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::LazyV2::INIT;
+        descriptor.get(|| {
+            let mut fields = ::std::vec::Vec::new();
+            fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>(
+                "id",
+                |m: &App| { &m.id },
+                |m: &mut App| { &mut m.id },
+            ));
+            fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>(
+                "workspace_id",
+                |m: &App| { &m.workspace_id },
+                |m: &mut App| { &mut m.workspace_id },
+            ));
+            fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>(
+                "name",
+                |m: &App| { &m.name },
+                |m: &mut App| { &mut m.name },
+            ));
+            ::protobuf::reflect::MessageDescriptor::new_pb_name::<App>(
+                "App",
+                fields,
+                file_descriptor_proto()
+            )
+        })
+    }
+
+    fn default_instance() -> &'static App {
+        static instance: ::protobuf::rt::LazyV2<App> = ::protobuf::rt::LazyV2::INIT;
+        instance.get(App::new)
+    }
+}
+
+impl ::protobuf::Clear for App {
+    fn clear(&mut self) {
+        self.id.clear();
+        self.workspace_id.clear();
+        self.name.clear();
+        self.unknown_fields.clear();
+    }
+}
+
+impl ::std::fmt::Debug for App {
+    fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
+        ::protobuf::text_format::fmt(self, f)
+    }
+}
+
+impl ::protobuf::reflect::ProtobufValue for App {
+    fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef {
+        ::protobuf::reflect::ReflectValueRef::Message(self)
+    }
+}
+
+static file_descriptor_proto_data: &'static [u8] = b"\
+    \n\nuser.proto\"L\n\x03App\x12\x0e\n\x02id\x18\x01\x20\x01(\tR\x02id\x12\
+    !\n\x0cworkspace_id\x18\x02\x20\x01(\tR\x0bworkspaceId\x12\x12\n\x04name\
+    \x18\x03\x20\x01(\tR\x04nameJ\xcf\x01\n\x06\x12\x04\0\0\x06\x01\n\x08\n\
+    \x01\x0c\x12\x03\0\0\x12\n\n\n\x02\x04\0\x12\x04\x02\0\x06\x01\n\n\n\x03\
+    \x04\0\x01\x12\x03\x02\x08\x0b\n\x0b\n\x04\x04\0\x02\0\x12\x03\x03\x04\
+    \x12\n\x0c\n\x05\x04\0\x02\0\x05\x12\x03\x03\x04\n\n\x0c\n\x05\x04\0\x02\
+    \0\x01\x12\x03\x03\x0b\r\n\x0c\n\x05\x04\0\x02\0\x03\x12\x03\x03\x10\x11\
+    \n\x0b\n\x04\x04\0\x02\x01\x12\x03\x04\x04\x1c\n\x0c\n\x05\x04\0\x02\x01\
+    \x05\x12\x03\x04\x04\n\n\x0c\n\x05\x04\0\x02\x01\x01\x12\x03\x04\x0b\x17\
+    \n\x0c\n\x05\x04\0\x02\x01\x03\x12\x03\x04\x1a\x1b\n\x0b\n\x04\x04\0\x02\
+    \x02\x12\x03\x05\x04\x14\n\x0c\n\x05\x04\0\x02\x02\x05\x12\x03\x05\x04\n\
+    \n\x0c\n\x05\x04\0\x02\x02\x01\x12\x03\x05\x0b\x0f\n\x0c\n\x05\x04\0\x02\
+    \x02\x03\x12\x03\x05\x12\x13b\x06proto3\
+";
+
+static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;
+
+fn parse_descriptor_proto() -> ::protobuf::descriptor::FileDescriptorProto {
+    ::protobuf::Message::parse_from_bytes(file_descriptor_proto_data).unwrap()
+}
+
+pub fn file_descriptor_proto() -> &'static ::protobuf::descriptor::FileDescriptorProto {
+    file_descriptor_proto_lazy.get(|| {
+        parse_descriptor_proto()
+    })
+}

+ 7 - 0
rust-lib/flowy-user/src/protobuf/proto/user.proto

@@ -0,0 +1,7 @@
+syntax = "proto3";
+
+message App {
+    string id = 1;
+    string workspace_id = 2;
+    string name = 3;
+}

+ 1 - 0
scripts/flowy-tool/Cargo.toml

@@ -13,6 +13,7 @@ tera = { version = "1.5.0" }
 log = "0.4.11"
 env_logger = "0.8.2"
 shell = { git="https://github.com/google/rust-shell.git"}
+cmd_lib = "1.1"
 flowy-ast = { path = "../../rust-lib/flowy-ast" }
 console = "0.14.0"
 fancy-regex = "0.5.0"

+ 7 - 6
scripts/flowy-tool/src/main.rs

@@ -11,17 +11,18 @@ fn main() {
 
     if let Some(ref matches) = matches.subcommand_matches("pb-gen") {
         let rust_source = matches.value_of("rust_source").unwrap();
-        let build_cache = matches.value_of("build_cache").unwrap();
+        let derive_meta = matches.value_of("derive_meta").unwrap();
         let rust_mod_dir = matches.value_of("rust_mod_dir").unwrap();
         let flutter_mod_dir = matches.value_of("flutter_mod_dir").unwrap();
         let proto_file_output = matches.value_of("proto_file_output").unwrap();
 
-        proto::ProtoGen::new()
+        proto::ProtoGenBuilder::new()
             .set_rust_source_dir(rust_source)
-            .set_build_cache_dir(build_cache)
+            .set_derive_meta_dir(derive_meta)
             .set_rust_mod_dir(rust_mod_dir)
             .set_flutter_mod_dir(flutter_mod_dir)
             .set_proto_file_output_dir(proto_file_output)
+            .build()
             .gen();
     }
 }
@@ -38,11 +39,11 @@ pub fn app<'a, 'b>() -> App<'a, 'b> {
                     Arg::with_name("rust_source")
                         .long("rust_source")
                         .value_name("DIRECTORY")
-                        .help("The directory to the rust code"),
+                        .help("Directory of the cargo workspace"),
                 )
                 .arg(
-                    Arg::with_name("build_cache")
-                        .long("build_cache")
+                    Arg::with_name("derive_meta")
+                        .long("derive_meta")
                         .value_name("PATH")
                         .help("Caching information used by flowy-derive"),
                 )

+ 10 - 8
scripts/flowy-tool/src/proto/ast.rs

@@ -5,20 +5,22 @@ use flowy_ast::*;
 use syn::Item;
 use walkdir::WalkDir;
 
-pub fn parse_crate_protobuf(root: &str, proto_output_dir: &str) -> Vec<CrateProtoInfo> {
-    log::info!("Generate proto file from {}", root);
+pub fn parse_crate_protobuf(root: &str) -> Vec<CrateProtoInfo> {
     let domains_info = get_crate_domain_directory(root);
     domains_info
-        .iter()
-        .map(|domain| {
-            let files = parse_files_protobuf(&domain.path, proto_output_dir);
-            CrateProtoInfo::new(&domain, files)
+        .into_iter()
+        .map(|crate_info| {
+            let files = parse_files_protobuf(&crate_info);
+            CrateProtoInfo::from_crate_info(crate_info, files)
         })
         .collect::<Vec<CrateProtoInfo>>()
 }
 
-fn parse_files_protobuf(root: &str, proto_output_dir: &str) -> Vec<FileProtoInfo> {
+fn parse_files_protobuf(crate_info: &CrateInfo) -> Vec<FileProtoInfo> {
     let mut gen_proto_vec: Vec<FileProtoInfo> = vec![];
+    let root = crate_info.domain_path.as_str();
+    let proto_output_dir = crate_info.proto_file_output_dir();
+
     // file_stem https://doc.rust-lang.org/std/path/struct.Path.html#method.file_stem
     for (path, file_name) in WalkDir::new(root)
         .into_iter()
@@ -41,7 +43,7 @@ fn parse_files_protobuf(root: &str, proto_output_dir: &str) -> Vec<FileProtoInfo
         let structs = get_ast_structs(&ast);
 
         // println!("😁 {} - {}", path, file_name);
-        let proto_file_path = format!("{}/{}.proto", proto_output_dir, &file_name);
+        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| {

+ 56 - 0
scripts/flowy-tool/src/proto/builder.rs

@@ -0,0 +1,56 @@
+use crate::proto::ProtoGen;
+
+pub struct ProtoGenBuilder {
+    rust_source_dir: Option<String>,
+    proto_file_output_dir: Option<String>,
+    rust_mod_dir: Option<String>,
+    flutter_mod_dir: Option<String>,
+    derive_meta_dir: Option<String>,
+}
+
+impl ProtoGenBuilder {
+    pub fn new() -> Self {
+        ProtoGenBuilder {
+            rust_source_dir: None,
+            proto_file_output_dir: None,
+            rust_mod_dir: None,
+            flutter_mod_dir: None,
+            derive_meta_dir: None,
+        }
+    }
+
+    pub fn set_rust_source_dir(mut self, dir: &str) -> Self {
+        self.rust_source_dir = Some(dir.to_string());
+        self
+    }
+
+    pub fn set_proto_file_output_dir(mut self, dir: &str) -> Self {
+        self.proto_file_output_dir = Some(dir.to_string());
+        self
+    }
+
+    pub fn set_rust_mod_dir(mut self, dir: &str) -> Self {
+        self.rust_mod_dir = Some(dir.to_string());
+        self
+    }
+
+    pub fn set_flutter_mod_dir(mut self, dir: &str) -> Self {
+        self.flutter_mod_dir = Some(dir.to_string());
+        self
+    }
+
+    pub fn set_derive_meta_dir(mut self, dir: &str) -> Self {
+        self.derive_meta_dir = Some(dir.to_string());
+        self
+    }
+
+    pub fn build(self) -> ProtoGen {
+        ProtoGen {
+            rust_source_dir: self.rust_source_dir.unwrap(),
+            proto_file_output_dir: self.proto_file_output_dir.unwrap(),
+            rust_mod_dir: self.rust_mod_dir.unwrap(),
+            flutter_mod_dir: self.flutter_mod_dir.unwrap(),
+            derive_meta_dir: self.derive_meta_dir.unwrap(),
+        }
+    }
+}

+ 73 - 25
scripts/flowy-tool/src/proto/helper.rs

@@ -1,26 +1,51 @@
 use walkdir::WalkDir;
 
+#[derive(Clone)]
 pub struct CrateInfo {
-    pub name: String,
-    pub path: String,
+    pub crate_folder_name: String,
+    pub domain_path: String,
+    pub crate_path: String,
 }
 
 pub struct CrateProtoInfo {
     pub files: Vec<FileProtoInfo>,
-    pub name: String,
-    pub path: String,
+    pub inner: CrateInfo,
 }
 
-impl CrateProtoInfo {
-    pub fn new(info: &CrateInfo, files: Vec<FileProtoInfo>) -> Self {
-        Self {
-            files,
-            name: info.name.to_owned(),
-            path: info.path.to_owned(),
+impl CrateInfo {
+    fn protobuf_crate_name(&self) -> String {
+        format!("{}/src/protobuf", self.crate_path)
+    }
+
+    pub fn proto_file_output_dir(&self) -> String {
+        let dir = format!("{}/proto", self.protobuf_crate_name());
+        self.create_file_if_not_exist(dir.as_ref());
+        dir
+    }
+
+    pub fn proto_struct_output_dir(&self) -> String {
+        let dir = format!("{}/model", self.protobuf_crate_name());
+        self.create_file_if_not_exist(dir.as_ref());
+        dir
+    }
+
+    pub fn crate_mod_file(&self) -> String {
+        format!("{}/mod.rs", self.proto_struct_output_dir())
+    }
+
+    fn create_file_if_not_exist(&self, dir: &str) {
+        if !std::path::Path::new(&dir).exists() {
+            std::fs::create_dir_all(&dir).unwrap();
         }
     }
 }
 
+impl CrateProtoInfo {
+    pub fn from_crate_info(inner: CrateInfo, files: Vec<FileProtoInfo>) -> Self {
+        Self { files, inner }
+    }
+}
+
 #[derive(Debug)]
 pub struct FileProtoInfo {
     pub file_name: String,
@@ -34,21 +59,22 @@ pub fn get_crate_domain_directory(root: &str) -> Vec<CrateInfo> {
         .into_iter()
         .filter_entry(|e| !is_hidden(e))
         .filter_map(|e| e.ok())
-        .filter(|e| is_domain_dir(e))
-        .map(|e| CrateInfo {
-            //TODO: get the crate name from toml file
-            name: e
-                .path()
-                .parent()
-                .unwrap()
-                .parent()
-                .unwrap()
-                .file_stem()
-                .unwrap()
-                .to_str()
-                .unwrap()
-                .to_string(),
-            path: e.path().to_str().unwrap().to_string(),
+        .filter(|e| is_crate_dir(e))
+        .flat_map(|e| {
+            // Assert e.path().parent() will be the crate dir
+            let path = e.path().parent().unwrap();
+            let crate_folder_name = path.file_stem().unwrap().to_str().unwrap().to_string();
+            if crate_folder_name == "flowy-user".to_owned() {
+                let crate_path = path.to_str().unwrap().to_string();
+                let domain_path = format!("{}/src/domain", crate_path);
+                Some(CrateInfo {
+                    crate_folder_name,
+                    domain_path,
+                    crate_path,
+                })
+            } else {
+                None
+            }
         })
         .collect::<Vec<CrateInfo>>()
 }
@@ -62,6 +88,28 @@ pub fn is_domain_dir(e: &walkdir::DirEntry) -> bool {
     }
 }
 
+pub fn is_crate_dir(e: &walkdir::DirEntry) -> bool {
+    let cargo = e.path().file_stem().unwrap().to_str().unwrap().to_string();
+    cargo == "Cargo".to_string()
+}
+
+pub fn domain_dir_from(e: &walkdir::DirEntry) -> Option<String> {
+    let domain = e.path().file_stem().unwrap().to_str().unwrap().to_string();
+    if e.file_type().is_dir() && domain == "domain".to_string() {
+        Some(e.path().to_str().unwrap().to_string())
+    } else {
+        None
+    }
+}
+
+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".to_string()
+}
+
 pub fn is_hidden(entry: &walkdir::DirEntry) -> bool {
     entry
         .file_name()

+ 2 - 0
scripts/flowy-tool/src/proto/mod.rs

@@ -1,6 +1,8 @@
 mod ast;
+mod builder;
 mod helper;
 mod proto_gen;
 mod template;
 
+pub use builder::*;
 pub use proto_gen::*;

+ 63 - 138
scripts/flowy-tool/src/proto/proto_gen.rs

@@ -2,175 +2,100 @@ use crate::proto::ast::*;
 use crate::proto::helper::*;
 use crate::{proto::template::*, util::*};
 use flowy_ast::*;
+use shell::*;
 use std::{fs::OpenOptions, io::Write};
 use syn::Item;
 use walkdir::WalkDir;
 
 pub struct ProtoGen {
-    rust_source_dir: Option<String>,
-    proto_file_output_dir: Option<String>,
-    rust_mod_dir: Option<String>,
-    flutter_mod_dir: Option<String>,
-    build_cache_dir: Option<String>,
+    pub(crate) rust_source_dir: String,
+    pub(crate) proto_file_output_dir: String,
+    pub(crate) rust_mod_dir: String,
+    pub(crate) flutter_mod_dir: String,
+    pub(crate) derive_meta_dir: String,
 }
 
 impl ProtoGen {
-    pub fn new() -> Self {
-        ProtoGen {
-            rust_source_dir: None,
-            proto_file_output_dir: None,
-            rust_mod_dir: None,
-            flutter_mod_dir: None,
-            build_cache_dir: None,
-        }
-    }
-
-    pub fn set_rust_source_dir(mut self, dir: &str) -> Self {
-        self.rust_source_dir = Some(dir.to_string());
-        self
-    }
+    pub fn gen(&self) {
+        let crate_proto_infos = parse_crate_protobuf(self.rust_source_dir.as_ref());
 
-    pub fn set_proto_file_output_dir(mut self, dir: &str) -> Self {
-        self.proto_file_output_dir = Some(dir.to_string());
-        self
-    }
+        write_proto_files(&crate_proto_infos);
 
-    pub fn set_rust_mod_dir(mut self, dir: &str) -> Self {
-        self.rust_mod_dir = Some(dir.to_string());
-        self
-    }
+        run_protoc(&crate_proto_infos);
 
-    pub fn set_flutter_mod_dir(mut self, dir: &str) -> Self {
-        self.flutter_mod_dir = Some(dir.to_string());
-        self
-    }
+        write_derive_meta(&crate_proto_infos, self.derive_meta_dir.as_ref());
 
-    pub fn set_build_cache_dir(mut self, build_cache_dir: &str) -> Self {
-        self.build_cache_dir = Some(build_cache_dir.to_string());
-        self
+        write_rust_crate_protobuf(&crate_proto_infos);
     }
+}
 
-    pub fn gen(&self) {
-        let infos = parse_crate_protobuf(
-            self.rust_source_dir.as_ref().unwrap().as_ref(),
-            self.proto_file_output_dir.as_ref().unwrap().as_ref(),
-        );
-        self.write_proto_files(&infos);
-        self.gen_derive(&infos);
-        self.update_rust_flowy_protobuf_mod_file(&infos);
+fn write_proto_files(crate_infos: &Vec<CrateProtoInfo>) {
+    for crate_info in crate_infos {
+        let dir = crate_info.inner.proto_file_output_dir();
+        crate_info.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(),
+                false,
+            );
+        });
     }
+}
 
-    fn gen_derive(&self, crate_infos: &Vec<CrateProtoInfo>) {
-        let file_proto_infos = crate_infos
-            .iter()
-            .map(|ref crate_info| &crate_info.files)
-            .flatten()
-            .collect::<Vec<&FileProtoInfo>>();
-
-        let structs: Vec<String> = file_proto_infos
-            .iter()
-            .map(|info| info.structs.clone())
-            .flatten()
-            .collect();
-        let enums: Vec<String> = file_proto_infos
-            .iter()
-            .map(|info| info.enums.clone())
-            .flatten()
-            .collect();
-        let derive_file = self.build_cache_dir.as_ref().unwrap().clone();
-
-        let mut derive_template = ProtobufDeriveCache::new(structs, enums);
-        let new_content = derive_template.render().unwrap();
-        let old_content = read_file(derive_file.as_ref()).unwrap();
-        if new_content.clone() == old_content {
-            return;
-        }
-        // println!("{}", diff_lines(&old_content, &new_content));
+fn write_rust_crate_protobuf(crate_infos: &Vec<CrateProtoInfo>) {
+    for crate_info in crate_infos {
+        let mod_path = crate_info.inner.crate_mod_file();
         match OpenOptions::new()
             .create(true)
             .write(true)
             .append(false)
             .truncate(true)
-            .open(&derive_file)
+            .open(&mod_path)
         {
             Ok(ref mut file) => {
-                file.write_all(new_content.as_bytes()).unwrap();
+                let mut mod_file_content = String::new();
+                for (_, file_name) in WalkDir::new(crate_info.inner.proto_file_output_dir())
+                    .into_iter()
+                    .filter_map(|e| e.ok())
+                    .filter(|e| e.file_type().is_dir() == false)
+                    .map(|e| {
+                        (
+                            e.path().to_str().unwrap().to_string(),
+                            e.path().file_stem().unwrap().to_str().unwrap().to_string(),
+                        )
+                    })
+                {
+                    let c = format!("\nmod {}; \npub use {}::*; \n", &file_name, &file_name);
+                    mod_file_content.push_str(c.as_ref());
+                }
+                file.write_all(mod_file_content.as_bytes()).unwrap();
             }
             Err(err) => {
-                panic!("Failed to open log file: {}", err);
+                panic!("Failed to open file: {}", err);
             }
         }
     }
+}
 
-    fn write_proto_files(&self, crate_infos: &Vec<CrateProtoInfo>) {
-        for crate_info in crate_infos {
-            crate_info.files.iter().for_each(|info| {
-                // let dir = format!(
-                //     "{}/{}",
-                //     self.proto_file_output_dir.as_ref().unwrap(),
-                //     &crate_info.name,
-                // );
-                let dir = format!("{}", self.proto_file_output_dir.as_ref().unwrap(),);
-
-                if !std::path::Path::new(&dir).exists() {
-                    std::fs::create_dir_all(&dir).unwrap();
-                }
-
-                let proto_file_path = format!("{}/{}.proto", dir, &info.file_name);
-                let new_content = info.generated_content.clone();
-                save_content_to_file_with_diff_prompt(
-                    &new_content,
-                    proto_file_path.as_ref(),
-                    false,
-                );
-            });
-        }
-    }
-
-    fn update_rust_flowy_protobuf_mod_file(&self, crate_infos: &Vec<CrateProtoInfo>) {
-        for crate_info in crate_infos {
-            // let dir = format!(
-            //     "{}/{}-pb",
-            //     self.rust_mod_dir.as_ref().unwrap(),
-            //     &crate_info.name,
-            // );
+fn run_protoc(crate_infos: &Vec<CrateProtoInfo>) {
+    // protoc --rust_out=${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/rust-lib/flowy-protobuf/src/model \
+    // --proto_path=${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/rust-lib/flowy-protobuf/define \
+    // ${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/rust-lib/flowy-protobuf/define/*.proto
 
-            let dir = format!("{}/model", self.rust_mod_dir.as_ref().unwrap(),);
-            if !std::path::Path::new(&dir).exists() {
-                std::fs::create_dir_all(&dir).unwrap();
-            }
-            let mod_path = format!("{}/mod.rs", dir);
+    for crate_info in crate_infos {
+        let rust_out = crate_info.inner.proto_struct_output_dir();
+        let proto_path = crate_info.inner.proto_file_output_dir();
 
-            match OpenOptions::new()
-                .create(false)
-                .write(true)
-                .append(false)
-                .truncate(true)
-                .open(&mod_path)
-            {
-                Ok(ref mut file) => {
-                    let mut mod_file_content = String::new();
-                    for (_, file_name) in
-                        WalkDir::new(self.proto_file_output_dir.as_ref().unwrap().clone())
-                            .into_iter()
-                            .filter_map(|e| e.ok())
-                            .filter(|e| e.file_type().is_dir() == false)
-                            .map(|e| {
-                                (
-                                    e.path().to_str().unwrap().to_string(),
-                                    e.path().file_stem().unwrap().to_str().unwrap().to_string(),
-                                )
-                            })
-                    {
-                        let c = format!("\nmod {}; \npub use {}::*; \n", &file_name, &file_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);
-                }
-            }
+        for proto_file in WalkDir::new(&proto_path)
+            .into_iter()
+            .filter_map(|e| e.ok())
+            .filter(|e| is_proto_file(e))
+            .map(|e| e.path().to_str().unwrap().to_string())
+        {
+            cmd_lib::run_cmd! {
+                protoc --rust_out=${rust_out} --proto_path=${proto_path} ${proto_file}
+            };
         }
     }
 }

+ 0 - 33
scripts/flowy-tool/src/proto/template/build_cache/derive_cache.rs

@@ -1,33 +0,0 @@
-use crate::util::get_tera;
-use tera::{Context, Tera};
-
-pub struct ProtobufDeriveCache {
-    context: Context,
-    structs: Vec<String>,
-    enums: Vec<String>,
-}
-
-#[allow(dead_code)]
-impl ProtobufDeriveCache {
-    pub fn new(structs: Vec<String>, enums: Vec<String>) -> Self {
-        return ProtobufDeriveCache {
-            context: Context::new(),
-            structs,
-            enums,
-        };
-    }
-
-    pub fn render(&mut self) -> Option<String> {
-        self.context.insert("names", &self.structs);
-        self.context.insert("enums", &self.enums);
-
-        let tera = get_tera("build_cache");
-        match tera.render("derive_cache.tera", &self.context) {
-            Ok(r) => Some(r),
-            Err(e) => {
-                log::error!("{:?}", e);
-                None
-            }
-        }
-    }
-}

+ 0 - 3
scripts/flowy-tool/src/proto/template/build_cache/mod.rs

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

+ 77 - 0
scripts/flowy-tool/src/proto/template/derive_meta/derive_meta.rs

@@ -0,0 +1,77 @@
+use crate::proto::helper::{CrateProtoInfo, FileProtoInfo};
+use crate::util::{get_tera, read_file};
+use std::fs::OpenOptions;
+use std::io::Write;
+use tera::{Context, Tera};
+
+pub struct ProtobufDeriveMeta {
+    context: Context,
+    structs: Vec<String>,
+    enums: Vec<String>,
+}
+
+#[allow(dead_code)]
+impl ProtobufDeriveMeta {
+    pub fn new(structs: Vec<String>, enums: Vec<String>) -> Self {
+        return ProtobufDeriveMeta {
+            context: Context::new(),
+            structs,
+            enums,
+        };
+    }
+
+    pub fn render(&mut self) -> Option<String> {
+        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
+            }
+        }
+    }
+}
+
+pub fn write_derive_meta(crate_infos: &Vec<CrateProtoInfo>, derive_meta_dir: &str) {
+    let file_proto_infos = crate_infos
+        .iter()
+        .map(|ref crate_info| &crate_info.files)
+        .flatten()
+        .collect::<Vec<&FileProtoInfo>>();
+
+    let structs: Vec<String> = file_proto_infos
+        .iter()
+        .map(|info| info.structs.clone())
+        .flatten()
+        .collect();
+    let enums: Vec<String> = file_proto_infos
+        .iter()
+        .map(|info| info.enums.clone())
+        .flatten()
+        .collect();
+
+    let mut derive_template = ProtobufDeriveMeta::new(structs, enums);
+    let new_content = derive_template.render().unwrap();
+    let old_content = read_file(derive_meta_dir).unwrap();
+    if new_content.clone() == old_content {
+        return;
+    }
+    // println!("{}", diff_lines(&old_content, &new_content));
+    match OpenOptions::new()
+        .create(true)
+        .write(true)
+        .append(false)
+        .truncate(true)
+        .open(derive_meta_dir)
+    {
+        Ok(ref mut file) => {
+            file.write_all(new_content.as_bytes()).unwrap();
+        }
+        Err(err) => {
+            panic!("Failed to open log file: {}", err);
+        }
+    }
+}

+ 0 - 0
scripts/flowy-tool/src/proto/template/build_cache/derive_cache.tera → scripts/flowy-tool/src/proto/template/derive_meta/derive_meta.tera


+ 3 - 0
scripts/flowy-tool/src/proto/template/derive_meta/mod.rs

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

+ 2 - 2
scripts/flowy-tool/src/proto/template/mod.rs

@@ -1,5 +1,5 @@
-mod build_cache;
+mod derive_meta;
 mod proto_file;
 
-pub use build_cache::*;
+pub use derive_meta::*;
 pub use proto_file::*;

+ 17 - 6
scripts/makefile/protobuf.toml

@@ -1,19 +1,30 @@
 
 [tasks.pb]
-dependencies = ["gen_pb_file", "gen_rust_pb"]
+dependencies = ["gen_pb_file"]
 
 [tasks.gen_pb_file]
 script = [
     """
     pb_gen_bin=${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/scripts/flowy-tool/Cargo.toml
     rust_source=${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/rust-lib/
+    rust_lib=${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/rust-lib
+    flutter_lib=${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/app_flowy/packages
 
-    build_cache=${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/rust-lib/flowy-derive/src/derive_cache/derive_cache.rs
-    proto_file_output=${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/rust-lib/flowy-protobuf/define
-    rust_mod_dir=${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/rust-lib/flowy-protobuf/src/
-    flutter_mod_dir=${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/flutter-lib/packages/flowy_protobuf/lib/
+    rust_flowy_protobuf=${rust_lib}/flowy-protobuf
+    flutter_flowy_protobuf=${flutter_lib}/flowy_protobuf
 
-    cargo run --manifest-path ${pb_gen_bin} pb-gen --rust_source=${rust_source}  --build_cache=${build_cache} --proto_file_output=${proto_file_output} --rust_mod_dir=${rust_mod_dir} --flutter_mod_dir=${flutter_mod_dir}
+    derive_meta=${rust_lib}/flowy-derive/src/derive_cache/derive_cache.rs
+    proto_file_output=${rust_flowy_protobuf}/define
+    rust_mod_dir=${rust_flowy_protobuf}/src/
+    flutter_mod_dir=${flutter_flowy_protobuf}/src/
+
+    cargo run \
+     --manifest-path ${pb_gen_bin} pb-gen \
+     --rust_source=${rust_source} \
+     --derive_meta=${derive_meta} \
+     --proto_file_output=${proto_file_output} \
+     --rust_mod_dir=${rust_mod_dir} \
+     --flutter_mod_dir=${flutter_mod_dir}
     """,
 ]
 script_runner = "@shell"