7 changed files with 115 additions and 34 deletions
@ -0,0 +1,78 @@
|
||||
use axum::{Json, Router, extract::State, http::StatusCode, response::IntoResponse, routing::get}; |
||||
use serde::Serialize; |
||||
use std::sync::Arc; |
||||
|
||||
use crate::state::AppState; |
||||
|
||||
// --- DTOs ---
|
||||
|
||||
#[derive(Debug, Serialize)] |
||||
pub struct DictListResponse { |
||||
pub dictionaries: Vec<DictListEntryResponse>, |
||||
} |
||||
|
||||
#[derive(Debug, Serialize)] |
||||
pub struct DictListEntryResponse { |
||||
pub name: String, |
||||
pub entry_count: u64, |
||||
} |
||||
|
||||
#[derive(Debug, Serialize)] |
||||
pub struct ErrorResponse { |
||||
pub error: String, |
||||
} |
||||
|
||||
impl IntoResponse for ErrorResponse { |
||||
fn into_response(self) -> axum::response::Response { |
||||
(StatusCode::INTERNAL_SERVER_ERROR, Json(self)).into_response() |
||||
} |
||||
} |
||||
|
||||
impl From<anyhow::Error> for ErrorResponse { |
||||
fn from(err: anyhow::Error) -> Self { |
||||
Self { |
||||
error: err.to_string(), |
||||
} |
||||
} |
||||
} |
||||
|
||||
impl From<applib::RepositoryError> for ErrorResponse { |
||||
fn from(err: applib::RepositoryError) -> Self { |
||||
Self { |
||||
error: err.to_string(), |
||||
} |
||||
} |
||||
} |
||||
|
||||
// --- Handlers ---
|
||||
|
||||
pub async fn list_dicts_handler( |
||||
State(state): State<Arc<AppState>>, |
||||
) -> Result<Json<DictListResponse>, ErrorResponse> { |
||||
let default_repo = state.container.create_dict_repo("default").await?; |
||||
|
||||
let dict_names = default_repo.fetch_dicts().await?; |
||||
|
||||
let mut entries = Vec::with_capacity(dict_names.len()); |
||||
|
||||
for dict_name in dict_names { |
||||
let dict_repo = state.container.create_dict_repo(&dict_name).await?; |
||||
|
||||
let entry_count = dict_repo.count_entries().await?; |
||||
|
||||
entries.push(DictListEntryResponse { |
||||
name: dict_name, |
||||
entry_count, |
||||
}); |
||||
} |
||||
|
||||
Ok(Json(DictListResponse { |
||||
dictionaries: entries, |
||||
})) |
||||
} |
||||
|
||||
// --- Router ---
|
||||
|
||||
pub fn routes() -> Router<Arc<AppState>> { |
||||
Router::new().route("/dicts", get(list_dicts_handler)) |
||||
} |
||||
@ -1,23 +1,21 @@
|
||||
pub const APP_NAME: &str = env!("CARGO_PKG_NAME"); |
||||
pub const APP_VERSION: &str = env!("CARGO_PKG_VERSION"); |
||||
|
||||
use crate::container::Container; |
||||
|
||||
#[derive(Clone)] |
||||
pub struct AppState { |
||||
pub name: String, |
||||
pub version: String, |
||||
pub container: Container, |
||||
} |
||||
|
||||
impl AppState { |
||||
pub fn new() -> Self { |
||||
Self { |
||||
pub async fn new() -> anyhow::Result<Self> { |
||||
Ok(Self { |
||||
name: APP_NAME.to_string(), |
||||
version: APP_VERSION.to_string(), |
||||
} |
||||
} |
||||
} |
||||
|
||||
impl Default for AppState { |
||||
fn default() -> Self { |
||||
Self::new() |
||||
container: Container::new().await?, |
||||
}) |
||||
} |
||||
} |
||||
|
||||
Loading…
Reference in new issue