Skip to main content

haystack_server/ops/
ops_handler.rs

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