1use crate::core::field::FieldValue;
4use anyhow::Result;
5use std::sync::Arc;
6use uuid::Uuid;
7
8pub trait Entity: Sized + Send + Sync + 'static {
13 type Service: Send + Sync;
15
16 fn resource_name() -> &'static str;
18
19 fn resource_name_singular() -> &'static str;
21
22 fn service_from_host(host: &Arc<dyn std::any::Any + Send + Sync>)
27 -> Result<Arc<Self::Service>>;
28}
29
30pub trait Data: Entity {
38 fn id(&self) -> Uuid;
40
41 fn tenant_id(&self) -> Uuid;
43
44 fn indexed_fields() -> &'static [&'static str];
46
47 fn field_value(&self, field: &str) -> Option<FieldValue>;
51
52 fn type_name() -> &'static str {
54 Self::resource_name_singular()
55 }
56}
57
58#[cfg(test)]
59mod tests {
60 use super::*;
61
62 #[derive(Clone)]
64 struct TestEntity {
65 id: Uuid,
66 tenant_id: Uuid,
67 name: String,
68 }
69
70 impl Entity for TestEntity {
71 type Service = ();
72
73 fn resource_name() -> &'static str {
74 "test_entities"
75 }
76
77 fn resource_name_singular() -> &'static str {
78 "test_entity"
79 }
80
81 fn service_from_host(
82 _host: &Arc<dyn std::any::Any + Send + Sync>,
83 ) -> Result<Arc<Self::Service>> {
84 Ok(Arc::new(()))
85 }
86 }
87
88 impl Data for TestEntity {
89 fn id(&self) -> Uuid {
90 self.id
91 }
92
93 fn tenant_id(&self) -> Uuid {
94 self.tenant_id
95 }
96
97 fn indexed_fields() -> &'static [&'static str] {
98 &["name"]
99 }
100
101 fn field_value(&self, field: &str) -> Option<FieldValue> {
102 match field {
103 "name" => Some(FieldValue::String(self.name.clone())),
104 _ => None,
105 }
106 }
107 }
108
109 #[test]
110 fn test_entity_metadata() {
111 assert_eq!(TestEntity::resource_name(), "test_entities");
112 assert_eq!(TestEntity::resource_name_singular(), "test_entity");
113 assert_eq!(TestEntity::type_name(), "test_entity");
114 }
115}