feat(axum): start stateful interactions tersely

Add state_interactions as a small helper for app-owned stateful registries, and use it in the workout exemplar to remove one layer of repetitive route wiring without hiding generated handles or app handlers.

req: axum_integration/003

req: ceremony/001

req: dx/003

req: codegen/002

req: examples/001
This commit is contained in:
slhx agent
2026-06-11 21:55:29 +02:00
parent d991addbb5
commit 0f8d07d36f
3 changed files with 51 additions and 3 deletions
+41
View File
@@ -232,6 +232,47 @@ fn interaction_request_dispatches_with_concise_handlers_helper() {
assert_eq!(response.batch.ops, vec![Slot::<String>::new(3).text("ok")]);
}
#[test]
fn state_interactions_starts_stateful_wiring_without_nested_closures() {
// req: axum_integration/003 req: ceremony/001 req: dx/003
fn ping(prefix: String) -> impl IntoEffect {
Slot::<String>::new(3).text(format!("{prefix}: ping"))
}
fn open(prefix: String, input: OpenProject) -> impl IntoEffect {
Slot::<String>::new(3).text(format!("{prefix}: {}", input.project_id.0))
}
let registry = || {
hemx_axum::state_interactions(BuildFingerprint(4), "project".to_owned())
.on_state(Handle::<()>::new(7), ping)
.on(Handle::<()>::new(8), open)
.into_registry()
};
let ping_response = InteractionRequest::from(InteractionForm::for_handle(
Handle::<()>::new(7),
Vec::new(),
))
.dispatch(registry())
.unwrap();
assert_eq!(
ping_response.batch.ops,
vec![Slot::<String>::new(3).text("project: ping")]
);
let open_response = InteractionRequest::from(InteractionForm::for_handle(
Handle::<()>::new(8),
vec![("project_id".to_owned(), "42".to_owned())],
))
.dispatch(registry())
.unwrap();
assert_eq!(
open_response.batch.ops,
vec![Slot::<String>::new(3).text("project: 42")]
);
}
#[test]
fn interaction_request_dispatches_typed_form_inputs() {
// req: axum_integration/003 req: form/004 req: canonical_authoring/003