use axum::body::Body; use axum::extract::{Query, State}; use axum::response::{IntoResponse, Response}; use axum::routing::get; use axum::Router; use futures_util::stream; use hemx::IntoEffect; use hemx_axum::{runtime_js, runtime_js_path, sse, EffectResponse, InteractionRequest}; use hemx_saas_example::{home_page, live_status, registry, settings_page, ui, AppContext}; use std::collections::BTreeMap; use std::convert::Infallible; #[tokio::main] async fn main() { let app = app(AppContext::demo()); let listener = tokio::net::TcpListener::bind("127.0.0.1:3003") .await .expect("bind saas tutorial example"); axum::serve(listener, app) .await .expect("serve saas tutorial example"); } fn app(ctx: AppContext) -> Router { Router::new() .route("/", get(home).post(interact)) .route("/settings", get(settings)) .route("/events", get(events)) .route(runtime_js_path(), get(runtime)) .route("/app.css", get(css)) .route("/metrics.js", get(metrics_js)) .with_state(ctx) } async fn home(State(ctx): State) -> impl IntoResponse { axum::response::Html(home_page(&ctx).into_string()) } async fn settings(State(ctx): State) -> impl IntoResponse { axum::response::Html(settings_page(&ctx).into_string()) } async fn interact( State(ctx): State, request: InteractionRequest, ) -> Result { request.dispatch_async(registry(ctx)).await } async fn events( Query(params): Query>, State(ctx): State, ) -> impl IntoResponse { let count = ctx.projects().len(); if params.contains_key("once") { return sse(stream::iter([Ok::<_, Infallible>( live_status(count).into_batch(ui::BUILD_FINGERPRINT), )])); } sse(stream::iter([Ok::<_, Infallible>( live_status(count).into_batch(ui::BUILD_FINGERPRINT), )])) } async fn runtime() -> impl IntoResponse { runtime_js() } async fn css() -> Response { Response::builder() .header("content-type", "text/css; charset=utf-8") .body(Body::from(include_str!("../templates/app.css"))) .expect("css response") } async fn metrics_js() -> Response { Response::builder() .header("content-type", "text/javascript; charset=utf-8") .body(Body::from(include_str!("../templates/metrics.js"))) .expect("metrics js response") }