diff --git a/packages/proto-macros/tests/genereate_app.rs b/packages/proto-macros/tests/genereate_app.rs index 609df64..2c26132 100644 --- a/packages/proto-macros/tests/genereate_app.rs +++ b/packages/proto-macros/tests/genereate_app.rs @@ -1,20 +1,18 @@ #[cfg(test)] mod test { + use hikari_proto::generate_app; + fn generate() { generate_app! { - #[routes] #[derive(PartialEq, Clone, Debug, Serialize, Deserialize)] pub enum Route { #[at("/")] Portal { recommend_list: Vec } #[at("/u/:id")] - #[at("/:id")] - #[url_params({ id: String })] Personal { id: String, name: String, email: String } #[at("/t/:id")] - #[url_params({ id: String })] Thread { id: String, title: String, content: String, comments: Vec } #[not_found] @@ -22,14 +20,12 @@ mod test { NotFound } - #[global_state] #[derive(PartialEq, Clone, Debug, Serialize, Deserialize)] pub struct Theme { pub primary_color: String, pub secondary_color: String, } - #[global_state] #[derive(PartialEq, Clone, Debug, Serialize, Deserialize)] pub struct UserToken { pub token: String, @@ -39,12 +35,16 @@ mod test { #[test] fn render_at_client() { - generate().render_to_element("#root"); + generate().hydrate(web_sys::window()?.document()?.get_element_by_id("_root")?); } #[test] fn render_at_server() { - generate().render_to_string(); + generate().render_to_string(Route::Personal { + id: "114514", + name: "homo", + email: "homo@red.tea", + }); let stream = generate().render_to_stream(); } diff --git a/packages/proto/src/lib.rs b/packages/proto/src/lib.rs index 34ae947..64e8af7 100644 --- a/packages/proto/src/lib.rs +++ b/packages/proto/src/lib.rs @@ -1,3 +1,4 @@ mod macros; +pub use macros::generate_app::*; pub use macros::register_routes::*; diff --git a/packages/proto/src/macros/generate_app.rs b/packages/proto/src/macros/generate_app.rs new file mode 100644 index 0000000..1944476 --- /dev/null +++ b/packages/proto/src/macros/generate_app.rs @@ -0,0 +1,56 @@ +#[macro_export] +macro_rules! generate_structs { + ($(#[$meta:meta])* $vis:vis struct $name:ident { $($field:tt)* } $($rest:tt)*) => { + $(#[$meta])* + $vis struct $name { + $($field)* + } + generate_structs! { $($rest)* } + }; + () => {} +} + +#[macro_export] +macro_rules! generate_app { + ( + $(#[$route_meta:meta])* + $route_vis:vis enum $route_enum:ident { + $( + $(#[$($variant_meta:meta)*])* + $variant:ident $( { $( $field:ident : $field_ty:ty ),* } )? + )* + } + + $($rest:tt)* + ) => { + #[derive(yew_router::Routable)] + $(#[$route_meta])* + $route_vis enum $route_enum { + $( + $(#[$($variant_meta)*])* + $variant $( { $( $field : $field_ty ),* } )? + )* + } + + generate_structs! { $($rest)* } + + #[cfg(feature = "web")] + impl $props_enum { + $props_vis fn hydrate(element: web_sys::Element) -> Result { + let props_json = element + .get_attribute("_props") + .ok_or_else(|| JsValue::from_str("Missing _props attribute"))?; + let props: Self = serde_json::from_str(&props_json)?; + Ok(props) + } + } + + #[cfg(not(feature = "web"))] + impl $props_enum { + $props_vis fn render_to_string(&self) -> Result { + let props_json = serde_json::to_string(self)?; + Ok(props_json) + } + } + }; +} diff --git a/packages/proto/src/macros/mod.rs b/packages/proto/src/macros/mod.rs index 85e97a0..78e47dc 100644 --- a/packages/proto/src/macros/mod.rs +++ b/packages/proto/src/macros/mod.rs @@ -1 +1,2 @@ +pub mod generate_app; pub mod register_routes;