mirror of
https://github.com/fabro-sh/fabro.git
synced 2026-09-06 08:18:58 +00:00
Extract typed ListResponse struct to eliminate double serialization
Replace inline json!() wrappers with a shared ListResponse<T> struct that serializes directly, avoiding the intermediate serde_json::Value. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
14322f40c2
commit
4f1297572d
2 changed files with 20 additions and 5 deletions
|
|
@ -11,7 +11,7 @@ use axum::Json;
|
|||
|
||||
use crate::error::ApiError;
|
||||
use crate::jwt_auth::AuthenticatedService;
|
||||
use crate::server::{AppState, PaginationParams};
|
||||
use crate::server::{AppState, ListResponse, PaginationParams};
|
||||
|
||||
fn paginated_response<T: serde::Serialize>(items: Vec<T>, pagination: &PaginationParams) -> Response {
|
||||
let limit = pagination.limit.clamp(1, 100) as usize;
|
||||
|
|
@ -23,7 +23,7 @@ fn paginated_response<T: serde::Serialize>(items: Vec<T>, pagination: &Paginatio
|
|||
}
|
||||
|
||||
fn list_response<T: serde::Serialize>(items: T) -> Response {
|
||||
(StatusCode::OK, Json(json!({ "data": items, "meta": { "has_more": false } }))).into_response()
|
||||
(StatusCode::OK, Json(ListResponse::new(items))).into_response()
|
||||
}
|
||||
|
||||
// ── Runs ───────────────────────────────────────────────────────────────
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ use tokio::sync::broadcast;
|
|||
use tokio_stream::wrappers::BroadcastStream;
|
||||
use tokio_stream::StreamExt;
|
||||
|
||||
use serde_json::json;
|
||||
use tracing::{error, info};
|
||||
|
||||
use arc_agent::LocalSandbox;
|
||||
|
|
@ -45,6 +44,22 @@ pub struct PaginationParams {
|
|||
pub offset: u32,
|
||||
}
|
||||
|
||||
/// Non-paginated list response wrapper with `has_more: false`.
|
||||
#[derive(serde::Serialize)]
|
||||
pub struct ListResponse<T: serde::Serialize> {
|
||||
data: T,
|
||||
meta: PaginationMeta,
|
||||
}
|
||||
|
||||
impl<T: serde::Serialize> ListResponse<T> {
|
||||
pub fn new(data: T) -> Self {
|
||||
Self {
|
||||
data,
|
||||
meta: PaginationMeta { has_more: false },
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Snapshot of a managed run.
|
||||
struct ManagedRun {
|
||||
dot_source: String,
|
||||
|
|
@ -645,7 +660,7 @@ async fn get_questions(
|
|||
Some(managed_run) => {
|
||||
let interviewer = match &managed_run.interviewer {
|
||||
Some(i) => i,
|
||||
None => return (StatusCode::OK, Json(json!({ "data": Vec::<ApiQuestion>::new(), "meta": { "has_more": false } }))).into_response(),
|
||||
None => return (StatusCode::OK, Json(ListResponse::new(Vec::<ApiQuestion>::new()))).into_response(),
|
||||
};
|
||||
let pending = interviewer.pending_questions();
|
||||
let questions: Vec<ApiQuestion> = pending
|
||||
|
|
@ -666,7 +681,7 @@ async fn get_questions(
|
|||
allow_freeform: pq.question.allow_freeform,
|
||||
})
|
||||
.collect();
|
||||
(StatusCode::OK, Json(json!({ "data": questions, "meta": { "has_more": false } }))).into_response()
|
||||
(StatusCode::OK, Json(ListResponse::new(questions))).into_response()
|
||||
}
|
||||
None => ApiError::not_found("Run not found.").into_response(),
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue