UNPKG

@re-shell/cli

Version:

Full-stack development platform uniting microservices and microfrontends. Build complete applications with .NET (ASP.NET Core Web API, Minimal API), Java (Spring Boot, Quarkus, Micronaut, Vert.x), Rust (Actix-Web, Warp, Rocket, Axum), Python (FastAPI, Dja

502 lines (501 loc) โ€ข 24.7 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.showCacheStats = showCacheStats; exports.configureCacheSettings = configureCacheSettings; exports.clearCache = clearCache; exports.testCachePerformance = testCachePerformance; exports.optimizeCache = optimizeCache; exports.listCachedCommands = listCachedCommands; const chalk_1 = __importDefault(require("chalk")); const spinner_1 = require("../utils/spinner"); const error_handler_1 = require("../utils/error-handler"); const plugin_command_cache_1 = require("../utils/plugin-command-cache"); const plugin_command_registry_1 = require("../utils/plugin-command-registry"); // Show cache statistics async function showCacheStats(options = {}) { const { verbose = false, json = false } = options; try { const cacheManager = (0, plugin_command_cache_1.createCommandCacheManager)(); const stats = cacheManager.getCacheStats(); const metrics = cacheManager.getMetrics(); const config = cacheManager.getConfiguration(); if (json) { console.log(JSON.stringify({ stats, metrics, config }, null, 2)); return; } console.log(chalk_1.default.cyan('๐Ÿ“Š Command Cache Statistics\n')); // Cache Overview console.log(chalk_1.default.yellow('Cache Overview:')); console.log(` Status: ${config.enabled ? chalk_1.default.green('Enabled') : chalk_1.default.red('Disabled')}`); console.log(` Strategy: ${config.strategy}`); console.log(` Size: ${stats.size} entries`); console.log(` Memory usage: ${(0, plugin_command_cache_1.formatCacheSize)(stats.memoryUsage)}`); console.log(` Hit rate: ${(0, plugin_command_cache_1.formatCacheHitRate)(stats.hitRate)}`); // Performance Metrics console.log(chalk_1.default.yellow('\nPerformance Metrics:')); console.log(` Total executions: ${metrics.totalExecutions}`); console.log(` Cache hits: ${chalk_1.default.green(metrics.cacheHits)}`); console.log(` Cache misses: ${chalk_1.default.red(metrics.cacheMisses)}`); console.log(` Average execution time: ${(0, plugin_command_cache_1.formatExecutionTime)(metrics.averageExecutionTime)}`); console.log(` Average cached time: ${(0, plugin_command_cache_1.formatExecutionTime)(metrics.averageCachedExecutionTime)}`); console.log(` Error rate: ${(metrics.errorRate * 100).toFixed(1)}%`); if (verbose) { // Configuration Details console.log(chalk_1.default.yellow('\nConfiguration:')); console.log(` Max size: ${config.maxSize} entries`); console.log(` Max memory: ${(0, plugin_command_cache_1.formatCacheSize)(config.maxMemoryUsage)}`); console.log(` Default TTL: ${(0, plugin_command_cache_1.formatExecutionTime)(config.defaultTTL)}`); console.log(` Cleanup interval: ${(0, plugin_command_cache_1.formatExecutionTime)(config.cleanupInterval)}`); console.log(` Invalidation strategy: ${config.invalidationStrategy}`); console.log(` Compression: ${config.compressionEnabled ? 'Yes' : 'No'}`); console.log(` Encryption: ${config.encryptionEnabled ? 'Yes' : 'No'}`); console.log(` Persist to disk: ${config.persistToDisk ? 'Yes' : 'No'}`); // Cache Entry Details if (stats.oldestEntry) { console.log(chalk_1.default.yellow('\nCache Entries:')); console.log(` Oldest: ${new Date(stats.oldestEntry.createdAt).toLocaleString()}`); console.log(` Newest: ${new Date(stats.newestEntry?.createdAt || 0).toLocaleString()}`); console.log(` Most accessed: ${stats.mostAccessedEntry?.accessCount || 0} times`); console.log(` Largest: ${(0, plugin_command_cache_1.formatCacheSize)(stats.largestEntry?.size || 0)}`); } // Last cleanup console.log(chalk_1.default.yellow('\nMaintenance:')); console.log(` Last cleanup: ${new Date(metrics.lastCleanupAt).toLocaleString()}`); } // Performance recommendations if (stats.hitRate < 0.5) { console.log(chalk_1.default.red('\nโš ๏ธ Low cache hit rate detected')); console.log(chalk_1.default.blue('๐Ÿ’ก Consider increasing TTL or adjusting invalidation strategy')); } if (stats.memoryUsage > config.maxMemoryUsage * 0.8) { console.log(chalk_1.default.yellow('\nโš ๏ธ High memory usage detected')); console.log(chalk_1.default.blue('๐Ÿ’ก Consider increasing max memory or enabling compression')); } await cacheManager.destroy(); } catch (error) { throw new error_handler_1.ValidationError(`Failed to show cache statistics: ${error instanceof Error ? error.message : String(error)}`); } } // Configure cache settings async function configureCacheSettings(setting, value, options = {}) { const { verbose = false } = options; try { const cacheManager = (0, plugin_command_cache_1.createCommandCacheManager)(); const currentConfig = cacheManager.getConfiguration(); // Validate setting const validSettings = [ 'enabled', 'strategy', 'maxSize', 'maxMemoryUsage', 'defaultTTL', 'cleanupInterval', 'compressionEnabled', 'encryptionEnabled', 'persistToDisk', 'performanceMonitoring' ]; if (!validSettings.includes(setting)) { throw new error_handler_1.ValidationError(`Invalid setting '${setting}'. Valid options: ${validSettings.join(', ')}`); } // Parse value based on setting type let parsedValue = value; switch (setting) { case 'enabled': case 'compressionEnabled': case 'encryptionEnabled': case 'persistToDisk': parsedValue = value.toLowerCase() === 'true'; break; case 'maxSize': case 'cleanupInterval': parsedValue = parseInt(value, 10); if (isNaN(parsedValue) || parsedValue < 0) { throw new error_handler_1.ValidationError(`${setting} must be a positive number`); } break; case 'maxMemoryUsage': case 'defaultTTL': parsedValue = parseInt(value, 10); if (isNaN(parsedValue) || parsedValue <= 0) { throw new error_handler_1.ValidationError(`${setting} must be a positive number`); } break; case 'strategy': if (!Object.values(plugin_command_cache_1.CacheStorageStrategy).includes(value)) { throw new error_handler_1.ValidationError(`Invalid strategy. Valid options: ${Object.values(plugin_command_cache_1.CacheStorageStrategy).join(', ')}`); } parsedValue = value; break; case 'performanceMonitoring': if (!Object.values(plugin_command_cache_1.PerformanceMonitoringLevel).includes(value)) { throw new error_handler_1.ValidationError(`Invalid monitoring level. Valid options: ${Object.values(plugin_command_cache_1.PerformanceMonitoringLevel).join(', ')}`); } parsedValue = value; break; } // Update configuration const updates = { [setting]: parsedValue }; cacheManager.updateConfiguration(updates); console.log(chalk_1.default.green(`โœ“ Updated cache configuration: ${setting} = ${parsedValue}`)); if (verbose) { console.log(chalk_1.default.yellow('\nCurrent Configuration:')); const newConfig = cacheManager.getConfiguration(); Object.entries(newConfig).forEach(([key, val]) => { const isChanged = key === setting; const color = isChanged ? 'cyan' : 'gray'; const colorFn = chalk_1.default[color]; console.log(` ${colorFn(key)}: ${val}`); }); } await cacheManager.destroy(); } catch (error) { throw new error_handler_1.ValidationError(`Failed to configure cache settings: ${error instanceof Error ? error.message : String(error)}`); } } // Clear cache async function clearCache(options = {}) { const { verbose = false, command, tags, force = false } = options; if (!force) { console.log(chalk_1.default.yellow('โš ๏ธ This will clear cached command results')); console.log(chalk_1.default.blue('Use --force to confirm the operation')); return; } try { const cacheManager = (0, plugin_command_cache_1.createCommandCacheManager)(); const spinner = (0, spinner_1.createSpinner)('Clearing cache...'); spinner.start(); let clearedCount = 0; if (command) { // Clear specific command cache clearedCount = await cacheManager.invalidateByCommand(command); spinner.stop(); console.log(chalk_1.default.green(`โœ“ Cleared cache for command '${command}' (${clearedCount} entries)`)); } else if (tags) { // Clear by tags const tagList = tags.split(',').map(tag => tag.trim()); clearedCount = await cacheManager.invalidateByTags(tagList); spinner.stop(); console.log(chalk_1.default.green(`โœ“ Cleared cache for tags: ${tagList.join(', ')} (${clearedCount} entries)`)); } else { // Clear all cache const statsBefore = cacheManager.getCacheStats(); await cacheManager.clearAll(); clearedCount = statsBefore.size; spinner.stop(); console.log(chalk_1.default.green(`โœ“ Cleared all cache (${clearedCount} entries)`)); } if (verbose && clearedCount > 0) { console.log(chalk_1.default.yellow('\nCache cleared successfully')); console.log(` Entries removed: ${clearedCount}`); console.log(` Memory freed: ${(0, plugin_command_cache_1.formatCacheSize)(0)}`); // Would calculate actual freed memory } await cacheManager.destroy(); } catch (error) { throw new error_handler_1.ValidationError(`Failed to clear cache: ${error instanceof Error ? error.message : String(error)}`); } } // Test cache performance async function testCachePerformance(iterations, options = {}) { const { verbose = false, json = false } = options; try { const iterationCount = parseInt(iterations, 10); if (isNaN(iterationCount) || iterationCount <= 0) { throw new error_handler_1.ValidationError('Iterations must be a positive number'); } const { Command } = require('commander'); const tempProgram = new Command(); const commandRegistry = (0, plugin_command_registry_1.createPluginCommandRegistry)(tempProgram); await commandRegistry.initialize(); const cacheManager = (0, plugin_command_cache_1.createCommandCacheManager)({ enabled: true, strategy: plugin_command_cache_1.CacheStorageStrategy.MEMORY, maxSize: 1000, defaultTTL: 60000 }); console.log(chalk_1.default.cyan(`๐Ÿงช Testing Cache Performance (${iterationCount} iterations)\n`)); const spinner = (0, spinner_1.createSpinner)('Running performance test...'); spinner.start(); const results = { totalIterations: iterationCount, executionTimes: [], cacheHitTimes: [], cacheMissTimes: [], hitCount: 0, missCount: 0 }; // Mock command execution function const mockCommandExecution = async () => { // Simulate command execution time await new Promise(resolve => setTimeout(resolve, Math.random() * 100 + 50)); return `Mock result ${Date.now()}`; }; // Create mock context const mockContext = { command: { name: 'test-command' }, plugin: { manifest: { name: 'test-plugin' } }, cli: { program: tempProgram, rootPath: process.cwd(), configPath: '', version: '1.0.0' }, logger: { debug: () => { }, info: () => { }, warn: () => { }, error: () => { } }, utils: { path: require('path'), chalk: chalk_1.default, spinner: null } }; for (let i = 0; i < iterationCount; i++) { const startTime = performance.now(); const result = await cacheManager.executeWithCache('test-command', { iteration: i % 10 }, // Repeat args to test cache hits { flag: true }, mockContext, mockCommandExecution); const executionTime = performance.now() - startTime; results.executionTimes.push(executionTime); if (result.hit) { results.cacheHitTimes.push(executionTime); results.hitCount++; } else { results.cacheMissTimes.push(executionTime); results.missCount++; } } spinner.stop(); const averageExecutionTime = results.executionTimes.reduce((sum, time) => sum + time, 0) / results.executionTimes.length; const averageHitTime = results.cacheHitTimes.length > 0 ? results.cacheHitTimes.reduce((sum, time) => sum + time, 0) / results.cacheHitTimes.length : 0; const averageMissTime = results.cacheMissTimes.length > 0 ? results.cacheMissTimes.reduce((sum, time) => sum + time, 0) / results.cacheMissTimes.length : 0; const hitRate = results.hitCount / iterationCount; const performanceGain = averageMissTime > 0 ? ((averageMissTime - averageHitTime) / averageMissTime) * 100 : 0; if (json) { console.log(JSON.stringify({ ...results, averageExecutionTime, averageHitTime, averageMissTime, hitRate, performanceGain }, null, 2)); await cacheManager.destroy(); return; } console.log(chalk_1.default.green('โœ“ Performance test completed\n')); console.log(chalk_1.default.yellow('Results:')); console.log(` Total iterations: ${iterationCount}`); console.log(` Cache hits: ${chalk_1.default.green(results.hitCount)}`); console.log(` Cache misses: ${chalk_1.default.red(results.missCount)}`); console.log(` Hit rate: ${(0, plugin_command_cache_1.formatCacheHitRate)(hitRate)}`); console.log(chalk_1.default.yellow('\nPerformance:')); console.log(` Average execution time: ${(0, plugin_command_cache_1.formatExecutionTime)(averageExecutionTime)}`); console.log(` Average hit time: ${(0, plugin_command_cache_1.formatExecutionTime)(averageHitTime)}`); console.log(` Average miss time: ${(0, plugin_command_cache_1.formatExecutionTime)(averageMissTime)}`); console.log(` Performance gain: ${performanceGain.toFixed(1)}%`); if (verbose) { console.log(chalk_1.default.yellow('\nCache Statistics:')); const stats = cacheManager.getCacheStats(); console.log(` Cache size: ${stats.size} entries`); console.log(` Memory usage: ${(0, plugin_command_cache_1.formatCacheSize)(stats.memoryUsage)}`); console.log(chalk_1.default.yellow('\nRecommendations:')); if (hitRate < 0.3) { console.log(chalk_1.default.red(' โ€ข Low hit rate - consider increasing TTL')); } if (performanceGain > 50) { console.log(chalk_1.default.green(' โ€ข Excellent performance gain from caching')); } else if (performanceGain < 20) { console.log(chalk_1.default.yellow(' โ€ข Moderate performance gain - cache may not be necessary')); } } await cacheManager.destroy(); } catch (error) { throw new error_handler_1.ValidationError(`Failed to test cache performance: ${error instanceof Error ? error.message : String(error)}`); } } // Optimize cache async function optimizeCache(options = {}) { const { verbose = false, force = false } = options; if (!force) { console.log(chalk_1.default.yellow('โš ๏ธ This will analyze and optimize cache configuration')); console.log(chalk_1.default.blue('Use --force to apply optimizations automatically')); } try { const cacheManager = (0, plugin_command_cache_1.createCommandCacheManager)(); const stats = cacheManager.getCacheStats(); const metrics = cacheManager.getMetrics(); const config = cacheManager.getConfiguration(); console.log(chalk_1.default.cyan('๐Ÿ”ง Cache Optimization Analysis\n')); const recommendations = []; // Analyze hit rate if (stats.hitRate < 0.3) { recommendations.push({ issue: 'Low cache hit rate', recommendation: 'Increase default TTL to keep entries longer', setting: 'defaultTTL', newValue: config.defaultTTL * 2, priority: 'high' }); } // Analyze memory usage if (stats.memoryUsage > config.maxMemoryUsage * 0.8) { recommendations.push({ issue: 'High memory usage', recommendation: 'Enable compression to reduce memory footprint', setting: 'compressionEnabled', newValue: true, priority: 'medium' }); } // Analyze cache size if (stats.size > config.maxSize * 0.9) { recommendations.push({ issue: 'Cache near capacity', recommendation: 'Increase max cache size', setting: 'maxSize', newValue: Math.floor(config.maxSize * 1.5), priority: 'medium' }); } // Analyze error rate if (metrics.errorRate > 0.1) { recommendations.push({ issue: 'High error rate', recommendation: 'Errors are not cached but tracked - consider investigating command failures', priority: 'high' }); } // Analyze performance if (metrics.averageExecutionTime > 5000) { recommendations.push({ issue: 'Slow command execution', recommendation: 'Commands are slow - caching provides significant benefit', priority: 'low' }); } // Display recommendations if (recommendations.length === 0) { console.log(chalk_1.default.green('โœ“ Cache is already optimally configured')); await cacheManager.destroy(); return; } console.log(chalk_1.default.yellow('Optimization Recommendations:\n')); recommendations.forEach((rec, index) => { const priorityColor = rec.priority === 'high' ? 'red' : rec.priority === 'medium' ? 'yellow' : 'blue'; const priorityIcon = rec.priority === 'high' ? '๐Ÿ”ด' : rec.priority === 'medium' ? '๐ŸŸก' : '๐Ÿ”ต'; console.log(`${index + 1}. ${priorityIcon} ${rec.issue}`); console.log(` ${rec.recommendation}`); if (rec.setting && rec.newValue !== undefined) { console.log(` ${chalk_1.default.gray(`Suggested: ${rec.setting} = ${rec.newValue}`)}`); } console.log(''); }); // Apply optimizations if forced if (force) { const spinner = (0, spinner_1.createSpinner)('Applying optimizations...'); spinner.start(); const updates = {}; let appliedCount = 0; for (const rec of recommendations) { if (rec.setting && rec.newValue !== undefined) { updates[rec.setting] = rec.newValue; appliedCount++; } } if (appliedCount > 0) { cacheManager.updateConfiguration(updates); spinner.stop(); console.log(chalk_1.default.green(`โœ“ Applied ${appliedCount} optimization(s)`)); if (verbose) { console.log(chalk_1.default.yellow('\nUpdated Configuration:')); const newConfig = cacheManager.getConfiguration(); Object.entries(updates).forEach(([key, value]) => { console.log(` ${chalk_1.default.cyan(key)}: ${value}`); }); } } else { spinner.stop(); console.log(chalk_1.default.yellow('No configuration changes to apply')); } } else { console.log(chalk_1.default.blue('๐Ÿ’ก Use --force to apply these optimizations automatically')); } await cacheManager.destroy(); } catch (error) { throw new error_handler_1.ValidationError(`Failed to optimize cache: ${error instanceof Error ? error.message : String(error)}`); } } // List cached commands async function listCachedCommands(options = {}) { const { verbose = false, json = false, includeErrors = false } = options; try { const cacheManager = (0, plugin_command_cache_1.createCommandCacheManager)(); const stats = cacheManager.getCacheStats(); // Mock getting cache entries (would be implemented in real cache manager) const mockEntries = [ { key: 'abc123', command: 'build', args: { target: 'production' }, createdAt: Date.now() - 300000, lastAccessedAt: Date.now() - 60000, accessCount: 5, size: 2048, success: true }, { key: 'def456', command: 'test', args: { coverage: true }, createdAt: Date.now() - 180000, lastAccessedAt: Date.now() - 30000, accessCount: 3, size: 1024, success: true } ]; if (json) { console.log(JSON.stringify(mockEntries, null, 2)); await cacheManager.destroy(); return; } console.log(chalk_1.default.cyan('๐Ÿ“‹ Cached Commands\n')); if (mockEntries.length === 0) { console.log(chalk_1.default.yellow('No cached commands found.')); await cacheManager.destroy(); return; } console.log(chalk_1.default.yellow('Cache Overview:')); console.log(` Total entries: ${stats.size}`); console.log(` Memory usage: ${(0, plugin_command_cache_1.formatCacheSize)(stats.memoryUsage)}`); console.log(''); mockEntries.forEach((entry, index) => { const successIcon = entry.success ? chalk_1.default.green('โœ“') : chalk_1.default.red('โœ—'); const timeAgo = Math.round((Date.now() - entry.lastAccessedAt) / 1000 / 60); console.log(`${index + 1}. ${successIcon} ${chalk_1.default.cyan(entry.command)}`); console.log(` ${chalk_1.default.gray('Args:')} ${JSON.stringify(entry.args)}`); console.log(` ${chalk_1.default.gray('Size:')} ${(0, plugin_command_cache_1.formatCacheSize)(entry.size)}`); console.log(` ${chalk_1.default.gray('Access count:')} ${entry.accessCount}`); console.log(` ${chalk_1.default.gray('Last accessed:')} ${timeAgo}m ago`); if (verbose) { console.log(` ${chalk_1.default.gray('Key:')} ${entry.key}`); console.log(` ${chalk_1.default.gray('Created:')} ${new Date(entry.createdAt).toLocaleString()}`); } console.log(''); }); await cacheManager.destroy(); } catch (error) { throw new error_handler_1.ValidationError(`Failed to list cached commands: ${error instanceof Error ? error.message : String(error)}`); } }