mockforge_collab/
core_bridge.rs1use crate::error::{CollabError, Result};
8use crate::models::TeamWorkspace;
9use mockforge_core::workspace::Workspace as CoreWorkspace;
10use mockforge_core::workspace_persistence::WorkspacePersistence;
11use serde_json::Value;
12use std::path::Path;
13use uuid::Uuid;
14
15pub struct CoreBridge {
17 persistence: WorkspacePersistence,
18}
19
20impl CoreBridge {
21 pub fn new<P: AsRef<Path>>(workspace_dir: P) -> Self {
23 Self {
24 persistence: WorkspacePersistence::new(workspace_dir),
25 }
26 }
27
28 pub fn team_to_core(&self, team_workspace: &TeamWorkspace) -> Result<CoreWorkspace> {
33 let workspace_json = &team_workspace.config;
35
36 let mut workspace: CoreWorkspace =
38 serde_json::from_value(workspace_json.clone()).map_err(|e| {
39 CollabError::Internal(format!("Failed to deserialize workspace from config: {}", e))
40 })?;
41
42 workspace.id = team_workspace.id.to_string();
45
46 workspace.name = team_workspace.name.clone();
48 workspace.description = team_workspace.description.clone();
49 workspace.updated_at = team_workspace.updated_at;
50
51 Ok(workspace)
52 }
53
54 pub fn core_to_team(
59 &self,
60 core_workspace: &CoreWorkspace,
61 owner_id: Uuid,
62 ) -> Result<TeamWorkspace> {
63 let workspace_json = serde_json::to_value(core_workspace).map_err(|e| {
65 CollabError::Internal(format!("Failed to serialize workspace to JSON: {}", e))
66 })?;
67
68 let mut team_workspace = TeamWorkspace::new(core_workspace.name.clone(), owner_id);
70 team_workspace.id = Uuid::parse_str(&core_workspace.id).unwrap_or_else(|_| Uuid::new_v4()); team_workspace.description = core_workspace.description.clone();
72 team_workspace.config = workspace_json;
73 team_workspace.created_at = core_workspace.created_at;
74 team_workspace.updated_at = core_workspace.updated_at;
75
76 Ok(team_workspace)
77 }
78
79 pub fn get_workspace_state(&self, team_workspace: &TeamWorkspace) -> Result<CoreWorkspace> {
83 self.team_to_core(team_workspace)
84 }
85
86 pub fn update_workspace_state(
90 &self,
91 team_workspace: &mut TeamWorkspace,
92 core_workspace: &CoreWorkspace,
93 ) -> Result<()> {
94 let workspace_json = serde_json::to_value(core_workspace)
96 .map_err(|e| CollabError::Internal(format!("Failed to serialize workspace: {}", e)))?;
97
98 team_workspace.config = workspace_json;
100 team_workspace.updated_at = chrono::Utc::now();
101
102 Ok(())
103 }
104
105 pub async fn load_workspace_from_disk(
109 &self,
110 workspace_id: &str,
111 owner_id: Uuid,
112 ) -> Result<TeamWorkspace> {
113 let core_workspace = self
115 .persistence
116 .load_workspace(workspace_id)
117 .await
118 .map_err(|e| CollabError::Internal(format!("Failed to load workspace: {}", e)))?;
119
120 self.core_to_team(&core_workspace, owner_id)
122 }
123
124 pub async fn save_workspace_to_disk(&self, team_workspace: &TeamWorkspace) -> Result<()> {
128 let core_workspace = self.team_to_core(team_workspace)?;
130
131 self.persistence
133 .save_workspace(&core_workspace)
134 .await
135 .map_err(|e| CollabError::Internal(format!("Failed to save workspace: {}", e)))?;
136
137 Ok(())
138 }
139
140 pub async fn export_workspace_for_backup(
144 &self,
145 team_workspace: &TeamWorkspace,
146 ) -> Result<Value> {
147 let core_workspace = self.team_to_core(team_workspace)?;
149
150 serde_json::to_value(&core_workspace)
152 .map_err(|e| CollabError::Internal(format!("Failed to serialize for backup: {}", e)))
153 }
154
155 pub async fn import_workspace_from_backup(
159 &self,
160 backup_data: &Value,
161 owner_id: Uuid,
162 new_name: Option<String>,
163 ) -> Result<TeamWorkspace> {
164 let mut core_workspace: CoreWorkspace = serde_json::from_value(backup_data.clone())
166 .map_err(|e| CollabError::Internal(format!("Failed to deserialize backup: {}", e)))?;
167
168 if let Some(name) = new_name {
170 core_workspace.name = name;
171 }
172
173 core_workspace.id = Uuid::new_v4().to_string();
175 core_workspace.created_at = chrono::Utc::now();
176 core_workspace.updated_at = chrono::Utc::now();
177
178 self.core_to_team(&core_workspace, owner_id)
180 }
181
182 pub fn get_workspace_state_json(&self, team_workspace: &TeamWorkspace) -> Result<Value> {
186 let core_workspace = self.team_to_core(team_workspace)?;
187 serde_json::to_value(&core_workspace)
188 .map_err(|e| CollabError::Internal(format!("Failed to serialize state: {}", e)))
189 }
190
191 pub fn update_workspace_state_from_json(
195 &self,
196 team_workspace: &mut TeamWorkspace,
197 state_json: &Value,
198 ) -> Result<()> {
199 let mut core_workspace: CoreWorkspace = serde_json::from_value(state_json.clone())
201 .map_err(|e| {
202 CollabError::Internal(format!("Failed to deserialize state JSON: {}", e))
203 })?;
204
205 core_workspace.id = team_workspace.id.to_string();
207 core_workspace.name = team_workspace.name.clone();
208 core_workspace.description = team_workspace.description.clone();
209
210 self.update_workspace_state(team_workspace, &core_workspace)
212 }
213
214 pub fn create_empty_workspace(&self, name: String, owner_id: Uuid) -> Result<TeamWorkspace> {
218 let core_workspace = CoreWorkspace::new(name.clone());
219 self.core_to_team(&core_workspace, owner_id)
220 }
221}
222
223#[cfg(test)]
224mod tests {
225 use super::*;
226
227 #[test]
228 fn test_team_to_core_conversion() {
229 let bridge = CoreBridge::new("/tmp/test");
230 let owner_id = Uuid::new_v4();
231
232 let core_workspace = CoreWorkspace::new("Test Workspace".to_string());
234 let team_workspace = bridge.core_to_team(&core_workspace, owner_id).unwrap();
235
236 let restored = bridge.team_to_core(&team_workspace).unwrap();
238
239 assert_eq!(restored.name, core_workspace.name);
240 assert_eq!(restored.folders.len(), core_workspace.folders.len());
241 assert_eq!(restored.requests.len(), core_workspace.requests.len());
242 }
243
244 #[test]
245 fn test_state_json_roundtrip() {
246 let bridge = CoreBridge::new("/tmp/test");
247 let owner_id = Uuid::new_v4();
248
249 let core_workspace = CoreWorkspace::new("Test".to_string());
251 let mut team_workspace = bridge.core_to_team(&core_workspace, owner_id).unwrap();
252
253 let state_json = bridge.get_workspace_state_json(&team_workspace).unwrap();
255
256 bridge
258 .update_workspace_state_from_json(&mut team_workspace, &state_json)
259 .unwrap();
260
261 let restored = bridge.team_to_core(&team_workspace).unwrap();
263 assert_eq!(restored.name, "Test");
264 }
265}