UNPKG

@boundless-oss/atlas

Version:

Atlas - MCP Server for comprehensive startup project management

193 lines 6.9 kB
import path from 'path'; import crypto from 'crypto'; import { ConfigManager } from '../../config/config-manager.js'; import { NodeFileSystemAdapter } from './file-system-adapter.js'; export class WorkspaceDataStore { store = { workspaces: {} }; configManager; MODULE_NAME = 'workspace'; DATA_FILE = 'workspace.json'; fs; constructor(configManager, fs) { this.configManager = configManager || new ConfigManager(); this.fs = fs || new NodeFileSystemAdapter(); } async init() { const storageManager = this.configManager.getStorageManager(); await storageManager.ensureStorageDirectories(); const data = await storageManager.loadData(this.MODULE_NAME, this.DATA_FILE); if (data) { this.store = data; } else { await this.save(); } } async save() { const storageManager = this.configManager.getStorageManager(); await storageManager.saveData(this.MODULE_NAME, this.DATA_FILE, this.store); } createWorkspace(name, rootPath, description) { const workspace = { id: this.generateId('ws'), name, description, rootPath, repositories: [], createdAt: new Date(), updatedAt: new Date(), settings: { autoSync: true, syncInterval: 3600000, // 1 hour crossRepoTags: true, }, }; this.store.workspaces[workspace.id] = workspace; if (!this.store.activeWorkspaceId) { this.store.activeWorkspaceId = workspace.id; } return workspace; } getWorkspace(nameOrId) { if (this.store.workspaces[nameOrId]) { return this.store.workspaces[nameOrId]; } return Object.values(this.store.workspaces).find(ws => ws.name === nameOrId); } getActiveWorkspace() { if (!this.store.activeWorkspaceId) { return undefined; } return this.store.workspaces[this.store.activeWorkspaceId]; } setActiveWorkspace(workspaceNameOrId) { // Try by ID first if (this.store.workspaces[workspaceNameOrId]) { this.store.activeWorkspaceId = workspaceNameOrId; return true; } // Try by name const workspace = this.getWorkspace(workspaceNameOrId); if (workspace) { this.store.activeWorkspaceId = workspace.id; return true; } return false; } addRepository(workspaceNameOrId, repo) { const workspace = this.getWorkspace(workspaceNameOrId); if (!workspace) { return null; } const newRepo = { ...repo, id: this.generateId('repo'), lastSync: new Date(), }; workspace.repositories.push(newRepo); workspace.updatedAt = new Date(); return newRepo; } async detectRepositories(rootPath) { const repositories = []; try { const entries = await this.fs.readdir(rootPath); for (const entry of entries) { const isDir = typeof entry.isDirectory === 'function' ? entry.isDirectory() : entry.isDirectory; if (isDir && !entry.name.startsWith('.')) { const repoPath = path.join(rootPath, entry.name); // Check if it's a git repository try { await this.fs.access(path.join(repoPath, '.git')); repositories.push({ id: this.generateId('repo'), name: entry.name, path: repoPath, type: 'git', lastSync: new Date(), }); } catch { // Check if it has package.json (might be a workspace package) try { await this.fs.access(path.join(repoPath, 'package.json')); repositories.push({ id: this.generateId('repo'), name: entry.name, path: repoPath, type: 'local', lastSync: new Date(), }); } catch { // Not a repository } } } } } catch (error) { console.error('Error detecting repositories:', error); } return repositories; } getRepositoriesForWorkspace(workspaceNameOrId) { const workspace = this.getWorkspace(workspaceNameOrId); return workspace?.repositories || []; } updateRepository(workspaceNameOrId, repoId, updates) { const workspace = this.getWorkspace(workspaceNameOrId); if (!workspace) { return false; } const repo = workspace.repositories.find(r => r.id === repoId); if (!repo) { return false; } Object.assign(repo, updates); repo.lastSync = new Date(); workspace.updatedAt = new Date(); return true; } getWorkspaces() { return Object.values(this.store.workspaces); } findRepository(name) { for (const workspace of Object.values(this.store.workspaces)) { const repo = workspace.repositories.find(r => r.name === name); if (repo) { return repo; } } return undefined; } findRepositoryByPath(repoPath) { for (const workspace of Object.values(this.store.workspaces)) { const repo = workspace.repositories.find(r => r.path === repoPath); if (repo) { return repo; } } return undefined; } getPrimaryRepository() { const activeWorkspace = this.getActiveWorkspace(); if (!activeWorkspace || activeWorkspace.repositories.length === 0) { return undefined; } // Return the first repository marked as primary, or the first repository return activeWorkspace.repositories.find(r => r.primary) || activeWorkspace.repositories[0]; } generateId(prefix = '') { let uuid; try { uuid = crypto.randomUUID(); } catch { // Fallback for environments where crypto.randomUUID is not available uuid = Date.now().toString(16) + '-' + Math.random().toString(16).substr(2); } return prefix ? `${prefix}-${uuid}` : uuid; } } //# sourceMappingURL=store.js.map