haystack_server/ops/
ops_handler.rs1use axum::extract::State;
4use axum::http::{HeaderMap, StatusCode};
5use axum::response::{IntoResponse, Response};
6
7use haystack_core::data::{HCol, HDict, HGrid};
8use haystack_core::kinds::Kind;
9
10use crate::content;
11use crate::state::SharedState;
12
13pub async fn handle(State(_state): State<SharedState>, headers: HeaderMap) -> Response {
15 let accept = headers
16 .get("Accept")
17 .and_then(|v| v.to_str().ok())
18 .unwrap_or("");
19
20 let ops = vec![
21 ("about", "Summary information for server"),
22 ("ops", "Operations supported by this server"),
23 ("formats", "Grid data formats supported by this server"),
24 ("read", "Read entity records by id or filter"),
25 ("nav", "Navigate a project for discovery"),
26 ("defs", "Query the definitions namespace"),
27 ("libs", "Query the library namespace"),
28 ("watchSub", "Subscribe to entity changes"),
29 ("watchPoll", "Poll for entity changes"),
30 ("watchUnsub", "Unsubscribe from entity changes"),
31 ("pointWrite", "Write a value to a writable point"),
32 ("hisRead", "Read historical time-series data"),
33 ("hisWrite", "Write historical time-series data"),
34 ("invokeAction", "Invoke an action on an entity"),
35 ("close", "Close the current session"),
36 ];
37
38 let cols = vec![HCol::new("name"), HCol::new("summary")];
39 let rows: Vec<HDict> = ops
40 .into_iter()
41 .map(|(name, summary)| {
42 let mut row = HDict::new();
43 row.set("name", Kind::Str(name.to_string()));
44 row.set("summary", Kind::Str(summary.to_string()));
45 row
46 })
47 .collect();
48
49 let grid = HGrid::from_parts(HDict::new(), cols, rows);
50 match content::encode_response_grid(&grid, accept) {
51 Ok((body, ct)) => ([(axum::http::header::CONTENT_TYPE, ct)], body).into_response(),
52 Err(e) => {
53 log::error!("Failed to encode ops grid: {e}");
54 (StatusCode::INTERNAL_SERVER_ERROR, "encoding error").into_response()
55 }
56 }
57}