1
0
Эх сурвалжийг харах

fix errors for nested routes

Evan Almloff 2 жил өмнө
parent
commit
a7f7aad947

+ 2 - 2
packages/fullstack/Cargo.toml

@@ -61,11 +61,11 @@ web-sys = { version = "0.3.61", features = ["Window", "Document", "Element", "Ht
 [features]
 default = ["hot-reload", "default-tls"]
 router = ["dioxus-router"]
-hot-reload = ["serde_json", "tokio-stream", "futures-util"]
+hot-reload = ["serde_json", "futures-util"]
 warp = ["dep:warp", "http-body", "ssr"]
 axum = ["dep:axum", "tower-http", "ssr"]
 salvo = ["dep:salvo", "ssr"]
-ssr = ["server_fn/ssr", "tokio", "dioxus-ssr", "hyper", "http", "dioxus-router/ssr"]
+ssr = ["server_fn/ssr", "tokio", "dioxus-ssr", "hyper", "http", "dioxus-router/ssr", "tokio-stream"]
 default-tls = ["server_fn/default-tls"]
 rustls = ["server_fn/rustls"]
 

+ 1 - 1
packages/fullstack/examples/axum-hello-world/Cargo.toml

@@ -7,7 +7,7 @@ publish = false
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 
 [dependencies]
-dioxus-web = { workspace = true, features=["hydrate"], optional = true }
+dioxus-web = { workspace = true, features = ["hydrate"], optional = true }
 dioxus = { workspace = true }
 dioxus-fullstack = { workspace = true }
 axum = { version = "0.6.12", optional = true }

+ 1 - 1
packages/router-macro/src/nest.rs

@@ -82,6 +82,6 @@ impl Nest {
     pub fn error_type(&self) -> TokenStream {
         let error_name = self.error_ident();
 
-        create_error_type(error_name, &self.segments)
+        create_error_type(error_name, &self.segments, None)
     }
 }

+ 1 - 1
packages/router-macro/src/redirect.rs

@@ -30,7 +30,7 @@ impl Redirect {
     pub fn error_type(&self) -> TokenStream {
         let error_name = self.error_ident();
 
-        create_error_type(error_name, &self.segments)
+        create_error_type(error_name, &self.segments, None)
     }
 
     pub fn parse_query(&self) -> TokenStream {

+ 8 - 13
packages/router-macro/src/route.rs

@@ -308,20 +308,11 @@ impl Route {
             RouteType::Child(field) => {
                 let name = &self.route_name;
                 let child_name = field.ident.as_ref().unwrap();
-                let ty = &field.ty;
 
                 quote! {
-                    {
-                        let mut trailing = String::new();
-                        for seg in segments {
-                            trailing += seg;
-                            trailing += "/";
-                        }
-                        trailing.pop();
-                        #enum_name::#name {
-                            #child_name: #ty::from_str(&trailing).unwrap(),
-                            #(#segments,)*
-                        }
+                    #enum_name::#name {
+                        #child_name,
+                        #(#segments,)*
                     }
                 }
             }
@@ -343,8 +334,12 @@ impl Route {
 
     pub fn error_type(&self) -> TokenStream2 {
         let error_name = self.error_ident();
+        let child_type = match &self.ty {
+            RouteType::Child(field) => Some(&field.ty),
+            RouteType::Leaf { .. } => None,
+        };
 
-        create_error_type(error_name, &self.segments)
+        create_error_type(error_name, &self.segments, child_type)
     }
 
     pub fn parse_query(&self) -> TokenStream2 {

+ 27 - 2
packages/router-macro/src/route_tree.rs

@@ -343,7 +343,7 @@ impl<'a> RouteTreeSegmentData<'a> {
                     RouteType::Child(_) => false,
                 };
 
-                print_route_segment(
+                let print_route_segment = print_route_segment(
                     route_segments.peekable(),
                     return_constructed(
                         insure_not_trailing,
@@ -356,7 +356,32 @@ impl<'a> RouteTreeSegmentData<'a> {
                     &error_enum_name,
                     enum_varient,
                     &varient_parse_error,
-                )
+                );
+
+                match &route.ty {
+                    RouteType::Child(child) => {
+                        let ty = &child.ty;
+                        let child_name = &child.ident;
+
+                        quote! {
+                            let mut trailing = String::new();
+                            for seg in segments.clone() {
+                                trailing += seg;
+                                trailing += "/";
+                            }
+                            trailing.pop();
+                            match #ty::from_str(&trailing).map_err(|err| #error_enum_name::#enum_varient(#varient_parse_error::ChildRoute(err))) {
+                                Ok(#child_name) => {
+                                    #print_route_segment
+                                }
+                                Err(err) => {
+                                    errors.push(err);
+                                }
+                            }
+                        }
+                    }
+                    RouteType::Leaf { .. } => print_route_segment,
+                }
             }
             Self::Nest { nest, children } => {
                 // At this point, we have matched all static segments, so we can just check if the remaining segments match the route

+ 24 - 2
packages/router-macro/src/segment.rs

@@ -222,7 +222,11 @@ pub fn parse_route_segments<'a>(
     Ok((route_segments, parsed_query))
 }
 
-pub(crate) fn create_error_type(error_name: Ident, segments: &[RouteSegment]) -> TokenStream2 {
+pub(crate) fn create_error_type(
+    error_name: Ident,
+    segments: &[RouteSegment],
+    child_type: Option<&Type>,
+) -> TokenStream2 {
     let mut error_variants = Vec::new();
     let mut display_match = Vec::new();
 
@@ -249,11 +253,28 @@ pub(crate) fn create_error_type(error_name: Ident, segments: &[RouteSegment]) ->
         }
     }
 
+    let child_type_variant = child_type
+        .map(|child_type| {
+            quote! { ChildRoute(<#child_type as std::str::FromStr>::Err) }
+        })
+        .into_iter();
+
+    let child_type_error = child_type
+        .map(|_| {
+            quote! {
+                Self::ChildRoute(error) => {
+                    write!(f, "{}", error)?
+                }
+            }
+        })
+        .into_iter();
+
     quote! {
         #[allow(non_camel_case_types)]
         #[derive(Debug, PartialEq)]
         pub enum #error_name {
             ExtraSegments(String),
+            #(#child_type_variant,)*
             #(#error_variants,)*
         }
 
@@ -262,7 +283,8 @@ pub(crate) fn create_error_type(error_name: Ident, segments: &[RouteSegment]) ->
                 match self {
                     Self::ExtraSegments(segments) => {
                         write!(f, "Found additional trailing segments: {}", segments)?
-                    }
+                    },
+                    #(#child_type_error,)*
                     #(#display_match,)*
                 }
                 Ok(())