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 workspace.initialize_default_mock_environments();
53
54 Ok(workspace)
55 }
56
57 pub fn core_to_team(
62 &self,
63 core_workspace: &CoreWorkspace,
64 owner_id: Uuid,
65 ) -> Result<TeamWorkspace> {
66 let workspace_json = serde_json::to_value(core_workspace).map_err(|e| {
68 CollabError::Internal(format!("Failed to serialize workspace to JSON: {e}"))
69 })?;
70
71 let mut team_workspace = TeamWorkspace::new(core_workspace.name.clone(), owner_id);
73 team_workspace.id = Uuid::parse_str(&core_workspace.id).unwrap_or_else(|_| Uuid::new_v4()); team_workspace.description = core_workspace.description.clone();
75 team_workspace.config = workspace_json;
76 team_workspace.created_at = core_workspace.created_at;
77 team_workspace.updated_at = core_workspace.updated_at;
78
79 Ok(team_workspace)
80 }
81
82 pub fn get_workspace_state(&self, team_workspace: &TeamWorkspace) -> Result<CoreWorkspace> {
86 self.team_to_core(team_workspace)
87 }
88
89 pub fn update_workspace_state(
93 &self,
94 team_workspace: &mut TeamWorkspace,
95 core_workspace: &CoreWorkspace,
96 ) -> Result<()> {
97 let workspace_json = serde_json::to_value(core_workspace)
99 .map_err(|e| CollabError::Internal(format!("Failed to serialize workspace: {e}")))?;
100
101 team_workspace.config = workspace_json;
103 team_workspace.updated_at = chrono::Utc::now();
104
105 Ok(())
106 }
107
108 pub async fn load_workspace_from_disk(
112 &self,
113 workspace_id: &str,
114 owner_id: Uuid,
115 ) -> Result<TeamWorkspace> {
116 let core_workspace = self
118 .persistence
119 .load_workspace(workspace_id)
120 .await
121 .map_err(|e| CollabError::Internal(format!("Failed to load workspace: {e}")))?;
122
123 self.core_to_team(&core_workspace, owner_id)
125 }
126
127 pub async fn save_workspace_to_disk(&self, team_workspace: &TeamWorkspace) -> Result<()> {
131 let core_workspace = self.team_to_core(team_workspace)?;
133
134 self.persistence
136 .save_workspace(&core_workspace)
137 .await
138 .map_err(|e| CollabError::Internal(format!("Failed to save workspace: {e}")))?;
139
140 Ok(())
141 }
142
143 pub async fn export_workspace_for_backup(
147 &self,
148 team_workspace: &TeamWorkspace,
149 ) -> Result<Value> {
150 let core_workspace = self.team_to_core(team_workspace)?;
152
153 serde_json::to_value(&core_workspace)
155 .map_err(|e| CollabError::Internal(format!("Failed to serialize for backup: {e}")))
156 }
157
158 pub async fn import_workspace_from_backup(
162 &self,
163 backup_data: &Value,
164 owner_id: Uuid,
165 new_name: Option<String>,
166 ) -> Result<TeamWorkspace> {
167 let mut core_workspace: CoreWorkspace = serde_json::from_value(backup_data.clone())
169 .map_err(|e| CollabError::Internal(format!("Failed to deserialize backup: {e}")))?;
170
171 if let Some(name) = new_name {
173 core_workspace.name = name;
174 }
175
176 core_workspace.id = Uuid::new_v4().to_string();
178 core_workspace.created_at = chrono::Utc::now();
179 core_workspace.updated_at = chrono::Utc::now();
180
181 self.core_to_team(&core_workspace, owner_id)
183 }
184
185 pub fn get_workspace_state_json(&self, team_workspace: &TeamWorkspace) -> Result<Value> {
189 let core_workspace = self.team_to_core(team_workspace)?;
190 serde_json::to_value(&core_workspace)
191 .map_err(|e| CollabError::Internal(format!("Failed to serialize state: {e}")))
192 }
193
194 pub fn update_workspace_state_from_json(
198 &self,
199 team_workspace: &mut TeamWorkspace,
200 state_json: &Value,
201 ) -> Result<()> {
202 let mut core_workspace: CoreWorkspace = serde_json::from_value(state_json.clone())
204 .map_err(|e| CollabError::Internal(format!("Failed to deserialize state JSON: {e}")))?;
205
206 core_workspace.id = team_workspace.id.to_string();
208 core_workspace.name = team_workspace.name.clone();
209 core_workspace.description = team_workspace.description.clone();
210
211 self.update_workspace_state(team_workspace, &core_workspace)
213 }
214
215 pub fn create_empty_workspace(&self, name: String, owner_id: Uuid) -> Result<TeamWorkspace> {
219 let core_workspace = CoreWorkspace::new(name);
220 self.core_to_team(&core_workspace, owner_id)
221 }
222}
223
224#[cfg(test)]
225mod tests {
226 use super::*;
227
228 #[test]
229 fn test_team_to_core_conversion() {
230 let bridge = CoreBridge::new("/tmp/test");
231 let owner_id = Uuid::new_v4();
232
233 let core_workspace = CoreWorkspace::new("Test Workspace".to_string());
235 let team_workspace = bridge.core_to_team(&core_workspace, owner_id).unwrap();
236
237 let restored = bridge.team_to_core(&team_workspace).unwrap();
239
240 assert_eq!(restored.name, core_workspace.name);
241 assert_eq!(restored.folders.len(), core_workspace.folders.len());
242 assert_eq!(restored.requests.len(), core_workspace.requests.len());
243 }
244
245 #[test]
246 fn test_state_json_roundtrip() {
247 let bridge = CoreBridge::new("/tmp/test");
248 let owner_id = Uuid::new_v4();
249
250 let core_workspace = CoreWorkspace::new("Test".to_string());
252 let mut team_workspace = bridge.core_to_team(&core_workspace, owner_id).unwrap();
253
254 let state_json = bridge.get_workspace_state_json(&team_workspace).unwrap();
256
257 bridge
259 .update_workspace_state_from_json(&mut team_workspace, &state_json)
260 .unwrap();
261
262 let restored = bridge.team_to_core(&team_workspace).unwrap();
264 assert_eq!(restored.name, "Test");
265 }
266}