leptos_spin/
route_table.rs

1use leptos_router::RouteListing;
2use routefinder::Router;
3
4pub struct RouteTable(Router<Option<RouteListing>>);
5
6pub(crate) enum RouteMatch {
7    Route(RouteListing),
8    ServerFn, // TODO: consider including the path
9    None,
10}
11
12impl RouteTable {
13    pub fn build<IV>(app_fn: impl Fn() -> IV + 'static + Clone) -> RouteTable
14    where
15        IV: leptos::IntoView + 'static,
16    {
17        let routes = generate_route_list(app_fn);
18
19        let mut rf = Router::new();
20        for listing in routes {
21            let path = listing.path().to_owned();
22            rf.add(path, Some(listing)).unwrap();
23        }
24
25        RouteTable(rf)
26    }
27
28    pub fn add_server_fn_prefix(&mut self, prefix: &str) -> Result<(), String> {
29        let wildcard = format!("{prefix}/*");
30        self.0.add(wildcard, None)
31    }
32
33    pub(crate) fn best_match(&self, path: &str) -> RouteMatch {
34        match self.0.best_match(path).as_ref() {
35            Some(m) => match m.as_ref() {
36                Some(listing) => RouteMatch::Route(listing.clone()),
37                None => RouteMatch::ServerFn,
38            },
39            None => RouteMatch::None,
40        }
41    }
42}
43
44fn generate_route_list<IV>(app_fn: impl Fn() -> IV + 'static + Clone) -> Vec<RouteListing>
45where
46    IV: leptos::IntoView + 'static,
47{
48    let (routes, _static_data_map) = leptos_router::generate_route_list_inner(app_fn);
49
50    let routes = routes
51        .into_iter()
52        .map(empty_to_slash)
53        .map(leptos_wildcards_to_spin)
54        .collect::<Vec<_>>();
55
56    if routes.is_empty() {
57        vec![RouteListing::new(
58            "/",
59            "",
60            Default::default(),
61            [leptos_router::Method::Get],
62            None,
63        )]
64    } else {
65        // TODO: the actix one has something about excluded routes
66        routes
67    }
68}
69
70fn empty_to_slash(listing: RouteListing) -> RouteListing {
71    let path = listing.path();
72    if path.is_empty() {
73        return RouteListing::new(
74            "/",
75            listing.path(),
76            listing.mode(),
77            listing.methods(),
78            listing.static_mode(),
79        );
80    }
81    listing
82}
83
84fn leptos_wildcards_to_spin(listing: RouteListing) -> RouteListing {
85    // TODO: wildcards, parameters, etc etc etc.
86    let path = listing.path();
87    let path2 = path.replace("*any", "*");
88    RouteListing::new(
89        path2,
90        listing.path(),
91        listing.mode(),
92        listing.methods(),
93        listing.static_mode(),
94    )
95}