1use std::sync::Arc;
2
3use axum::Json;
4use axum::extract::{Path, State};
5use axum::http::StatusCode;
6use axum::response::IntoResponse;
7
8use crate::state::ApiState;
9use crate::types::*;
10
11#[utoipa::path(
12 get,
13 path = "/health",
14 responses(
15 (status = 200, description = "Service is healthy", body = HealthResponse)
16 )
17)]
18pub async fn health() -> Json<HealthResponse> {
19 Json(HealthResponse {
20 status: "ok",
21 version: env!("CARGO_PKG_VERSION"),
22 })
23}
24
25#[utoipa::path(
26 get,
27 path = "/sources",
28 responses(
29 (status = 200, description = "List configured sources", body = SourceListResponse)
30 )
31)]
32pub async fn list_sources(State(state): State<Arc<ApiState>>) -> Json<SourceListResponse> {
33 Json(SourceListResponse {
34 sources: state.sources_info(),
35 })
36}
37
38#[utoipa::path(
39 get,
40 path = "/sources/{name}",
41 params(("name" = String, Path, description = "Source name")),
42 responses(
43 (status = 200, description = "Source details", body = SourceInfo),
44 (status = 404, description = "Source not found", body = ErrorResponse)
45 )
46)]
47pub async fn get_source(
48 State(state): State<Arc<ApiState>>,
49 Path(name): Path<String>,
50) -> Result<Json<SourceInfo>, impl IntoResponse> {
51 state
52 .sources_info()
53 .into_iter()
54 .find(|s| s.name == name)
55 .map(Json)
56 .ok_or_else(|| {
57 (
58 StatusCode::NOT_FOUND,
59 Json(ErrorResponse {
60 error: format!("source not found: {name}"),
61 }),
62 )
63 })
64}
65
66#[utoipa::path(
67 get,
68 path = "/sinks",
69 responses(
70 (status = 200, description = "List configured sinks", body = SinkListResponse)
71 )
72)]
73pub async fn list_sinks(State(state): State<Arc<ApiState>>) -> Json<SinkListResponse> {
74 Json(SinkListResponse {
75 sinks: state.sinks_info(),
76 })
77}
78
79#[utoipa::path(
80 get,
81 path = "/pipes",
82 responses(
83 (status = 200, description = "List configured pipes", body = PipeListResponse)
84 )
85)]
86pub async fn list_pipes(State(state): State<Arc<ApiState>>) -> Json<PipeListResponse> {
87 Json(PipeListResponse {
88 pipes: state.pipes_info(),
89 })
90}
91
92#[utoipa::path(
93 get,
94 path = "/pipes/{name}",
95 params(("name" = String, Path, description = "Pipe name")),
96 responses(
97 (status = 200, description = "Pipe details", body = PipeInfo),
98 (status = 404, description = "Pipe not found", body = ErrorResponse)
99 )
100)]
101pub async fn get_pipe(
102 State(state): State<Arc<ApiState>>,
103 Path(name): Path<String>,
104) -> Result<Json<PipeInfo>, impl IntoResponse> {
105 state
106 .pipes_info()
107 .into_iter()
108 .find(|p| p.name == name)
109 .map(Json)
110 .ok_or_else(|| {
111 (
112 StatusCode::NOT_FOUND,
113 Json(ErrorResponse {
114 error: format!("pipe not found: {name}"),
115 }),
116 )
117 })
118}