metis_core/application/services/
database.rs1use crate::dal::database::{models::*, repository::DocumentRepository};
2use crate::domain::documents::types::DocumentType;
3use crate::Result;
4
5pub struct DatabaseService {
7 repository: DocumentRepository,
8}
9
10impl DatabaseService {
11 pub fn new(repository: DocumentRepository) -> Self {
12 Self { repository }
13 }
14
15 pub fn create_document(&mut self, document: NewDocument) -> Result<Document> {
17 self.repository.create_document(document)
18 }
19
20 pub fn find_by_filepath(&mut self, filepath: &str) -> Result<Option<Document>> {
22 self.repository.find_by_filepath(filepath)
23 }
24
25 pub fn find_by_id(&mut self, id: &str) -> Result<Option<Document>> {
27 self.repository.find_by_id(id)
28 }
29
30 pub fn update_document(&mut self, filepath: &str, document: &Document) -> Result<Document> {
32 self.repository.update_document(filepath, document)
33 }
34
35 pub fn delete_document(&mut self, filepath: &str) -> Result<bool> {
37 self.repository.delete_document(filepath)
38 }
39
40 pub fn search_documents(&mut self, query: &str) -> Result<Vec<Document>> {
42 self.repository.search_documents(query)
43 }
44
45 pub fn find_by_type(&mut self, doc_type: DocumentType) -> Result<Vec<Document>> {
47 let type_str = doc_type.to_string();
48 self.repository.find_by_type(&type_str)
49 }
50
51 pub fn find_by_tag(&mut self, tag: &str) -> Result<Vec<Document>> {
53 self.repository.find_by_tag(tag)
54 }
55
56 pub fn find_children(&mut self, parent_id: &str) -> Result<Vec<Document>> {
58 self.repository.find_children(parent_id)
59 }
60
61 pub fn find_parent(&mut self, child_id: &str) -> Result<Option<Document>> {
63 self.repository.find_parent(child_id)
64 }
65
66 pub fn create_relationship(
68 &mut self,
69 parent_id: &str,
70 child_id: &str,
71 parent_filepath: &str,
72 child_filepath: &str,
73 ) -> Result<()> {
74 let relationship = DocumentRelationship {
75 parent_id: parent_id.to_string(),
76 child_id: child_id.to_string(),
77 parent_filepath: parent_filepath.to_string(),
78 child_filepath: child_filepath.to_string(),
79 };
80 self.repository.create_relationship(relationship)
81 }
82
83 pub fn document_exists(&mut self, filepath: &str) -> Result<bool> {
85 Ok(self.repository.find_by_filepath(filepath)?.is_some())
86 }
87
88 pub fn count_by_type(&mut self, doc_type: DocumentType) -> Result<usize> {
90 let docs = self.repository.find_by_type(&doc_type.to_string())?;
91 Ok(docs.len())
92 }
93
94 pub fn get_all_id_filepath_pairs(&mut self) -> Result<Vec<(String, String)>> {
96 let mut pairs = Vec::new();
99
100 for doc_type in [
101 DocumentType::Vision,
102 DocumentType::Strategy,
103 DocumentType::Initiative,
104 DocumentType::Task,
105 DocumentType::Adr,
106 ] {
107 let docs = self.repository.find_by_type(&doc_type.to_string())?;
108 for doc in docs {
109 pairs.push((doc.id, doc.filepath));
110 }
111 }
112
113 Ok(pairs)
114 }
115}
116
117#[cfg(test)]
118mod tests {
119 use super::*;
120 use crate::dal::Database;
121
122 fn setup_service() -> DatabaseService {
123 let db = Database::new(":memory:").expect("Failed to create test database");
124 DatabaseService::new(db.into_repository())
125 }
126
127 fn create_test_document() -> NewDocument {
128 NewDocument {
129 filepath: "/test/doc.md".to_string(),
130 id: "test-doc-1".to_string(),
131 title: "Test Document".to_string(),
132 document_type: "vision".to_string(),
133 created_at: 1609459200.0,
134 updated_at: 1609459200.0,
135 archived: false,
136 exit_criteria_met: false,
137 file_hash: "abc123".to_string(),
138 frontmatter_json: "{}".to_string(),
139 content: Some("Test content".to_string()),
140 phase: "draft".to_string(),
141 }
142 }
143
144 #[test]
145 fn test_database_service_crud() {
146 let mut service = setup_service();
147
148 let new_doc = create_test_document();
150 let created = service.create_document(new_doc).expect("Failed to create");
151 assert_eq!(created.id, "test-doc-1");
152
153 let found = service
155 .find_by_id("test-doc-1")
156 .expect("Failed to find")
157 .expect("Document not found");
158 assert_eq!(found.filepath, "/test/doc.md");
159
160 let mut updated_doc = found.clone();
162 updated_doc.title = "Updated Title".to_string();
163 let updated = service
164 .update_document("/test/doc.md", &updated_doc)
165 .expect("Failed to update");
166 assert_eq!(updated.title, "Updated Title");
167
168 let deleted = service
170 .delete_document("/test/doc.md")
171 .expect("Failed to delete");
172 assert!(deleted);
173
174 assert!(!service
176 .document_exists("/test/doc.md")
177 .expect("Failed to check existence"));
178 }
179
180 #[test]
181 fn test_database_service_relationships() {
182 let mut service = setup_service();
183
184 let parent = NewDocument {
186 id: "parent-1".to_string(),
187 filepath: "/parent.md".to_string(),
188 document_type: "strategy".to_string(),
189 ..create_test_document()
190 };
191
192 let child = NewDocument {
193 id: "child-1".to_string(),
194 filepath: "/child.md".to_string(),
195 document_type: "initiative".to_string(),
196 ..create_test_document()
197 };
198
199 service
200 .create_document(parent)
201 .expect("Failed to create parent");
202 service
203 .create_document(child)
204 .expect("Failed to create child");
205
206 service
208 .create_relationship("parent-1", "child-1", "/parent.md", "/child.md")
209 .expect("Failed to create relationship");
210
211 let children = service
213 .find_children("parent-1")
214 .expect("Failed to find children");
215 assert_eq!(children.len(), 1);
216 assert_eq!(children[0].id, "child-1");
217
218 let parent = service
220 .find_parent("child-1")
221 .expect("Failed to find parent")
222 .expect("Parent not found");
223 assert_eq!(parent.id, "parent-1");
224 }
225}