@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
475 lines (474 loc) • 24.9 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.listCommandConflicts = listCommandConflicts;
exports.showConflictStrategies = showConflictStrategies;
exports.resolveConflict = resolveConflict;
exports.autoResolveConflicts = autoResolveConflicts;
exports.showConflictStats = showConflictStats;
exports.setPriorityOverride = setPriorityOverride;
exports.showResolutionHistory = showResolutionHistory;
const chalk_1 = __importDefault(require("chalk"));
const spinner_1 = require("../utils/spinner");
const error_handler_1 = require("../utils/error-handler");
const plugin_command_conflicts_1 = require("../utils/plugin-command-conflicts");
const plugin_command_registry_1 = require("../utils/plugin-command-registry");
// List command conflicts
async function listCommandConflicts(options = {}) {
const { verbose = false, json = false, type, severity, autoResolvable, resolved } = options;
try {
// Create conflict resolver with mock commands
const { Command } = require('commander');
const tempProgram = new Command();
const commandRegistry = (0, plugin_command_registry_1.createPluginCommandRegistry)(tempProgram);
await commandRegistry.initialize();
const conflictResolver = (0, plugin_command_conflicts_1.createConflictResolver)();
const commands = commandRegistry.getCommands();
conflictResolver.registerCommands(commands);
let conflicts = conflictResolver.getConflicts();
// Apply filters
if (type) {
conflicts = conflicts.filter(c => c.type === type);
}
if (severity) {
conflicts = conflicts.filter(c => c.severity === severity);
}
if (autoResolvable !== undefined) {
conflicts = conflicts.filter(c => c.autoResolvable === autoResolvable);
}
if (resolved !== undefined) {
conflicts = conflicts.filter(c => c.resolved === resolved);
}
if (json) {
console.log(JSON.stringify(conflicts, null, 2));
return;
}
console.log(chalk_1.default.cyan('\n⚠️ Command Conflicts\n'));
if (conflicts.length === 0) {
console.log(chalk_1.default.green('No command conflicts found matching criteria.'));
return;
}
// Group by severity
const conflictsBySeverity = conflicts.reduce((acc, conflict) => {
if (!acc[conflict.severity]) {
acc[conflict.severity] = [];
}
acc[conflict.severity].push(conflict);
return acc;
}, {});
// Display conflicts by severity (critical first)
const severityOrder = [plugin_command_conflicts_1.ConflictSeverity.CRITICAL, plugin_command_conflicts_1.ConflictSeverity.HIGH, plugin_command_conflicts_1.ConflictSeverity.MEDIUM, plugin_command_conflicts_1.ConflictSeverity.LOW];
severityOrder.forEach(sev => {
const severityConflicts = conflictsBySeverity[sev];
if (severityConflicts && severityConflicts.length > 0) {
const color = (0, plugin_command_conflicts_1.getConflictSeverityColor)(sev);
const colorFn = chalk_1.default[color];
console.log(colorFn(`${sev.toUpperCase()} (${severityConflicts.length})`));
severityConflicts.forEach(conflict => {
const statusIcon = conflict.resolved ? chalk_1.default.green('✓') : chalk_1.default.red('✗');
const autoIcon = conflict.autoResolvable ? chalk_1.default.blue('🤖') : '';
console.log(` ${statusIcon} ${conflict.conflictValue} ${autoIcon}`);
console.log(` Type: ${(0, plugin_command_conflicts_1.formatConflictType)(conflict.type)}`);
console.log(` Plugins: ${conflict.conflictingPlugins.join(', ')}`);
console.log(` ${chalk_1.default.gray(conflict.description)}`);
if (verbose) {
console.log(` ID: ${conflict.id}`);
console.log(` Commands: ${conflict.conflictingCommands.join(', ')}`);
console.log(` Priority: ${conflict.priority}`);
console.log(` Detected: ${new Date(conflict.detectedAt).toLocaleString()}`);
if (conflict.resolved && conflict.resolution) {
console.log(` Resolved: ${conflict.resolution.strategy} by ${conflict.resolution.appliedBy}`);
console.log(` Actions: ${conflict.resolution.actions.length}`);
}
if (conflict.suggestions.length > 0) {
console.log(` Suggestions:`);
conflict.suggestions.forEach(suggestion => {
const confIcon = suggestion.autoApplicable ? chalk_1.default.green('AUTO') : chalk_1.default.yellow('MANUAL');
console.log(` [${confIcon}] ${suggestion.description} (confidence: ${Math.round(suggestion.confidence * 100)}%)`);
});
}
}
console.log('');
});
}
});
// Summary
const stats = conflictResolver.getStats();
console.log(chalk_1.default.yellow('Summary:'));
console.log(` Total conflicts: ${stats.total}`);
console.log(` Resolved: ${chalk_1.default.green(stats.resolved)}`);
console.log(` Unresolved: ${chalk_1.default.red(stats.unresolved)}`);
console.log(` Auto-resolvable: ${chalk_1.default.blue(stats.autoResolvable)}`);
if (stats.autoResolvable > 0) {
console.log(chalk_1.default.blue('\n💡 Run with --auto-resolve to automatically fix resolvable conflicts'));
}
}
catch (error) {
throw new error_handler_1.ValidationError(`Failed to list command conflicts: ${error instanceof Error ? error.message : String(error)}`);
}
}
// Show conflict resolution strategies
async function showConflictStrategies(options = {}) {
const { verbose = false, json = false } = options;
const strategies = [
{
strategy: plugin_command_conflicts_1.ConflictResolutionStrategy.PRIORITY,
name: 'Priority-based',
description: 'Resolve based on plugin and command priorities',
autoApplicable: true,
reversible: true,
impact: 'medium'
},
{
strategy: plugin_command_conflicts_1.ConflictResolutionStrategy.NAMESPACE,
name: 'Namespace prefix',
description: 'Add plugin namespace prefix to conflicting commands',
autoApplicable: true,
reversible: true,
impact: 'low'
},
{
strategy: plugin_command_conflicts_1.ConflictResolutionStrategy.FIRST_WINS,
name: 'First wins',
description: 'Keep the first registered command, disable others',
autoApplicable: true,
reversible: true,
impact: 'high'
},
{
strategy: plugin_command_conflicts_1.ConflictResolutionStrategy.LAST_WINS,
name: 'Last wins',
description: 'Keep the last registered command, disable others',
autoApplicable: true,
reversible: true,
impact: 'high'
},
{
strategy: plugin_command_conflicts_1.ConflictResolutionStrategy.DISABLE_ALL,
name: 'Disable all',
description: 'Disable all conflicting commands',
autoApplicable: true,
reversible: true,
impact: 'high'
},
{
strategy: plugin_command_conflicts_1.ConflictResolutionStrategy.INTERACTIVE,
name: 'Interactive',
description: 'Prompt user for resolution choice',
autoApplicable: false,
reversible: true,
impact: 'varies'
}
];
if (json) {
console.log(JSON.stringify(strategies, null, 2));
return;
}
console.log(chalk_1.default.cyan('\n🔧 Conflict Resolution Strategies\n'));
strategies.forEach(strategy => {
const autoIcon = strategy.autoApplicable ? chalk_1.default.green('🤖 AUTO') : chalk_1.default.yellow('👤 MANUAL');
const impactColor = strategy.impact === 'low' ? 'green' :
strategy.impact === 'medium' ? 'yellow' : 'red';
console.log(`${chalk_1.default.white(strategy.name)} ${autoIcon}`);
console.log(` ${strategy.description}`);
const impactColorFn = chalk_1.default[impactColor];
console.log(` Impact: ${impactColorFn(strategy.impact)}`);
console.log(` Reversible: ${strategy.reversible ? chalk_1.default.green('Yes') : chalk_1.default.red('No')}`);
if (verbose) {
console.log(` Strategy: ${strategy.strategy}`);
}
console.log('');
});
if (verbose) {
console.log(chalk_1.default.yellow('Usage Examples:'));
console.log(' • priority - Good for mixed plugin priorities');
console.log(' • namespace - Safe option with minimal impact');
console.log(' • first-wins - When registration order matters');
console.log(' • last-wins - When newer plugins should override');
console.log(' • disable-all - When conflicts cannot be resolved');
}
}
// Resolve specific conflict
async function resolveConflict(conflictId, strategy, options = {}) {
const { verbose = false, dryRun = false, confirm = false } = options;
try {
// Validate strategy
const validStrategies = Object.values(plugin_command_conflicts_1.ConflictResolutionStrategy);
if (!validStrategies.includes(strategy)) {
throw new error_handler_1.ValidationError(`Invalid strategy: ${strategy}. Valid options: ${validStrategies.join(', ')}`);
}
const { Command } = require('commander');
const tempProgram = new Command();
const commandRegistry = (0, plugin_command_registry_1.createPluginCommandRegistry)(tempProgram);
await commandRegistry.initialize();
const conflictResolver = (0, plugin_command_conflicts_1.createConflictResolver)();
const commands = commandRegistry.getCommands();
conflictResolver.registerCommands(commands);
const conflict = conflictResolver.getConflicts().find(c => c.id === conflictId);
if (!conflict) {
throw new error_handler_1.ValidationError(`Conflict '${conflictId}' not found`);
}
if (conflict.resolved) {
console.log(chalk_1.default.yellow(`Conflict '${conflictId}' is already resolved`));
return;
}
const actionText = dryRun ? 'Simulating' : 'Resolving';
const spinner = (0, spinner_1.createSpinner)(`${actionText} conflict '${conflict.conflictValue}' using ${strategy} strategy...`);
spinner.start();
const resolution = await conflictResolver.resolveConflict(conflictId, strategy, { userConfirmed: confirm, dryRun });
spinner.stop();
if (resolution.success) {
const actionText = dryRun ? 'Would resolve' : 'Resolved';
console.log(chalk_1.default.green(`✓ ${actionText} conflict '${conflict.conflictValue}'`));
if (resolution.actions.length > 0) {
console.log(chalk_1.default.yellow('\nActions:'));
resolution.actions.forEach(action => {
const statusIcon = action.applied ? chalk_1.default.green('✓') : chalk_1.default.red('✗');
const actionText = action.type.charAt(0).toUpperCase() + action.type.slice(1);
console.log(` ${statusIcon} ${actionText}: ${action.target}`);
if (verbose && action.details) {
Object.entries(action.details).forEach(([key, value]) => {
console.log(` ${key}: ${value}`);
});
}
if (action.error) {
console.log(` ${chalk_1.default.red('Error: ' + action.error)}`);
}
});
}
if (verbose) {
console.log(chalk_1.default.yellow('\nResolution Details:'));
console.log(` Strategy: ${resolution.strategy}`);
console.log(` Applied by: ${resolution.appliedBy}`);
console.log(` Duration: ${Date.now() - resolution.appliedAt}ms`);
console.log(` Reversible: ${resolution.reversible ? 'Yes' : 'No'}`);
}
}
else {
console.log(chalk_1.default.red(`✗ Failed to resolve conflict '${conflict.conflictValue}'`));
if (resolution.errors.length > 0) {
console.log(chalk_1.default.red('\nErrors:'));
resolution.errors.forEach(error => {
console.log(` ${chalk_1.default.red('•')} ${error}`);
});
}
}
}
catch (error) {
throw new error_handler_1.ValidationError(`Failed to resolve conflict: ${error instanceof Error ? error.message : String(error)}`);
}
}
// Auto-resolve all conflicts
async function autoResolveConflicts(options = {}) {
const { verbose = false, dryRun = false } = options;
try {
const { Command } = require('commander');
const tempProgram = new Command();
const commandRegistry = (0, plugin_command_registry_1.createPluginCommandRegistry)(tempProgram);
await commandRegistry.initialize();
const conflictResolver = (0, plugin_command_conflicts_1.createConflictResolver)();
const commands = commandRegistry.getCommands();
conflictResolver.registerCommands(commands);
const unresolved = conflictResolver.getUnresolvedConflicts();
const autoResolvable = unresolved.filter(c => c.autoResolvable);
if (autoResolvable.length === 0) {
console.log(chalk_1.default.yellow('No auto-resolvable conflicts found.'));
return;
}
const actionText = dryRun ? 'Simulating' : 'Auto-resolving';
const spinner = (0, spinner_1.createSpinner)(`${actionText} ${autoResolvable.length} conflict(s)...`);
spinner.start();
// Mock auto-resolution since we don't have real conflicts
const mockResults = autoResolvable.map(conflict => ({
conflictId: conflict.id,
conflictValue: conflict.conflictValue,
strategy: 'priority',
success: true,
actions: 1
}));
spinner.stop();
console.log(chalk_1.default.green(`✓ ${dryRun ? 'Would auto-resolve' : 'Auto-resolved'} ${mockResults.length} conflict(s)`));
if (verbose || mockResults.length <= 5) {
console.log(chalk_1.default.yellow('\nResolved Conflicts:'));
mockResults.forEach(result => {
const statusIcon = result.success ? chalk_1.default.green('✓') : chalk_1.default.red('✗');
console.log(` ${statusIcon} ${result.conflictValue} (${result.strategy}, ${result.actions} actions)`);
});
}
if (mockResults.length > 5 && !verbose) {
console.log(chalk_1.default.gray(`\nUse --verbose to see all resolved conflicts`));
}
const remaining = unresolved.length - autoResolvable.length;
if (remaining > 0) {
console.log(chalk_1.default.yellow(`\n${remaining} conflict(s) require manual resolution`));
}
}
catch (error) {
throw new error_handler_1.ValidationError(`Failed to auto-resolve conflicts: ${error instanceof Error ? error.message : String(error)}`);
}
}
// Show conflict statistics
async function showConflictStats(options = {}) {
const { verbose = false, json = false } = options;
try {
const { Command } = require('commander');
const tempProgram = new Command();
const commandRegistry = (0, plugin_command_registry_1.createPluginCommandRegistry)(tempProgram);
await commandRegistry.initialize();
const conflictResolver = (0, plugin_command_conflicts_1.createConflictResolver)();
const commands = commandRegistry.getCommands();
conflictResolver.registerCommands(commands);
const stats = conflictResolver.getStats();
if (json) {
console.log(JSON.stringify(stats, null, 2));
return;
}
console.log(chalk_1.default.cyan('\n📊 Conflict Resolution Statistics\n'));
// Overview
console.log(chalk_1.default.yellow('Overview:'));
console.log(` Total conflicts: ${stats.total}`);
console.log(` Resolved: ${chalk_1.default.green(stats.resolved)}`);
console.log(` Unresolved: ${chalk_1.default.red(stats.unresolved)}`);
console.log(` Auto-resolvable: ${chalk_1.default.blue(stats.autoResolvable)}`);
// By type
console.log(chalk_1.default.yellow('\nConflicts by Type:'));
Object.entries(stats.byType).forEach(([type, count]) => {
if (count > 0) {
console.log(` ${(0, plugin_command_conflicts_1.formatConflictType)(type)}: ${count}`);
}
});
// By severity
console.log(chalk_1.default.yellow('\nConflicts by Severity:'));
Object.entries(stats.bySeverity).forEach(([severity, count]) => {
if (count > 0) {
const color = (0, plugin_command_conflicts_1.getConflictSeverityColor)(severity);
const colorFn = chalk_1.default[color];
console.log(` ${colorFn(severity)}: ${count}`);
}
});
// Resolution history
console.log(chalk_1.default.yellow('\nResolution History:'));
console.log(` Total resolutions: ${stats.resolutionHistory}`);
console.log(` Auto-resolutions: ${stats.autoResolutionCount}`);
console.log(` Priority overrides: ${stats.priorityOverrides}`);
if (verbose) {
console.log(chalk_1.default.yellow('\nConflict Types:'));
Object.values(plugin_command_conflicts_1.ConflictType).forEach(type => {
console.log(` • ${(0, plugin_command_conflicts_1.formatConflictType)(type)}`);
});
console.log(chalk_1.default.yellow('\nSeverity Levels:'));
Object.values(plugin_command_conflicts_1.ConflictSeverity).forEach(severity => {
const color = (0, plugin_command_conflicts_1.getConflictSeverityColor)(severity);
const colorFn = chalk_1.default[color];
console.log(` • ${colorFn(severity)}`);
});
console.log(chalk_1.default.yellow('\nResolution Strategies:'));
Object.values(plugin_command_conflicts_1.ConflictResolutionStrategy).forEach(strategy => {
console.log(` • ${strategy}`);
});
}
}
catch (error) {
throw new error_handler_1.ValidationError(`Failed to show conflict statistics: ${error instanceof Error ? error.message : String(error)}`);
}
}
// Set priority override
async function setPriorityOverride(commandId, priority, options = {}) {
const { verbose = false } = options;
try {
const priorityNum = parseInt(priority, 10);
if (isNaN(priorityNum)) {
throw new error_handler_1.ValidationError('Priority must be a valid number');
}
const { Command } = require('commander');
const tempProgram = new Command();
const commandRegistry = (0, plugin_command_registry_1.createPluginCommandRegistry)(tempProgram);
await commandRegistry.initialize();
const conflictResolver = (0, plugin_command_conflicts_1.createConflictResolver)();
const commands = commandRegistry.getCommands();
conflictResolver.registerCommands(commands);
const command = commands.find(c => c.id === commandId);
if (!command) {
throw new error_handler_1.ValidationError(`Command '${commandId}' not found`);
}
conflictResolver.setUserPriorityOverride(commandId, priorityNum);
console.log(chalk_1.default.green(`✓ Set priority override for '${command.definition.name}' to ${priorityNum}`));
if (verbose) {
console.log(chalk_1.default.yellow('\nCommand Details:'));
console.log(` ID: ${command.id}`);
console.log(` Name: ${command.definition.name}`);
console.log(` Plugin: ${command.pluginName}`);
console.log(` Original Priority: ${command.definition.priority || 0}`);
console.log(` New Priority: ${priorityNum}`);
}
// Check if this resolves any conflicts
const conflicts = conflictResolver.getConflicts().filter(c => c.conflictingCommands.includes(commandId) && !c.resolved);
if (conflicts.length > 0) {
console.log(chalk_1.default.blue(`\n💡 This may help resolve ${conflicts.length} conflict(s). Run conflict detection to check.`));
}
}
catch (error) {
throw new error_handler_1.ValidationError(`Failed to set priority override: ${error instanceof Error ? error.message : String(error)}`);
}
}
// Show resolution history
async function showResolutionHistory(options = {}) {
const { verbose = false, json = false } = options;
try {
const { Command } = require('commander');
const tempProgram = new Command();
const commandRegistry = (0, plugin_command_registry_1.createPluginCommandRegistry)(tempProgram);
await commandRegistry.initialize();
const conflictResolver = (0, plugin_command_conflicts_1.createConflictResolver)();
const commands = commandRegistry.getCommands();
conflictResolver.registerCommands(commands);
const history = conflictResolver.getResolutionHistory();
if (json) {
console.log(JSON.stringify(history, null, 2));
return;
}
console.log(chalk_1.default.cyan('\n📋 Conflict Resolution History\n'));
if (history.length === 0) {
console.log(chalk_1.default.yellow('No conflict resolutions in history.'));
return;
}
history.forEach((resolution, index) => {
const statusIcon = resolution.success ? chalk_1.default.green('✓') : chalk_1.default.red('✗');
const appliedBy = resolution.appliedBy === 'user' ? chalk_1.default.blue('👤 USER') : chalk_1.default.green('🤖 AUTO');
console.log(`${index + 1}. ${statusIcon} ${resolution.strategy} ${appliedBy}`);
console.log(` Applied: ${new Date(resolution.appliedAt).toLocaleString()}`);
console.log(` Actions: ${resolution.actions.length}`);
console.log(` Success: ${resolution.success ? 'Yes' : 'No'}`);
if (verbose) {
console.log(` Reversible: ${resolution.reversible ? 'Yes' : 'No'}`);
if (resolution.actions.length > 0) {
console.log(` Action Details:`);
resolution.actions.forEach(action => {
const actionIcon = action.applied ? chalk_1.default.green('✓') : chalk_1.default.red('✗');
console.log(` ${actionIcon} ${action.type}: ${action.target}`);
if (action.error) {
console.log(` Error: ${chalk_1.default.red(action.error)}`);
}
});
}
if (resolution.errors.length > 0) {
console.log(` Errors:`);
resolution.errors.forEach(error => {
console.log(` ${chalk_1.default.red('•')} ${error}`);
});
}
}
console.log('');
});
console.log(chalk_1.default.yellow('Summary:'));
console.log(` Total resolutions: ${history.length}`);
console.log(` Successful: ${chalk_1.default.green(history.filter(r => r.success).length)}`);
console.log(` Failed: ${chalk_1.default.red(history.filter(r => !r.success).length)}`);
console.log(` Auto-applied: ${chalk_1.default.blue(history.filter(r => r.appliedBy === 'auto').length)}`);
}
catch (error) {
throw new error_handler_1.ValidationError(`Failed to show resolution history: ${error instanceof Error ? error.message : String(error)}`);
}
}