use crate::response::status_code;
use axum::{http::StatusCode, response::IntoResponse};
use ayun_config::config;
use ayun_core::SharedString;
use serde::{Deserialize, Serialize};
use std::borrow::Cow;
#[derive(Debug, Deserialize, Serialize)]
pub struct Json {
code: u16,
success: bool,
data: serde_json::Value,
message: Option<SharedString>,
}
impl Default for Json {
fn default() -> Self {
Self::new()
}
}
impl Json {
fn new() -> Self {
let status_code = StatusCode::OK;
Self {
code: status_code.as_u16(),
success: status_code.is_success(),
data: serde_json::Value::Object(Default::default()),
message: status_code.canonical_reason().map(Cow::Borrowed),
}
}
pub fn code(mut self, code: StatusCode) -> Self {
self.code = code.as_u16();
self.success = code.is_success();
self
}
pub fn data<T>(mut self, data: &T) -> Self
where
T: Serialize,
{
match serde_json::to_value(data) {
Ok(value) => self.data = value,
Err(err) => self.message = Some(Cow::from(err.to_string())),
}
self
}
pub fn message(mut self, message: impl Into<SharedString>) -> Self {
self.message = Some(message.into());
self
}
#[cfg(feature = "database")]
pub fn paginate(
mut self,
page: u64,
limit: u64,
items: Vec<serde_json::Value>,
items_and_pages: sea_orm::ItemsAndPagesNumber,
) -> Self {
self.data = serde_json::json!({
"items": items,
"per_page": limit,
"current_page": page,
"total": items_and_pages.number_of_items,
"total_pages": items_and_pages.number_of_pages,
});
self
}
}
impl IntoResponse for Json {
fn into_response(self) -> axum::response::Response {
let server = config::<crate::config::Server>("server").unwrap_or_default();
let status_code = match server.response.strict {
true => status_code(self.code),
false => StatusCode::OK,
};
(status_code, axum::Json(self)).into_response()
}
}