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