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