mockforge_collab/
server.rs1use crate::api::{create_router as create_api_router, ApiState};
4use crate::auth::AuthService;
5use crate::backup::BackupService;
6use crate::config::CollabConfig;
7use crate::core_bridge::CoreBridge;
8use crate::error::Result;
9use crate::events::EventBus;
10use crate::history::{History, VersionControl};
11use crate::merge::MergeService;
12use crate::sync::SyncEngine;
13use crate::user::UserService;
14use crate::websocket::{ws_handler, WsState};
15use crate::workspace::WorkspaceService;
16use axum::routing::get;
17use axum::Router;
18use sqlx::{Pool, Sqlite};
19use std::sync::Arc;
20
21pub struct CollabServer {
23 _config: CollabConfig,
25 db: Pool<Sqlite>,
27 auth: Arc<AuthService>,
29 user: Arc<UserService>,
31 workspace: Arc<WorkspaceService>,
33 event_bus: Arc<EventBus>,
35 sync: Arc<SyncEngine>,
37 history: Arc<History>,
39 merge: Arc<MergeService>,
41 backup: Arc<BackupService>,
43}
44
45impl CollabServer {
46 pub async fn new(config: CollabConfig) -> Result<Self> {
52 let db = sqlx::SqlitePool::connect(&config.database_url).await?;
54
55 Self::run_migrations(&db).await?;
57
58 let workspace_dir = config.workspace_dir.as_deref().unwrap_or("./workspaces");
60 let core_bridge = Arc::new(CoreBridge::new(workspace_dir));
61
62 let auth = Arc::new(AuthService::new(config.jwt_secret.clone()));
64 let user = Arc::new(UserService::new(db.clone(), auth.clone()));
65 let workspace =
66 Arc::new(WorkspaceService::with_core_bridge(db.clone(), core_bridge.clone()));
67 let event_bus = Arc::new(EventBus::new(config.event_bus_capacity));
68 let sync = Arc::new(SyncEngine::with_integration(
69 event_bus.clone(),
70 db.clone(),
71 core_bridge.clone(),
72 workspace.clone(),
73 ));
74 let mut history = History::new(db.clone());
75 history.set_auto_commit(config.auto_commit);
76 let history = Arc::new(history);
77
78 let merge = Arc::new(MergeService::new(db.clone()));
80
81 let backup = Arc::new(BackupService::new(
83 db.clone(),
84 config.backup_dir.clone(),
85 core_bridge,
86 workspace.clone(),
87 ));
88
89 Ok(Self {
90 _config: config,
91 db,
92 auth,
93 user,
94 workspace,
95 event_bus,
96 sync,
97 history,
98 merge,
99 backup,
100 })
101 }
102
103 pub async fn run_migrations(db: &sqlx::SqlitePool) -> Result<()> {
112 tracing::info!("Running database migrations");
113 sqlx::migrate!("./migrations").run(db).await.map_err(|e| {
114 tracing::error!("Migration failed: {}", e);
115 crate::error::CollabError::DatabaseError(format!("Migration failed: {e}"))
116 })?;
117 tracing::info!("Database migrations completed successfully");
118 Ok(())
119 }
120
121 pub async fn run(self, addr: &str) -> Result<()> {
127 tracing::info!("Starting MockForge Collaboration Server on {}", addr);
128
129 let version_control = Arc::new(VersionControl::new(self.db.clone()));
131
132 let api_state = ApiState {
138 auth: self.auth.clone(),
139 user: self.user.clone(),
140 workspace: self.workspace.clone(),
141 history: version_control,
142 merge: self.merge.clone(),
143 backup: self.backup.clone(),
144 sync: self.sync.clone(),
145 };
146 let api_router = create_api_router(api_state);
147
148 let ws_state = WsState {
150 auth: self.auth.clone(),
151 sync: self.sync.clone(),
152 event_bus: self.event_bus.clone(),
153 workspace: self.workspace.clone(),
154 };
155
156 let app = Router::new()
158 .route("/ws", get(ws_handler))
159 .with_state(ws_state)
160 .merge(api_router);
161
162 let listener = tokio::net::TcpListener::bind(addr)
164 .await
165 .map_err(|e| crate::error::CollabError::Internal(format!("Failed to bind: {e}")))?;
166
167 tracing::info!("Server listening on {}", addr);
168
169 axum::serve(listener, app)
171 .await
172 .map_err(|e| crate::error::CollabError::Internal(format!("Server error: {e}")))?;
173
174 Ok(())
175 }
176
177 #[must_use]
179 pub fn auth(&self) -> Arc<AuthService> {
180 self.auth.clone()
181 }
182
183 #[must_use]
185 pub fn workspace(&self) -> Arc<WorkspaceService> {
186 self.workspace.clone()
187 }
188
189 #[must_use]
191 pub fn sync(&self) -> Arc<SyncEngine> {
192 self.sync.clone()
193 }
194
195 #[must_use]
197 pub fn history(&self) -> Arc<History> {
198 self.history.clone()
199 }
200}