derived_cms/
entity.rs

1use std::{fmt::Display, future::Future};
2
3use axum::extract::FromRequestParts;
4pub use derived_cms_derive::Entity;
5use generic_array::{ArrayLength, GenericArray};
6use serde::{Deserialize, Serialize};
7
8use crate::{
9    app::AppError,
10    column::{Column, ColumnInfo},
11    context::ContextTrait,
12    input::InputInfo,
13};
14
15pub trait EntityBase<S: ContextTrait>:
16    for<'de> Deserialize<'de> + Serialize + Send + Sync + Unpin + 'static
17{
18    /// should usually be an UUID
19    type Id: for<'de> Deserialize<'de> + Clone + Display + Serialize + Send;
20
21    type Create: for<'de> Deserialize<'de> + Serialize + Send + Sync + Unpin + 'static;
22    type Update: for<'de> Deserialize<'de> + Serialize + Send + Sync + Unpin + 'static;
23
24    type NumberOfColumns: ArrayLength;
25
26    fn name() -> &'static str;
27    fn name_plural() -> &'static str;
28
29    /// should return the value of the field used as primary key.
30    fn id(&self) -> &Self::Id;
31
32    fn columns() -> GenericArray<ColumnInfo, Self::NumberOfColumns>;
33    fn column_values(&self) -> GenericArray<&dyn Column, Self::NumberOfColumns>;
34    fn inputs(value: Option<&Self>) -> impl IntoIterator<Item = InputInfo<'_, S>>;
35}
36
37pub trait Entity<S: ContextTrait>:
38    EntityBase<S> + Get<S> + List<S> + Create<S> + Update<S> + Delete<S>
39{
40}
41
42pub trait Get<S: ContextTrait>: EntityBase<S> {
43    type RequestExt: FromRequestParts<S> + Send + Sync + Clone;
44    type Error: Into<AppError> + Serialize + Send;
45
46    fn get(
47        id: &<Self as EntityBase<S>>::Id,
48        ext: Self::RequestExt,
49    ) -> impl Future<Output = Result<Option<Self>, Self::Error>> + Send;
50}
51
52pub trait List<S: ContextTrait>: EntityBase<S> {
53    type RequestExt: FromRequestParts<S> + Send + Sync + Clone;
54    type Error: Into<AppError> + Serialize + Send;
55
56    // TODO: limit & offset
57    fn list(
58        ext: Self::RequestExt,
59    ) -> impl Future<Output = Result<impl IntoIterator<Item = Self>, Self::Error>> + Send;
60}
61
62pub trait Create<S: ContextTrait>: EntityBase<S> {
63    type RequestExt: FromRequestParts<S> + Send + Sync + Clone;
64    type Error: Into<AppError> + Serialize + Send;
65
66    fn create(
67        data: <Self as EntityBase<S>>::Create,
68        ext: Self::RequestExt,
69    ) -> impl Future<Output = Result<Self, Self::Error>> + Send;
70}
71
72pub trait Update<S: ContextTrait>: EntityBase<S> {
73    type RequestExt: FromRequestParts<S> + Send + Sync + Clone;
74    type Error: Into<AppError> + Serialize + Send;
75
76    fn update(
77        id: &<Self as EntityBase<S>>::Id,
78        data: <Self as EntityBase<S>>::Update,
79        ext: Self::RequestExt,
80    ) -> impl Future<Output = Result<Self, Self::Error>> + Send;
81}
82
83pub trait Delete<S: ContextTrait>: EntityBase<S> {
84    type RequestExt: FromRequestParts<S> + Send + Sync + Clone;
85    type Error: Into<AppError> + Serialize + Send + Sync + Unpin + 'static;
86
87    fn delete(
88        id: &<Self as EntityBase<S>>::Id,
89        ext: Self::RequestExt,
90    ) -> impl Future<Output = Result<(), Self::Error>> + Send;
91}