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_NAME: &str = env!("CARGO_PKG_NAME"); |
||||||
pub const APP_VERSION: &str = env!("CARGO_PKG_VERSION"); |
pub const APP_VERSION: &str = env!("CARGO_PKG_VERSION"); |
||||||
|
|
||||||
|
use crate::container::Container; |
||||||
|
|
||||||
#[derive(Clone)] |
#[derive(Clone)] |
||||||
pub struct AppState { |
pub struct AppState { |
||||||
pub name: String, |
pub name: String, |
||||||
pub version: String, |
pub version: String, |
||||||
|
pub container: Container, |
||||||
} |
} |
||||||
|
|
||||||
impl AppState { |
impl AppState { |
||||||
pub fn new() -> Self { |
pub async fn new() -> anyhow::Result<Self> { |
||||||
Self { |
Ok(Self { |
||||||
name: APP_NAME.to_string(), |
name: APP_NAME.to_string(), |
||||||
version: APP_VERSION.to_string(), |
version: APP_VERSION.to_string(), |
||||||
} |
container: Container::new().await?, |
||||||
} |
}) |
||||||
} |
|
||||||
|
|
||||||
impl Default for AppState { |
|
||||||
fn default() -> Self { |
|
||||||
Self::new() |
|
||||||
} |
} |
||||||
} |
} |
||||||
|
|||||||
Loading…
Reference in new issue