@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
JavaScript
;
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)}`);
}
}