@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
647 lines (646 loc) ⢠26.8 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.manageWorkspaceConflict = manageWorkspaceConflict;
const chalk_1 = __importDefault(require("chalk"));
const prompts_1 = __importDefault(require("prompts"));
const fs = __importStar(require("fs-extra"));
const workspace_conflict_1 = require("../utils/workspace-conflict");
const error_handler_1 = require("../utils/error-handler");
const DEFAULT_WORKSPACE_FILE = 're-shell.workspaces.yaml';
async function manageWorkspaceConflict(options = {}) {
const { spinner, verbose, json } = options;
try {
if (options.detect) {
await detectConflicts(options, spinner);
return;
}
if (options.resolve) {
await resolveConflicts(options, spinner);
return;
}
if (options.preview) {
await previewResolution(options, spinner);
return;
}
if (options.autoResolve) {
await autoResolveAllConflicts(options, spinner);
return;
}
if (options.interactive) {
await interactiveConflictManagement(options, spinner);
return;
}
// Default: detect conflicts
await detectConflicts(options, spinner);
}
catch (error) {
if (spinner)
spinner.fail(chalk_1.default.red('Conflict management failed'));
throw error;
}
}
async function detectConflicts(options, spinner) {
const workspaceFile = options.workspaceFile || DEFAULT_WORKSPACE_FILE;
if (!(await fs.pathExists(workspaceFile))) {
throw new error_handler_1.ValidationError(`Workspace file not found: ${workspaceFile}`);
}
if (spinner)
spinner.setText('Detecting workspace conflicts...');
try {
const detectionOptions = {
includeWarnings: options.includeWarnings ?? true,
checkDependencies: options.checkDependencies ?? true,
checkPorts: options.checkPorts ?? true,
checkPaths: options.checkPaths ?? true,
checkTypes: options.checkTypes ?? true,
enableResolution: true
};
const conflicts = await (0, workspace_conflict_1.detectWorkspaceConflicts)(workspaceFile, detectionOptions);
if (spinner)
spinner.stop();
if (options.json) {
console.log(JSON.stringify(conflicts, null, 2));
return;
}
if (conflicts.length === 0) {
console.log(chalk_1.default.green('\\nā
No conflicts detected!'));
console.log(chalk_1.default.gray('Your workspace definition is conflict-free.'));
return;
}
console.log(chalk_1.default.cyan('\\nš Workspace Conflict Analysis'));
console.log(chalk_1.default.gray('ā'.repeat(50)));
const errorCount = conflicts.filter(c => c.severity === 'error').length;
const warningCount = conflicts.filter(c => c.severity === 'warning').length;
const infoCount = conflicts.filter(c => c.severity === 'info').length;
console.log(`Found ${chalk_1.default.red(errorCount)} errors, ${chalk_1.default.yellow(warningCount)} warnings, ${chalk_1.default.blue(infoCount)} info`);
if (options.groupBy === 'type') {
displayConflictsByType(conflicts, options);
}
else if (options.groupBy === 'severity') {
displayConflictsBySeverity(conflicts, options);
}
else if (options.groupBy === 'workspace') {
displayConflictsByWorkspace(conflicts, options);
}
else {
displayConflictsList(conflicts, options);
}
if (errorCount > 0) {
console.log(chalk_1.default.cyan('\\nš ļø Resolution Commands:'));
console.log(' ⢠Auto-resolve: re-shell workspace-conflict auto-resolve');
console.log(' ⢠Interactive: re-shell workspace-conflict interactive');
console.log(' ⢠Manual resolve: re-shell workspace-conflict resolve --conflict-id <id>');
}
}
catch (error) {
if (spinner)
spinner.fail(chalk_1.default.red('Failed to detect conflicts'));
throw error;
}
}
async function resolveConflicts(options, spinner) {
const workspaceFile = options.workspaceFile || DEFAULT_WORKSPACE_FILE;
if (!options.conflictId) {
throw new error_handler_1.ValidationError('Conflict ID is required for manual resolution');
}
if (spinner)
spinner.setText('Resolving workspace conflicts...');
try {
const manager = await (0, workspace_conflict_1.createWorkspaceConflictManager)();
const definition = await manager['loadWorkspaceDefinition'](workspaceFile);
const conflicts = await manager.detectConflicts(definition);
const conflict = conflicts.find(c => c.id === options.conflictId);
if (!conflict) {
throw new error_handler_1.ValidationError(`Conflict not found: ${options.conflictId}`);
}
let resolutionId = options.resolutionId;
// If no resolution specified, prompt user
if (!resolutionId && !options.force) {
if (spinner)
spinner.stop();
const response = await (0, prompts_1.default)([
{
type: 'select',
name: 'resolution',
message: `Choose resolution for: ${conflict.description}`,
choices: conflict.suggestions.map(r => ({
title: `${r.description} (${r.riskLevel} risk)`,
value: r.id,
description: r.preview
}))
}
]);
if (!response.resolution)
return;
resolutionId = response.resolution;
}
else if (!resolutionId) {
// Auto-select first automatic resolution
const autoResolution = conflict.suggestions.find(r => r.automatic);
if (autoResolution) {
resolutionId = autoResolution.id;
}
else {
throw new error_handler_1.ValidationError('No automatic resolution available. Please specify --resolution-id');
}
}
if (spinner)
spinner.setText('Applying resolution...');
const result = await manager.resolveConflicts(definition, [conflict], true);
await manager['saveWorkspaceDefinition'](workspaceFile, definition);
if (spinner)
spinner.stop();
if (options.json) {
console.log(JSON.stringify(result, null, 2));
return;
}
if (result.resolved.length > 0) {
console.log(chalk_1.default.green('\\nā
Conflict resolved successfully!'));
console.log(chalk_1.default.cyan('\\nš Changes made:'));
for (const change of result.changes) {
console.log(` ⢠${change.target}.${change.property}: ${chalk_1.default.red(String(change.oldValue))} ā ${chalk_1.default.green(String(change.newValue))}`);
console.log(` ${chalk_1.default.gray(change.reason)}`);
}
}
else {
console.log(chalk_1.default.red('\\nā Failed to resolve conflict'));
if (result.warnings.length > 0) {
console.log(chalk_1.default.yellow('\\nWarnings:'));
for (const warning of result.warnings) {
console.log(` ā ļø ${warning}`);
}
}
}
}
catch (error) {
if (spinner)
spinner.fail(chalk_1.default.red('Failed to resolve conflict'));
throw error;
}
}
async function previewResolution(options, spinner) {
const workspaceFile = options.workspaceFile || DEFAULT_WORKSPACE_FILE;
if (!options.conflictId || !options.resolutionId) {
throw new error_handler_1.ValidationError('Both conflict ID and resolution ID are required for preview');
}
if (spinner)
spinner.setText('Previewing resolution...');
try {
const manager = await (0, workspace_conflict_1.createWorkspaceConflictManager)();
const definition = await manager['loadWorkspaceDefinition'](workspaceFile);
const conflicts = await manager.detectConflicts(definition);
const conflict = conflicts.find(c => c.id === options.conflictId);
if (!conflict) {
throw new error_handler_1.ValidationError(`Conflict not found: ${options.conflictId}`);
}
const preview = await manager.previewResolution(definition, conflict, options.resolutionId);
if (spinner)
spinner.stop();
if (options.json) {
console.log(JSON.stringify(preview, null, 2));
return;
}
console.log(chalk_1.default.cyan('\\nš Resolution Preview'));
console.log(chalk_1.default.gray('ā'.repeat(50)));
console.log(`Conflict: ${chalk_1.default.yellow(conflict.description)}`);
console.log(`Resolution: ${chalk_1.default.blue(conflict.suggestions.find(r => r.id === options.resolutionId)?.description)}`);
if (preview.success) {
console.log(chalk_1.default.green('\\nā
Preview successful'));
console.log(chalk_1.default.cyan('\\nš Proposed changes:'));
for (const change of preview.changes) {
console.log(` ⢠${change.target}.${change.property}: ${chalk_1.default.red(String(change.oldValue))} ā ${chalk_1.default.green(String(change.newValue))}`);
console.log(` ${chalk_1.default.gray(change.reason)}`);
}
}
else {
console.log(chalk_1.default.red('\\nā Preview failed'));
if (preview.warnings.length > 0) {
console.log(chalk_1.default.yellow('\\nWarnings:'));
for (const warning of preview.warnings) {
console.log(` ā ļø ${warning}`);
}
}
}
console.log(chalk_1.default.cyan('\\nš Apply resolution:'));
console.log(` re-shell workspace-conflict resolve --conflict-id ${options.conflictId} --resolution-id ${options.resolutionId}`);
}
catch (error) {
if (spinner)
spinner.fail(chalk_1.default.red('Failed to preview resolution'));
throw error;
}
}
async function autoResolveAllConflicts(options, spinner) {
const workspaceFile = options.workspaceFile || DEFAULT_WORKSPACE_FILE;
if (spinner)
spinner.setText('Auto-resolving all conflicts...');
try {
const result = await (0, workspace_conflict_1.autoResolveConflicts)(workspaceFile);
if (spinner)
spinner.stop();
if (options.json) {
console.log(JSON.stringify(result, null, 2));
return;
}
console.log(chalk_1.default.cyan('\\nš¤ Auto-Resolution Results'));
console.log(chalk_1.default.gray('ā'.repeat(50)));
console.log(`Resolved: ${chalk_1.default.green(result.resolved.length)} conflicts`);
console.log(`Unresolved: ${chalk_1.default.red(result.unresolved.length)} conflicts`);
if (result.resolved.length > 0) {
console.log(chalk_1.default.cyan('\\nā
Resolved conflicts:'));
for (const conflict of result.resolved) {
console.log(` ⢠${conflict.description}`);
}
console.log(chalk_1.default.cyan('\\nš Changes made:'));
for (const change of result.changes) {
console.log(` ⢠${change.target}.${change.property}: ${chalk_1.default.red(String(change.oldValue))} ā ${chalk_1.default.green(String(change.newValue))}`);
}
}
if (result.unresolved.length > 0) {
console.log(chalk_1.default.yellow('\\nā ļø Unresolved conflicts (require manual intervention):'));
for (const conflict of result.unresolved) {
console.log(` ⢠${conflict.description}`);
}
console.log(chalk_1.default.cyan('\\nš ļø Manual resolution:'));
console.log(' re-shell workspace-conflict interactive');
}
if (result.warnings.length > 0) {
console.log(chalk_1.default.yellow('\\nā ļø Warnings:'));
for (const warning of result.warnings) {
console.log(` ${warning}`);
}
}
}
catch (error) {
if (spinner)
spinner.fail(chalk_1.default.red('Auto-resolution failed'));
throw error;
}
}
async function interactiveConflictManagement(options, spinner) {
if (spinner)
spinner.stop();
const response = await (0, prompts_1.default)([
{
type: 'select',
name: 'action',
message: 'What would you like to do?',
choices: [
{ title: 'š Detect conflicts', value: 'detect' },
{ title: 'š¤ Auto-resolve all conflicts', value: 'auto-resolve' },
{ title: 'š ļø Manual conflict resolution', value: 'manual' },
{ title: 'š Preview resolution', value: 'preview' },
{ title: 'š Conflict analysis', value: 'analysis' }
]
}
]);
if (!response.action)
return;
switch (response.action) {
case 'detect':
await detectConflictsInteractive(options);
break;
case 'auto-resolve':
await autoResolveAllConflicts({ ...options, interactive: false });
break;
case 'manual':
await manualResolutionInteractive(options);
break;
case 'preview':
await previewResolutionInteractive(options);
break;
case 'analysis':
await conflictAnalysisInteractive(options);
break;
}
}
async function detectConflictsInteractive(options) {
const response = await (0, prompts_1.default)([
{
type: 'text',
name: 'workspaceFile',
message: 'Workspace file:',
initial: 're-shell.workspaces.yaml'
},
{
type: 'multiselect',
name: 'checks',
message: 'Select checks to perform:',
choices: [
{ title: 'Dependencies', value: 'dependencies', selected: true },
{ title: 'Ports', value: 'ports', selected: true },
{ title: 'Paths', value: 'paths', selected: true },
{ title: 'Types', value: 'types', selected: true }
]
},
{
type: 'confirm',
name: 'includeWarnings',
message: 'Include warnings?',
initial: true
},
{
type: 'select',
name: 'groupBy',
message: 'Group results by:',
choices: [
{ title: 'Conflict type', value: 'type' },
{ title: 'Severity', value: 'severity' },
{ title: 'Workspace', value: 'workspace' },
{ title: 'None (list)', value: 'none' }
]
}
]);
if (!response.workspaceFile)
return;
await detectConflicts({
...options,
...response,
checkDependencies: response.checks.includes('dependencies'),
checkPorts: response.checks.includes('ports'),
checkPaths: response.checks.includes('paths'),
checkTypes: response.checks.includes('types'),
groupBy: response.groupBy === 'none' ? undefined : response.groupBy,
interactive: false
});
}
async function manualResolutionInteractive(options) {
const workspaceFile = options.workspaceFile || DEFAULT_WORKSPACE_FILE;
// First detect conflicts
const conflicts = await (0, workspace_conflict_1.detectWorkspaceConflicts)(workspaceFile);
if (conflicts.length === 0) {
console.log(chalk_1.default.green('\\nā
No conflicts to resolve!'));
return;
}
const response = await (0, prompts_1.default)([
{
type: 'select',
name: 'conflictId',
message: 'Select conflict to resolve:',
choices: conflicts.map(c => ({
title: `${getSeverityIcon(c.severity)} ${c.description}`,
value: c.id,
description: c.details
}))
}
]);
if (!response.conflictId)
return;
const conflict = conflicts.find(c => c.id === response.conflictId);
if (!conflict)
return;
const resolutionResponse = await (0, prompts_1.default)([
{
type: 'select',
name: 'resolutionId',
message: 'Choose resolution:',
choices: conflict.suggestions.map(r => ({
title: `${r.description} (${r.riskLevel} risk)`,
value: r.id,
description: r.preview
}))
},
{
type: 'confirm',
name: 'preview',
message: 'Preview changes before applying?',
initial: true
}
]);
if (!resolutionResponse.resolutionId)
return;
if (resolutionResponse.preview) {
await previewResolution({
...options,
conflictId: response.conflictId,
resolutionId: resolutionResponse.resolutionId,
interactive: false
});
const confirmResponse = await (0, prompts_1.default)([
{
type: 'confirm',
name: 'apply',
message: 'Apply this resolution?',
initial: false
}
]);
if (!confirmResponse.apply)
return;
}
await resolveConflicts({
...options,
conflictId: response.conflictId,
resolutionId: resolutionResponse.resolutionId,
interactive: false
});
}
async function previewResolutionInteractive(options) {
const workspaceFile = options.workspaceFile || DEFAULT_WORKSPACE_FILE;
const conflicts = await (0, workspace_conflict_1.detectWorkspaceConflicts)(workspaceFile);
if (conflicts.length === 0) {
console.log(chalk_1.default.green('\\nā
No conflicts to preview!'));
return;
}
const response = await (0, prompts_1.default)([
{
type: 'select',
name: 'conflictId',
message: 'Select conflict:',
choices: conflicts.map(c => ({
title: `${getSeverityIcon(c.severity)} ${c.description}`,
value: c.id
}))
}
]);
if (!response.conflictId)
return;
const conflict = conflicts.find(c => c.id === response.conflictId);
if (!conflict)
return;
const resolutionResponse = await (0, prompts_1.default)([
{
type: 'select',
name: 'resolutionId',
message: 'Select resolution to preview:',
choices: conflict.suggestions.map(r => ({
title: r.description,
value: r.id
}))
}
]);
if (!resolutionResponse.resolutionId)
return;
await previewResolution({
...options,
conflictId: response.conflictId,
resolutionId: resolutionResponse.resolutionId,
interactive: false
});
}
async function conflictAnalysisInteractive(options) {
const workspaceFile = options.workspaceFile || DEFAULT_WORKSPACE_FILE;
const conflicts = await (0, workspace_conflict_1.detectWorkspaceConflicts)(workspaceFile);
console.log(chalk_1.default.cyan('\\nš Conflict Analysis Dashboard'));
console.log(chalk_1.default.gray('ā'.repeat(50)));
if (conflicts.length === 0) {
console.log(chalk_1.default.green('ā
No conflicts detected - workspace is healthy!'));
return;
}
// Analysis by severity
const severityStats = {
error: conflicts.filter(c => c.severity === 'error').length,
warning: conflicts.filter(c => c.severity === 'warning').length,
info: conflicts.filter(c => c.severity === 'info').length
};
console.log(chalk_1.default.cyan('\\nBy Severity:'));
console.log(` ${chalk_1.default.red('ā')} Errors: ${severityStats.error}`);
console.log(` ${chalk_1.default.yellow('ā')} Warnings: ${severityStats.warning}`);
console.log(` ${chalk_1.default.blue('ā')} Info: ${severityStats.info}`);
// Analysis by type
const typeStats = {};
for (const conflict of conflicts) {
typeStats[conflict.type] = (typeStats[conflict.type] || 0) + 1;
}
console.log(chalk_1.default.cyan('\\nBy Type:'));
for (const [type, count] of Object.entries(typeStats)) {
console.log(` ⢠${type}: ${count}`);
}
// Most affected workspaces
const workspaceStats = {};
for (const conflict of conflicts) {
for (const workspace of conflict.affectedWorkspaces) {
workspaceStats[workspace] = (workspaceStats[workspace] || 0) + 1;
}
}
const topAffected = Object.entries(workspaceStats)
.sort(([, a], [, b]) => b - a)
.slice(0, 5);
if (topAffected.length > 0) {
console.log(chalk_1.default.cyan('\\nMost Affected Workspaces:'));
for (const [workspace, count] of topAffected) {
console.log(` ⢠${workspace}: ${count} conflicts`);
}
}
// Automatic resolution potential
const autoResolvable = conflicts.filter(c => c.suggestions.some(s => s.automatic && s.riskLevel === 'low')).length;
console.log(chalk_1.default.cyan('\\nResolution Summary:'));
console.log(` ⢠Auto-resolvable (low risk): ${chalk_1.default.green(autoResolvable)}`);
console.log(` ⢠Requires manual intervention: ${chalk_1.default.yellow(conflicts.length - autoResolvable)}`);
if (autoResolvable > 0) {
console.log(chalk_1.default.cyan('\\nš¤ Quick fix:'));
console.log(' re-shell workspace-conflict auto-resolve');
}
}
// Display helper functions
function displayConflictsList(conflicts, options) {
console.log(chalk_1.default.cyan('\\nš Conflicts:'));
for (let i = 0; i < conflicts.length; i++) {
const conflict = conflicts[i];
const icon = getSeverityIcon(conflict.severity);
console.log(`\\n${i + 1}. ${icon} ${chalk_1.default.bold(conflict.description)}`);
console.log(` ID: ${chalk_1.default.gray(conflict.id)}`);
console.log(` Type: ${chalk_1.default.blue(conflict.type)}`);
console.log(` Affected: ${conflict.affectedWorkspaces.join(', ')}`);
if (options.verbose) {
console.log(` Details: ${chalk_1.default.gray(conflict.details)}`);
console.log(` Resolutions: ${conflict.suggestions.length} available`);
}
}
}
function displayConflictsByType(conflicts, options) {
const byType = {};
for (const conflict of conflicts) {
if (!byType[conflict.type]) {
byType[conflict.type] = [];
}
byType[conflict.type].push(conflict);
}
for (const [type, typeConflicts] of Object.entries(byType)) {
console.log(chalk_1.default.cyan(`\\nš ${type.toUpperCase()} (${typeConflicts.length})`));
for (const conflict of typeConflicts) {
const icon = getSeverityIcon(conflict.severity);
console.log(` ${icon} ${conflict.description}`);
if (options.verbose) {
console.log(` ${chalk_1.default.gray(conflict.details)}`);
}
}
}
}
function displayConflictsBySeverity(conflicts, options) {
const severityOrder = ['error', 'warning', 'info'];
for (const severity of severityOrder) {
const severityConflicts = conflicts.filter(c => c.severity === severity);
if (severityConflicts.length === 0)
continue;
const icon = getSeverityIcon(severity);
console.log(chalk_1.default.cyan(`\\n${icon} ${severity.toUpperCase()} (${severityConflicts.length})`));
for (const conflict of severityConflicts) {
console.log(` ⢠${conflict.description}`);
if (options.verbose) {
console.log(` ${chalk_1.default.gray(conflict.details)}`);
}
}
}
}
function displayConflictsByWorkspace(conflicts, options) {
const byWorkspace = {};
for (const conflict of conflicts) {
for (const workspace of conflict.affectedWorkspaces) {
if (!byWorkspace[workspace]) {
byWorkspace[workspace] = [];
}
byWorkspace[workspace].push(conflict);
}
}
for (const [workspace, workspaceConflicts] of Object.entries(byWorkspace)) {
console.log(chalk_1.default.cyan(`\\nšļø ${workspace} (${workspaceConflicts.length})`));
for (const conflict of workspaceConflicts) {
const icon = getSeverityIcon(conflict.severity);
console.log(` ${icon} ${conflict.description}`);
}
}
}
function getSeverityIcon(severity) {
switch (severity) {
case 'error': return 'ā';
case 'warning': return 'ā ļø';
case 'info': return 'ā¹ļø';
default: return 'ā¢';
}
}