1use crate::core::{Data, EntityReference, Link};
4use anyhow::Result;
5use async_trait::async_trait;
6use uuid::Uuid;
7
8#[async_trait]
13pub trait DataService<T: Data>: Send + Sync {
14 async fn create(&self, tenant_id: &Uuid, entity: T) -> Result<T>;
16
17 async fn get(&self, tenant_id: &Uuid, id: &Uuid) -> Result<Option<T>>;
19
20 async fn list(&self, tenant_id: &Uuid) -> Result<Vec<T>>;
22
23 async fn update(&self, tenant_id: &Uuid, id: &Uuid, entity: T) -> Result<T>;
25
26 async fn delete(&self, tenant_id: &Uuid, id: &Uuid) -> Result<()>;
28
29 async fn search(&self, tenant_id: &Uuid, field: &str, value: &str) -> Result<Vec<T>>;
31}
32
33#[async_trait]
38pub trait LinkService: Send + Sync {
39 async fn create(
41 &self,
42 tenant_id: &Uuid,
43 link_type: &str,
44 source: EntityReference,
45 target: EntityReference,
46 metadata: Option<serde_json::Value>,
47 ) -> Result<Link>;
48
49 async fn get(&self, tenant_id: &Uuid, id: &Uuid) -> Result<Option<Link>>;
51
52 async fn list(&self, tenant_id: &Uuid) -> Result<Vec<Link>>;
54
55 async fn find_by_source(
59 &self,
60 tenant_id: &Uuid,
61 source_id: &Uuid,
62 source_type: &str,
63 link_type: Option<&str>,
64 target_type: Option<&str>,
65 ) -> Result<Vec<Link>>;
66
67 async fn find_by_target(
71 &self,
72 tenant_id: &Uuid,
73 target_id: &Uuid,
74 target_type: &str,
75 link_type: Option<&str>,
76 source_type: Option<&str>,
77 ) -> Result<Vec<Link>>;
78
79 async fn update(
85 &self,
86 tenant_id: &Uuid,
87 id: &Uuid,
88 metadata: Option<serde_json::Value>,
89 ) -> Result<Link>;
90
91 async fn delete(&self, tenant_id: &Uuid, id: &Uuid) -> Result<()>;
93
94 async fn delete_by_entity(
98 &self,
99 tenant_id: &Uuid,
100 entity_id: &Uuid,
101 entity_type: &str,
102 ) -> Result<()>;
103}
104
105#[cfg(test)]
106mod tests {
107 use super::*;
108 use crate::core::entity::Entity;
109
110 #[derive(Clone, Debug)]
112 struct TestEntity {
113 id: Uuid,
114 tenant_id: Uuid,
115 }
116
117 impl Entity for TestEntity {
118 type Service = ();
119 fn resource_name() -> &'static str {
120 "tests"
121 }
122 fn resource_name_singular() -> &'static str {
123 "test"
124 }
125 fn service_from_host(
126 _: &std::sync::Arc<dyn std::any::Any + Send + Sync>,
127 ) -> Result<std::sync::Arc<Self::Service>> {
128 Ok(std::sync::Arc::new(()))
129 }
130 }
131
132 impl Data for TestEntity {
133 fn id(&self) -> Uuid {
134 self.id
135 }
136 fn tenant_id(&self) -> Uuid {
137 self.tenant_id
138 }
139 fn indexed_fields() -> &'static [&'static str] {
140 &[]
141 }
142 fn field_value(&self, _field: &str) -> Option<crate::core::field::FieldValue> {
143 None
144 }
145 }
146
147 async fn generic_create<T, S>(service: &S, tenant_id: &Uuid, entity: T) -> Result<T>
149 where
150 T: Data,
151 S: DataService<T>,
152 {
153 service.create(tenant_id, entity).await
154 }
155
156 #[test]
157 fn test_traits_compile() {
158 }
161}