dioxus_aws/
lib.rs

1use dioxus::dioxus_core::Element;
2
3#[cfg(feature = "server")]
4use axum::routing::Route;
5#[cfg(feature = "server")]
6use axum_core::{extract::Request, response::IntoResponse};
7#[cfg(feature = "server")]
8use std::convert::Infallible;
9#[cfg(feature = "server")]
10use tower_layer::Layer;
11#[cfg(feature = "server")]
12use tower_service::Service;
13
14#[cfg(feature = "lambda")]
15mod lambda;
16
17pub mod prelude {
18    pub use dioxus::prelude::*;
19    pub use dioxus_fullstack::prelude::*;
20}
21
22#[doc = include_str!("../docs/launch.md")]
23pub fn launch(_app: fn() -> Element) {
24    #[cfg(feature = "web")]
25    dioxus::launch(_app);
26
27    #[cfg(feature = "server")]
28    {
29        use axum::routing::*;
30        use dioxus_fullstack::prelude::*;
31
32        struct TryIntoResult(Result<ServeConfig, dioxus_fullstack::UnableToLoadIndex>);
33
34        impl TryInto<ServeConfig> for TryIntoResult {
35            type Error = dioxus_fullstack::UnableToLoadIndex;
36
37            fn try_into(self) -> Result<ServeConfig, Self::Error> {
38                self.0
39            }
40        }
41
42        tokio::runtime::Runtime::new()
43            .unwrap()
44            .block_on(async move {
45                let app = Router::new().serve_dioxus_application(
46                    TryIntoResult(ServeConfigBuilder::default().build()),
47                    _app,
48                );
49
50                #[cfg(not(feature = "lambda"))]
51                {
52                    let address = dioxus_cli_config::fullstack_address_or_localhost();
53                    let listener = tokio::net::TcpListener::bind(address).await.unwrap();
54
55                    axum::serve(listener, app.into_make_service())
56                        .await
57                        .unwrap();
58                }
59
60                #[cfg(feature = "lambda")]
61                {
62                    use self::lambda::LambdaAdapter;
63
64                    tracing::info!("Running in lambda mode");
65                    lambda_runtime::run(LambdaAdapter::from(app)).await.unwrap();
66                }
67            });
68    };
69}
70
71#[cfg(feature = "server")]
72pub async fn launch_with_layers<L>(app: fn() -> Element, layers: Vec<L>)
73where
74    L: Layer<Route> + Clone + Send + 'static,
75    L::Service: Service<Request> + Clone + Send + 'static,
76    <L::Service as Service<Request>>::Response: IntoResponse + 'static,
77    <L::Service as Service<Request>>::Error: Into<Infallible> + 'static,
78    <L::Service as Service<Request>>::Future: Send + 'static,
79{
80    #[cfg(feature = "web")]
81    dioxus::launch(app);
82
83    #[cfg(feature = "server")]
84    {
85        use axum::routing::*;
86        use dioxus_fullstack::prelude::*;
87
88        struct TryIntoResult(Result<ServeConfig, dioxus_fullstack::UnableToLoadIndex>);
89
90        impl TryInto<ServeConfig> for TryIntoResult {
91            type Error = dioxus_fullstack::UnableToLoadIndex;
92
93            fn try_into(self) -> Result<ServeConfig, Self::Error> {
94                self.0
95            }
96        }
97
98        let mut app = Router::new()
99            .serve_dioxus_application(TryIntoResult(ServeConfigBuilder::default().build()), app);
100
101        for layer in layers {
102            app = app.layer(layer);
103        }
104
105        #[cfg(not(feature = "lambda"))]
106        {
107            let address = dioxus_cli_config::fullstack_address_or_localhost();
108            let listener = tokio::net::TcpListener::bind(address).await.unwrap();
109
110            axum::serve(listener, app.into_make_service())
111                .await
112                .unwrap();
113        }
114
115        #[cfg(feature = "lambda")]
116        {
117            use self::lambda::LambdaAdapter;
118
119            tracing::info!("Running in lambda mode");
120            lambda_runtime::run(LambdaAdapter::from(app)).await.unwrap();
121        }
122    };
123}
124
125#[cfg(feature = "server")]
126pub struct AppBuilder<L> {
127    layers: Vec<L>,
128    app: fn() -> Element,
129}
130
131#[cfg(feature = "server")]
132impl<L> AppBuilder<L>
133where
134    L: Layer<Route> + Clone + Send + 'static,
135    L::Service: Service<Request> + Clone + Send + 'static,
136    <L::Service as Service<Request>>::Response: IntoResponse + 'static,
137    <L::Service as Service<Request>>::Error: Into<Infallible> + 'static,
138    <L::Service as Service<Request>>::Future: Send + 'static,
139{
140    pub fn new(app: fn() -> Element) -> Self {
141        Self {
142            layers: Vec::new(),
143            app,
144        }
145    }
146
147    pub fn layer(mut self, layer: L) -> Self {
148        self.layers.push(layer);
149        self
150    }
151
152    pub async fn serve(self) {
153        launch_with_layers(self.app, self.layers).await;
154    }
155}