UNPKG

@boundless-oss/atlas

Version:

Atlas - MCP Server for comprehensive startup project management

237 lines 8.74 kB
import { StorageManager } from '../../storage/storage-manager.js'; export class CodeAnalysisStore { storageManager; moduleName = 'code-analysis'; constructor(configManager) { this.storageManager = new StorageManager(); } async initialize() { await this.storageManager.ensureStorageDirectories(); } // Analysis History Management async saveAnalysisResult(result) { let history = []; try { history = await this.storageManager.loadData(this.moduleName, 'analysis-history.json') || []; } catch { // File doesn't exist yet } history.push(result); // Keep only last 50 analyses if (history.length > 50) { history = history.slice(-50); } await this.storageManager.saveData(this.moduleName, 'analysis-history.json', history); } async getAnalysisHistory(limit) { try { const history = await this.storageManager.loadData(this.moduleName, 'analysis-history.json'); if (limit && limit > 0) { return (history || []).slice(-limit); } return history || []; } catch { return []; } } async getLatestAnalysis() { const history = await this.getAnalysisHistory(1); return history.length > 0 ? history[0] : null; } // Code Review Management async saveCodeReview(review) { let reviews = []; try { reviews = await this.storageManager.loadData(this.moduleName, 'code-reviews.json') || []; } catch { // File doesn't exist yet } reviews.push(review); // Keep only last 100 reviews if (reviews.length > 100) { reviews = reviews.slice(-100); } await this.storageManager.saveData(this.moduleName, 'code-reviews.json', reviews); } async getCodeReviews(fileFilter) { try { const reviews = await this.storageManager.loadData(this.moduleName, 'code-reviews.json'); if (fileFilter) { return (reviews || []).filter(review => review.file.includes(fileFilter)); } return reviews || []; } catch { return []; } } // Metrics History Management async saveMetricsHistory(projectId, entry) { let history; try { history = await this.storageManager.loadData(this.moduleName, `metrics-${projectId}.json`) || { projectId, entries: [], baseline: undefined, }; } catch { history = { projectId, entries: [], baseline: undefined, trends: [], }; } history.entries.push(entry); // Keep only last 30 days of entries const thirtyDaysAgo = new Date(); thirtyDaysAgo.setDate(thirtyDaysAgo.getDate() - 30); history.entries = history.entries.filter(e => new Date(e.timestamp) > thirtyDaysAgo); await this.storageManager.saveData(this.moduleName, `metrics-${projectId}.json`, history); } async getMetricsHistory(projectId) { try { return await this.storageManager.loadData(this.moduleName, `metrics-${projectId}.json`); } catch { return null; } } async setBaseline(projectId, commit, metrics) { let history = await this.getMetricsHistory(projectId); if (!history) { history = { projectId, entries: [], baseline: undefined, trends: [], }; } history.baseline = { timestamp: new Date().toISOString(), branch: 'main', commit, metrics, }; await this.storageManager.saveData(this.moduleName, `metrics-${projectId}.json`, history); } // Trend Analysis async getMetricsTrend(projectId, metricPath, days = 7) { const history = await this.getMetricsHistory(projectId); if (!history) { return []; } const startDate = new Date(); startDate.setDate(startDate.getDate() - days); const trend = history.entries .filter(entry => new Date(entry.timestamp) > startDate) .map(entry => { const value = this.getNestedValue(entry.metrics, metricPath); return { timestamp: entry.timestamp, value: typeof value === 'number' ? value : 0, }; }) .filter(item => item.value !== 0); return trend; } async getQualityScore(projectId) { const history = await this.getMetricsHistory(projectId); if (!history || history.entries.length === 0) { return 0; } const latestEntry = history.entries[history.entries.length - 1]; const metrics = latestEntry.metrics; // Calculate weighted quality score const complexityScore = Math.max(0, 100 - metrics.complexity.average * 5); const maintainabilityScore = metrics.maintainability.average; const duplicationScore = Math.max(0, 100 - metrics.duplication.percentage); const issuesScore = Math.max(0, 100 - metrics.quality.issues.total * 2); const qualityScore = (complexityScore * 0.25 + maintainabilityScore * 0.35 + duplicationScore * 0.2 + issuesScore * 0.2); return Math.round(qualityScore); } getNestedValue(obj, path) { const keys = path.split('.'); let current = obj; for (const key of keys) { if (current && typeof current === 'object' && key in current) { current = current[key]; } else { return undefined; } } return current; } // Custom Rules Management async saveCustomRules(projectId, rules) { await this.storageManager.saveData(this.moduleName, `rules-${projectId}.json`, rules); } async getCustomRules(projectId) { try { return await this.storageManager.loadData(this.moduleName, `rules-${projectId}.json`) || []; } catch { return []; } } // Export/Import async exportAnalysisData(projectId) { const [history, reviews, metrics, rules,] = await Promise.all([ this.getAnalysisHistory(), this.getCodeReviews(), this.getMetricsHistory(projectId), this.getCustomRules(projectId), ]); return { analysisHistory: history, codeReviews: reviews, metricsHistory: metrics, customRules: rules, exportedAt: new Date().toISOString(), }; } async importAnalysisData(projectId, data) { if (data.analysisHistory) { await this.storageManager.saveData(this.moduleName, 'analysis-history.json', data.analysisHistory); } if (data.codeReviews) { await this.storageManager.saveData(this.moduleName, 'code-reviews.json', data.codeReviews); } if (data.metricsHistory) { await this.storageManager.saveData(this.moduleName, `metrics-${projectId}.json`, data.metricsHistory); } if (data.customRules) { await this.storageManager.saveData(this.moduleName, `rules-${projectId}.json`, data.customRules); } } // Cleanup async cleanupOldData(daysToKeep = 30) { let cleanedItems = 0; // Clean analysis history const history = await this.getAnalysisHistory(); const cutoffDate = new Date(); cutoffDate.setDate(cutoffDate.getDate() - daysToKeep); const filteredHistory = history.filter(item => new Date(item.timestamp) > cutoffDate); if (filteredHistory.length < history.length) { await this.storageManager.saveData(this.moduleName, 'analysis-history.json', filteredHistory); cleanedItems += history.length - filteredHistory.length; } // Clean code reviews const reviews = await this.getCodeReviews(); const filteredReviews = reviews.filter(review => new Date(review.timestamp) > cutoffDate); if (filteredReviews.length < reviews.length) { await this.storageManager.saveData(this.moduleName, 'code-reviews.json', filteredReviews); cleanedItems += reviews.length - filteredReviews.length; } return cleanedItems; } } //# sourceMappingURL=store.js.map