Files
hemx/examples/workout/src/main.rs
T
slhx agent 4254327cc7 refactor(examples): hide workout dispatch details
Keep the workout binary to page/runtime/interaction plumbing by moving generated handle dispatch behind an app-owned interactions function, while preserving typed form adapters and full verification.

req: codegen/002

req: examples/001
2026-06-11 22:19:17 +02:00

65 lines
1.8 KiB
Rust

use axum::extract::State;
use axum::response::IntoResponse;
use axum::routing::get;
use axum::Router;
use hemx_axum::{runtime_js, runtime_js_path, EffectResponse, InteractionRequest};
use hemx_workout_example::{self as workout_app, AppState};
use std::net::SocketAddr;
use std::str::FromStr;
#[tokio::main]
async fn main() {
let app = app(AppState::demo());
let addr = std::env::var("HEMX_WORKOUT_ADDR")
.ok()
.and_then(|value| SocketAddr::from_str(&value).ok())
.unwrap_or_else(|| SocketAddr::from(([127, 0, 0, 1], 3028)));
let listener = tokio::net::TcpListener::bind(addr).await.expect(
"bind workout example address; set HEMX_WORKOUT_ADDR=127.0.0.1:3030 if the default is busy",
);
eprintln!("hemx workout example: http://{addr}");
axum::serve(listener, app).await.unwrap();
}
pub fn app(state: AppState) -> Router {
Router::new()
.route("/", get(page).post(interact))
.route("/workout.css", get(workout_css))
.route(runtime_js_path(), get(runtime))
.with_state(state)
}
async fn page(State(state): State<AppState>) -> impl IntoResponse {
axum::response::Html(
state.with_workout(|workout| workout_app::page(runtime_js_path(), workout).into_string()),
)
}
async fn interact(
State(state): State<AppState>,
request: InteractionRequest,
) -> Result<EffectResponse, impl IntoResponse> {
request.dispatch(workout_app::interactions(state))
}
async fn workout_css() -> impl IntoResponse {
(
[("content-type", "text/css; charset=utf-8")],
include_str!("../templates/workout.css"),
)
}
async fn runtime() -> impl IntoResponse {
runtime_js()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn routes_can_be_built_for_run_and_deploy_smoke() {
let _app = app(AppState::demo());
}
}