Skip to main content

ograf_core/
lib.rs

1//! The pure OGraf-spec Core server: graphics, renderers, actions, and the
2//! renderer WebSocket protocol. Knows nothing about zones, API keys, or
3//! admin accounts — every access decision is delegated to whatever
4//! [`access::AccessControl`] implementation the binary wires in (Dependency
5//! Inversion principle). A consumer that wants no access control at all can
6//! use [`access::AllowAllAccessControl`].
7
8pub mod access;
9pub mod config;
10pub mod error;
11pub mod handlers;
12pub mod models;
13pub mod protocol;
14pub mod renderer_ws;
15pub mod store;
16
17use std::sync::Arc;
18
19use access::AccessControl;
20use config::Config;
21use store::renderers::RendererRegistry;
22
23#[derive(Clone)]
24pub struct AppState {
25    pub config: Arc<Config>,
26    pub renderers: Arc<RendererRegistry>,
27    pub access: Arc<dyn AccessControl>,
28}
29
30pub use axum::Router;
31
32/// Builds the `/ograf/v1/*` API router plus the internal graphic-asset route
33/// used by the renderer HTML — everything a consumer needs to nest under its
34/// own top-level router alongside its own admin routes. Static file serving
35/// (`/renderer`, admin UI) and CORS/tracing layers are the binary's own
36/// concern, not Core's.
37pub fn build_router(state: AppState) -> Router {
38    use axum::routing::{get, post, put};
39
40    let api = Router::new()
41        .route("/", get(handlers::server_info))
42        .route("/health", get(handlers::health))
43        .route("/graphics", get(handlers::graphics::list_graphics))
44        .route("/graphics/:id", get(handlers::graphics::get_graphic))
45        .route(
46            "/graphics/:id/assets/*path",
47            get(handlers::graphics::serve_graphic_asset),
48        )
49        .route(
50            "/graphics/:id/thumbnail",
51            get(handlers::graphics::get_thumbnail),
52        )
53        .route(
54            "/renderers/connect",
55            get(handlers::renderers::connect_renderer),
56        )
57        .route("/renderers", get(handlers::renderers::list_renderers))
58        .route("/renderers/:id", get(handlers::renderers::get_renderer))
59        .route(
60            "/renderers/:id/target",
61            get(handlers::renderers::get_target),
62        )
63        .route(
64            "/renderers/:id/customActions/:action_id",
65            post(handlers::actions::renderer_custom_action),
66        )
67        .route(
68            "/renderers/:id/target/graphicInstance/clear",
69            put(handlers::actions::clear),
70        )
71        .route(
72            "/renderers/:id/target/graphicInstance/load",
73            post(handlers::actions::load),
74        )
75        .route(
76            "/renderers/:id/target/graphicInstance/playAction",
77            post(handlers::actions::play_action),
78        )
79        .route(
80            "/renderers/:id/target/graphicInstance/stopAction",
81            post(handlers::actions::stop_action),
82        )
83        .route(
84            "/renderers/:id/target/graphicInstance/updateAction",
85            post(handlers::actions::update_action),
86        )
87        .route(
88            "/renderers/:id/target/graphicInstance/customActions/:action_id",
89            post(handlers::actions::custom_action),
90        );
91
92    Router::new()
93        .nest("/ograf/v1", api)
94        .route(
95            "/serverApi/internal/graphics/:graphic_id/*path",
96            get(handlers::graphics::serve_graphic_asset),
97        )
98        .with_state(state)
99}