Skip to main content

shaperail_runtime/db/
generated.rs

1use serde::de::DeserializeOwned;
2use serde::Serialize;
3use serde_json::{Map, Value};
4
5use super::{FilterSet, ResourceRow, SortDirection, SortParam};
6use shaperail_core::{FieldError, ShaperailError};
7
8pub fn parse_optional_json<T: DeserializeOwned>(
9    data: &Map<String, Value>,
10    field: &str,
11) -> Result<Option<T>, ShaperailError> {
12    let Some(value) = data.get(field) else {
13        return Ok(None);
14    };
15
16    if value.is_null() {
17        return Ok(None);
18    }
19
20    serde_json::from_value(value.clone())
21        .map(Some)
22        .map_err(|_| {
23            ShaperailError::Validation(vec![FieldError {
24                field: field.to_string(),
25                message: format!("{field} has an invalid value"),
26                code: "invalid_value".to_string(),
27            }])
28        })
29}
30
31pub fn parse_embedded_json<T: DeserializeOwned>(
32    field: &str,
33    value: Value,
34) -> Result<T, ShaperailError> {
35    serde_json::from_value(value).map_err(|_| {
36        ShaperailError::Internal(format!(
37            "Invalid generated default value for field '{field}'"
38        ))
39    })
40}
41
42pub fn require_field<T>(value: Option<T>, field: &str) -> Result<T, ShaperailError> {
43    value.ok_or_else(|| {
44        ShaperailError::Validation(vec![FieldError {
45            field: field.to_string(),
46            message: format!("{field} is required"),
47            code: "required".to_string(),
48        }])
49    })
50}
51
52pub fn parse_filter_text(filters: &FilterSet, field: &str) -> Option<String> {
53    filters
54        .filters
55        .iter()
56        .find(|filter| filter.field == field)
57        .map(|filter| filter.value.clone())
58}
59
60pub fn parse_filter<T>(
61    filters: &FilterSet,
62    field: &str,
63    code: &str,
64    parser: impl Fn(&str) -> Result<T, ShaperailError>,
65) -> Result<Option<T>, ShaperailError> {
66    let Some(raw) = parse_filter_text(filters, field) else {
67        return Ok(None);
68    };
69
70    parser(&raw).map(Some).map_err(|_| {
71        ShaperailError::Validation(vec![FieldError {
72            field: field.to_string(),
73            message: format!("{field} has an invalid filter value"),
74            code: code.to_string(),
75        }])
76    })
77}
78
79pub fn sort_field_at(sort: &SortParam, index: usize) -> Option<String> {
80    sort.fields.get(index).map(|field| field.field.clone())
81}
82
83pub fn sort_direction_at(sort: &SortParam, index: usize) -> Option<&'static str> {
84    sort.fields.get(index).map(|field| match field.direction {
85        SortDirection::Asc => "asc",
86        SortDirection::Desc => "desc",
87    })
88}
89
90pub fn row_from_model<T: Serialize>(model: &T) -> Result<ResourceRow, ShaperailError> {
91    serde_json::to_value(model)
92        .map(ResourceRow)
93        .map_err(|e| ShaperailError::Internal(format!("Failed to serialize row: {e}")))
94}