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