Skip to main content

oversync_api/
handlers.rs

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}