1use {
2 convert_case::{Case, Casing},
3 std::{fmt::Write, path::Path},
4 tonic_build::Config,
5};
6
7pub fn generate_hooks<P: AsRef<Path>, P2: AsRef<Path>, P3: AsRef<Path>>(
9 protos: &[P],
10 includes: &[P2],
11 to_path: &Option<P3>,
12 uri: &str,
13) -> Result<(), std::io::Error> {
14 let mut config = Config::new();
15 let file_descriptor_set = config.load_fds(protos, includes)?;
16
17 for fd in file_descriptor_set.file {
18 let mut str = String::new();
19 let pkg_name = fd
20 .package
21 .as_ref()
22 .map_or_else(|| "_", |string| string.as_str());
23 let filename = format!("{pkg_name}.dx.rs");
24
25 for service in &fd.service {
26 write!(
27 str,
28 r#"
29 #[path = "{out_dir}/{package_name}.rs"]
30 mod proto;
31 pub use proto::*;
32 use ::dioxus::prelude::*;
33
34 pub struct {service_name}ServiceHook({tonic_client}<::tonic_web_wasm_client::Client>);
35
36 pub fn use_{service_name_lowercase}_service() -> {service_name}ServiceHook {{
37 {service_name}ServiceHook({tonic_client}::new(::tonic_web_wasm_client::Client::new(
38 {uri:?}.to_string()
39 )))
40 }}
41
42 impl {service_name}ServiceHook {{
43 "#,
44 out_dir = std::env::var("OUT_DIR").expect("build.rs"),
45 tonic_client = format!(
46 "proto::{}_client::{}Client",
47 service.name().to_case(Case::Snake),
48 service.name().to_case(Case::Pascal)
49 ),
50 package_name = pkg_name,
51 service_name = service.name().to_case(Case::Pascal),
52 service_name_lowercase = service.name().to_case(Case::Snake)
53 ).expect("write error");
54
55 for rpc in &service.method {
56 write!(
57 str,
58 r"
59 pub fn {rpc_name}(&self, req: Signal<proto::{rpc_input}>) -> Resource<Result<proto::{rpc_ouptut}, tonic::Status>> {{
60 let client = self.0.to_owned();
61 use_resource(move || {{
62 let mut client = client.clone();
63 async move {{ client.{rpc_name}(req()).await.map(|resp| resp.into_inner()) }}
64 }})
65 }}
66 ",
67 rpc_name = rpc.name().to_case(Case::Snake),
68 rpc_input = rpc
69 .input_type()
70 .split('.')
71 .next_back()
72 .expect("Should always have type"),
73 rpc_ouptut = rpc
74 .output_type()
75 .split('.')
76 .next_back()
77 .expect("Should always have type"),
78 ).expect("write error");
79 }
80
81 str.push('}');
82 }
83
84 match to_path {
85 Some(p) => {
86 std::fs::write(
87 {
88 let mut path_to_file = p.as_ref().to_owned();
89 path_to_file.push(filename);
90 path_to_file
91 },
92 str,
93 )
94 },
95 None => {
96 std::fs::write(
97 format!("{}/{filename}", std::env::var("OUT_DIR").expect("build.rs")),
98 str,
99 )
100 },
101 }?;
102 }
103
104
105 Ok(())
106}