@boundless-oss/atlas
Version:
Atlas - MCP Server for comprehensive startup project management
193 lines • 6.9 kB
JavaScript
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