config.jsā¢9.79 kB
/**
* Configuration Management System
* Handles user-configurable settings and thresholds
*/
import fs from 'fs-extra';
import path from 'path';
export class ConfigManager {
constructor(configPath = './mcp-config.json') {
this.configPath = configPath;
this.defaultConfig = {
// Smart Analysis Settings
similarityThresholds: {
feature: 0.6, // Feature similarity threshold for updates vs new files
steps: 0.8, // Step similarity threshold for reuse
selectors: 0.5, // Selector overlap threshold for page object updates
content: 0.4 // General content similarity threshold
},
// File Generation Settings
fileGeneration: {
alwaysCreateBackups: true,
preserveExistingComments: true,
addGeneratedTimestamp: true,
includeMetadata: true
},
// Code Quality Settings
codeQuality: {
enforceJSDoc: true,
enforceErrorHandling: true,
enforcePageObjectModel: true,
maxFunctionLength: 50,
maxFileLength: 500
},
// Pattern Recognition Settings
patternRecognition: {
enableSemanticAnalysis: true,
cachePatterns: true,
maxCacheAge: 3600000, // 1 hour in milliseconds
analysisDepth: 'deep' // 'shallow', 'medium', 'deep'
},
// Output Formatting
outputFormatting: {
indentationType: 'spaces',
indentationSize: 2,
quoteStyle: 'single',
semicolons: true,
trailingCommas: true
},
// Performance Settings
performance: {
enableParallelProcessing: true,
maxConcurrentFiles: 10,
enableCaching: true,
timeoutMs: 30000
},
// Repository Analysis
repositoryAnalysis: {
maxFilesToAnalyze: 100,
skipDirectories: ['node_modules', '.git', 'dist', 'build', 'coverage'],
includeFileTypes: ['.js', '.ts', '.feature'],
extractUtilFunctions: true
},
// User Preferences
userPreferences: {
verboseLogging: false,
showProgressIndicators: true,
autoSaveGeneratedFiles: true,
confirmBeforeOverwrite: false
}
};
this.config = { ...this.defaultConfig };
this.loadConfig();
}
async loadConfig() {
try {
if (await fs.pathExists(this.configPath)) {
const userConfig = await fs.readJson(this.configPath);
this.config = this.mergeConfigs(this.defaultConfig, userConfig);
} else {
await this.saveConfig();
}
} catch (error) {
console.warn(`Failed to load config: ${error.message}. Using defaults.`);
}
}
async saveConfig() {
try {
await fs.writeJson(this.configPath, this.config, { spaces: 2 });
} catch (error) {
console.error(`Failed to save config: ${error.message}`);
}
}
mergeConfigs(defaultConfig, userConfig) {
const merged = { ...defaultConfig };
Object.keys(userConfig).forEach(key => {
if (typeof userConfig[key] === 'object' && !Array.isArray(userConfig[key])) {
merged[key] = { ...defaultConfig[key], ...userConfig[key] };
} else {
merged[key] = userConfig[key];
}
});
return merged;
}
get(key) {
const keys = key.split('.');
let value = this.config;
for (const k of keys) {
if (value && typeof value === 'object' && k in value) {
value = value[k];
} else {
return undefined;
}
}
return value;
}
set(key, value) {
const keys = key.split('.');
let target = this.config;
for (let i = 0; i < keys.length - 1; i++) {
const k = keys[i];
if (!(k in target) || typeof target[k] !== 'object') {
target[k] = {};
}
target = target[k];
}
target[keys[keys.length - 1]] = value;
this.saveConfig();
}
getFeatureSimilarityThreshold() {
return this.get('similarityThresholds.feature');
}
getStepSimilarityThreshold() {
return this.get('similarityThresholds.steps');
}
getSelectorSimilarityThreshold() {
return this.get('similarityThresholds.selectors');
}
shouldEnforceJSDoc() {
return this.get('codeQuality.enforceJSDoc');
}
shouldEnableParallelProcessing() {
return this.get('performance.enableParallelProcessing');
}
getMaxConcurrentFiles() {
return this.get('performance.maxConcurrentFiles');
}
getMaxFilesToAnalyze() {
return this.get('repositoryAnalysis.maxFilesToAnalyze');
}
getSkipDirectories() {
return this.get('repositoryAnalysis.skipDirectories');
}
getIndentationConfig() {
return {
type: this.get('outputFormatting.indentationType'),
size: this.get('outputFormatting.indentationSize')
};
}
isVerboseLogging() {
return this.get('userPreferences.verboseLogging');
}
shouldShowProgress() {
return this.get('userPreferences.showProgressIndicators');
}
// Validation methods
validateConfig() {
const errors = [];
// Validate similarity thresholds
const thresholds = this.get('similarityThresholds');
Object.keys(thresholds).forEach(key => {
const value = thresholds[key];
if (typeof value !== 'number' || value < 0 || value > 1) {
errors.push(`Invalid similarity threshold for ${key}: must be between 0 and 1`);
}
});
// Validate performance settings
const maxConcurrent = this.get('performance.maxConcurrentFiles');
if (typeof maxConcurrent !== 'number' || maxConcurrent < 1 || maxConcurrent > 100) {
errors.push('maxConcurrentFiles must be between 1 and 100');
}
// Validate code quality settings
const maxFunctionLength = this.get('codeQuality.maxFunctionLength');
if (typeof maxFunctionLength !== 'number' || maxFunctionLength < 10) {
errors.push('maxFunctionLength must be at least 10');
}
return errors;
}
// Export current configuration
async exportConfig(filePath) {
try {
await fs.writeJson(filePath, this.config, { spaces: 2 });
return true;
} catch (error) {
console.error(`Failed to export config: ${error.message}`);
return false;
}
}
// Import configuration
async importConfig(filePath) {
try {
const importedConfig = await fs.readJson(filePath);
this.config = this.mergeConfigs(this.defaultConfig, importedConfig);
const errors = this.validateConfig();
if (errors.length > 0) {
console.warn('Configuration validation warnings:', errors);
}
await this.saveConfig();
return true;
} catch (error) {
console.error(`Failed to import config: ${error.message}`);
return false;
}
}
// Reset to defaults
async resetToDefaults() {
this.config = { ...this.defaultConfig };
await this.saveConfig();
}
// Get configuration schema for UI generation
getConfigSchema() {
return {
similarityThresholds: {
type: 'object',
description: 'Thresholds for determining when to update vs create files',
properties: {
feature: { type: 'number', min: 0, max: 1, description: 'Feature similarity threshold' },
steps: { type: 'number', min: 0, max: 1, description: 'Step similarity threshold' },
selectors: { type: 'number', min: 0, max: 1, description: 'Selector overlap threshold' },
content: { type: 'number', min: 0, max: 1, description: 'Content similarity threshold' }
}
},
codeQuality: {
type: 'object',
description: 'Code quality enforcement settings',
properties: {
enforceJSDoc: { type: 'boolean', description: 'Require JSDoc comments' },
enforceErrorHandling: { type: 'boolean', description: 'Require error handling' },
enforcePageObjectModel: { type: 'boolean', description: 'Enforce POM patterns' },
maxFunctionLength: { type: 'number', min: 10, description: 'Maximum function length' }
}
},
performance: {
type: 'object',
description: 'Performance optimization settings',
properties: {
enableParallelProcessing: { type: 'boolean', description: 'Enable parallel file processing' },
maxConcurrentFiles: { type: 'number', min: 1, max: 100, description: 'Max concurrent files' },
enableCaching: { type: 'boolean', description: 'Enable pattern caching' }
}
}
};
}
}