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

402 lines (401 loc) • 18.8 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.resolveDependencies = resolveDependencies; exports.showDependencyTree = showDependencyTree; exports.checkConflicts = checkConflicts; exports.validateVersions = validateVersions; exports.updateDependencies = updateDependencies; const chalk_1 = __importDefault(require("chalk")); const spinner_1 = require("../utils/spinner"); const error_handler_1 = require("../utils/error-handler"); const plugin_dependency_1 = require("../utils/plugin-dependency"); const plugin_system_1 = require("../utils/plugin-system"); // Resolve dependencies for a plugin async function resolveDependencies(pluginName, options = {}) { const { verbose = false, json = false, strategy = 'strict', allowPrerelease = false, ignoreOptional = false, autoInstall = false, dryRun = false } = options; try { const registry = (0, plugin_system_1.createPluginRegistry)(); await registry.initialize(); const plugin = registry.getPlugin(pluginName); if (!plugin) { throw new error_handler_1.ValidationError(`Plugin '${pluginName}' not found`); } const resolver = (0, plugin_dependency_1.createDependencyResolver)({ strategy, allowPrerelease, ignoreOptional, autoInstall: autoInstall && !dryRun }); // Register all available plugins with resolver const allPlugins = registry.getPlugins(); allPlugins.forEach(p => resolver.registerPlugin(p)); const spinner = (0, spinner_1.createSpinner)(`Resolving dependencies for ${pluginName}...`); spinner.start(); const result = await resolver.resolveDependencies(plugin.manifest, { strategy, allowPrerelease, ignoreOptional, autoInstall: autoInstall && !dryRun }); spinner.stop(); if (json) { console.log(JSON.stringify(result, null, 2)); return; } console.log(chalk_1.default.cyan(`\nšŸ”— Dependency Resolution for ${pluginName}\n`)); displayResolutionResult(result, verbose); if (dryRun && autoInstall) { console.log(chalk_1.default.yellow('\nšŸ“‹ Installation Plan (Dry Run):\n')); displayInstallationPlan(result.installationPlan); } } catch (error) { throw new error_handler_1.ValidationError(`Dependency resolution failed: ${error instanceof Error ? error.message : String(error)}`); } } // Show dependency tree for a plugin async function showDependencyTree(pluginName, options = {}) { const { verbose = false, json = false } = options; try { const registry = (0, plugin_system_1.createPluginRegistry)(); await registry.initialize(); const resolver = (0, plugin_dependency_1.createDependencyResolver)(); // Register all available plugins const allPlugins = registry.getPlugins(); allPlugins.forEach(p => resolver.registerPlugin(p)); const dependencyGraph = resolver.getDependencyGraph(); if (json) { const graphData = Array.from(dependencyGraph.entries()).map(([name, node]) => ({ name, version: node.version, dependencies: Array.from(node.dependencies), dependents: Array.from(node.dependents), resolved: node.resolved, depth: node.depth })); console.log(JSON.stringify(graphData, null, 2)); return; } console.log(chalk_1.default.cyan('\n🌳 Plugin Dependency Tree\n')); if (pluginName) { const node = dependencyGraph.get(pluginName); if (!node) { throw new error_handler_1.ValidationError(`Plugin '${pluginName}' not found in dependency graph`); } displayDependencyNode(node, dependencyGraph, 0, new Set(), verbose); } else { // Show all top-level plugins (no dependents) const topLevel = Array.from(dependencyGraph.values()) .filter(node => node.dependents.size === 0) .sort((a, b) => a.name.localeCompare(b.name)); if (topLevel.length === 0) { console.log(chalk_1.default.yellow('No plugins found in dependency graph.')); return; } topLevel.forEach(node => { displayDependencyNode(node, dependencyGraph, 0, new Set(), verbose); console.log(''); }); } } catch (error) { throw new error_handler_1.ValidationError(`Failed to show dependency tree: ${error instanceof Error ? error.message : String(error)}`); } } // Check for dependency conflicts async function checkConflicts(options = {}) { const { verbose = false, json = false, strategy = 'strict' } = options; try { const registry = (0, plugin_system_1.createPluginRegistry)(); await registry.initialize(); const resolver = (0, plugin_dependency_1.createDependencyResolver)({ strategy }); // Register all plugins const allPlugins = registry.getPlugins(); allPlugins.forEach(p => resolver.registerPlugin(p)); const spinner = (0, spinner_1.createSpinner)('Checking for dependency conflicts...'); spinner.start(); const conflicts = []; const resolutions = []; // Check each plugin for conflicts for (const plugin of allPlugins) { try { const result = await resolver.resolveDependencies(plugin.manifest); resolutions.push(result); conflicts.push(...result.conflicts); } catch (error) { // Plugin has unresolvable conflicts conflicts.push({ type: 'incompatible', source: plugin.manifest.name, target: 'unknown', requested: 'unknown', resolution: { action: 'remove', target: plugin.manifest.name, reason: error instanceof Error ? error.message : String(error) } }); } } spinner.stop(); if (json) { console.log(JSON.stringify({ conflicts, totalPlugins: allPlugins.length, pluginsWithConflicts: resolutions.filter(r => r.conflicts.length > 0).length }, null, 2)); return; } console.log(chalk_1.default.cyan('\nāš ļø Dependency Conflict Analysis\n')); if (conflicts.length === 0) { console.log(chalk_1.default.green('āœ… No dependency conflicts found!')); console.log(chalk_1.default.gray(`Analyzed ${allPlugins.length} plugins successfully.`)); return; } console.log(chalk_1.default.red(`Found ${conflicts.length} dependency conflicts:\n`)); displayConflicts(conflicts, verbose); // Show resolution suggestions const resolvableConflicts = conflicts.filter(c => c.resolution); if (resolvableConflicts.length > 0) { console.log(chalk_1.default.yellow('\nšŸ’” Suggested Resolutions:\n')); resolvableConflicts.forEach((conflict, index) => { if (conflict.resolution) { console.log(`${index + 1}. ${chalk_1.default.cyan(conflict.resolution.action)} ${conflict.resolution.target}`); if (conflict.resolution.version) { console.log(` Version: ${conflict.resolution.version}`); } console.log(` Reason: ${chalk_1.default.gray(conflict.resolution.reason)}`); console.log(''); } }); } } catch (error) { throw new error_handler_1.ValidationError(`Conflict check failed: ${error instanceof Error ? error.message : String(error)}`); } } // Validate dependency versions async function validateVersions(options = {}) { const { verbose = false, json = false } = options; try { const registry = (0, plugin_system_1.createPluginRegistry)(); await registry.initialize(); const plugins = registry.getPlugins(); const validationResults = []; const spinner = (0, spinner_1.createSpinner)('Validating plugin versions...'); spinner.start(); for (const plugin of plugins) { const result = { plugin: plugin.manifest.name, version: plugin.manifest.version, valid: true, issues: [] }; // Validate version format const semver = require('semver'); if (!semver.valid(plugin.manifest.version)) { result.valid = false; result.issues.push('Invalid version format'); } // Check for prerelease versions if (semver.prerelease(plugin.manifest.version)) { result.issues.push('Prerelease version'); } // Validate dependency versions if (plugin.manifest.dependencies) { Object.entries(plugin.manifest.dependencies).forEach(([name, version]) => { if (!semver.validRange(version)) { result.valid = false; result.issues.push(`Invalid dependency version range: ${name}@${version}`); } }); } // Check for outdated dependencies if (plugin.manifest.reshell?.plugins) { Object.entries(plugin.manifest.reshell.plugins).forEach(([name, version]) => { const depPlugin = registry.getPlugin(name); if (depPlugin) { const currentVersion = depPlugin.manifest.version; if (semver.gt(currentVersion, version)) { result.issues.push(`Outdated plugin dependency: ${name}@${version} (latest: ${currentVersion})`); } } }); } validationResults.push(result); } spinner.stop(); if (json) { console.log(JSON.stringify(validationResults, null, 2)); return; } console.log(chalk_1.default.cyan('\nšŸ” Plugin Version Validation\n')); const validPlugins = validationResults.filter(r => r.valid); const invalidPlugins = validationResults.filter(r => !r.valid); const pluginsWithIssues = validationResults.filter(r => r.issues.length > 0); console.log(chalk_1.default.green(`āœ… Valid plugins: ${validPlugins.length}/${validationResults.length}`)); if (invalidPlugins.length > 0) { console.log(chalk_1.default.red(`āŒ Invalid plugins: ${invalidPlugins.length}`)); } if (pluginsWithIssues.length > 0) { console.log(chalk_1.default.yellow(`āš ļø Plugins with issues: ${pluginsWithIssues.length}`)); } if (verbose || invalidPlugins.length > 0) { console.log(''); validationResults.forEach(result => { if (!result.valid || (verbose && result.issues.length > 0)) { const status = result.valid ? chalk_1.default.yellow('āš ļø ') : chalk_1.default.red('āŒ'); console.log(`${status} ${chalk_1.default.white(result.plugin)} ${chalk_1.default.gray(`v${result.version}`)}`); result.issues.forEach((issue) => { const color = result.valid ? chalk_1.default.yellow : chalk_1.default.red; console.log(` ${color(issue)}`); }); console.log(''); } }); } } catch (error) { throw new error_handler_1.ValidationError(`Version validation failed: ${error instanceof Error ? error.message : String(error)}`); } } // Update plugin dependencies async function updateDependencies(pluginName, options = {}) { const { verbose = false, dryRun = false } = options; try { const registry = (0, plugin_system_1.createPluginRegistry)(); await registry.initialize(); const plugin = registry.getPlugin(pluginName); if (!plugin) { throw new error_handler_1.ValidationError(`Plugin '${pluginName}' not found`); } const spinner = (0, spinner_1.createSpinner)(`Updating dependencies for ${pluginName}...`); spinner.start(); // TODO: Implement actual dependency update logic // This would involve: // 1. Checking for newer versions of dependencies // 2. Updating package.json/manifest // 3. Installing new versions // 4. Running tests to ensure compatibility await new Promise(resolve => setTimeout(resolve, 2000)); // Simulate update spinner.succeed(chalk_1.default.green(`Dependencies updated for ${pluginName}!`)); if (verbose) { console.log(chalk_1.default.gray('Updated dependencies would be listed here...')); } } catch (error) { throw new error_handler_1.ValidationError(`Dependency update failed: ${error instanceof Error ? error.message : String(error)}`); } } // Display resolution result function displayResolutionResult(result, verbose) { console.log(chalk_1.default.yellow('Resolution Status:')); console.log(` Success: ${result.success ? chalk_1.default.green('āœ“') : chalk_1.default.red('āœ—')}`); console.log(` Resolved: ${result.resolved.length} dependencies`); console.log(` Conflicts: ${result.conflicts.length}`); console.log(` Missing: ${result.missing.length}`); if (result.circular.length > 0) { console.log(` Circular: ${result.circular.length} cycles`); } if (result.resolved.length > 0) { console.log(chalk_1.default.yellow('\nResolved Dependencies:')); result.resolved.forEach(dep => { const status = dep.resolved ? chalk_1.default.green('āœ“') : chalk_1.default.red('āœ—'); console.log(` ${status} ${chalk_1.default.white(dep.name)} ${chalk_1.default.gray(`${dep.version} → ${dep.resolvedVersion || 'unknown'}`)}`); if (verbose && dep.conflicts && dep.conflicts.length > 0) { dep.conflicts.forEach(conflict => { console.log(` ${chalk_1.default.yellow('āš ļø')} ${conflict.type}: ${conflict.requested} vs ${conflict.available}`); }); } }); } if (result.missing.length > 0) { console.log(chalk_1.default.red('\nMissing Dependencies:')); result.missing.forEach(missing => { console.log(` ${chalk_1.default.red('āœ—')} ${missing}`); }); } if (result.conflicts.length > 0) { console.log(chalk_1.default.red('\nConflicts:')); displayConflicts(result.conflicts, verbose); } if (result.warnings.length > 0) { console.log(chalk_1.default.yellow('\nWarnings:')); result.warnings.forEach(warning => { console.log(` ${chalk_1.default.yellow('āš ļø')} ${warning}`); }); } } // Display dependency conflicts function displayConflicts(conflicts, verbose) { conflicts.forEach((conflict, index) => { console.log(`${index + 1}. ${chalk_1.default.red(conflict.type)} conflict:`); console.log(` Source: ${chalk_1.default.white(conflict.source)}`); console.log(` Target: ${chalk_1.default.white(conflict.target)}`); console.log(` Requested: ${chalk_1.default.cyan(conflict.requested)}`); if (conflict.available) { console.log(` Available: ${chalk_1.default.cyan(conflict.available)}`); } if (verbose && conflict.resolution) { console.log(` Resolution: ${chalk_1.default.yellow(conflict.resolution.action)} ${conflict.resolution.target}`); if (conflict.resolution.version) { console.log(` Version: ${conflict.resolution.version}`); } console.log(` Reason: ${chalk_1.default.gray(conflict.resolution.reason)}`); } console.log(''); }); } // Display installation plan function displayInstallationPlan(plan) { if (plan.length === 0) { console.log(chalk_1.default.gray('No installation steps required.')); return; } plan.forEach((step, index) => { const actionColor = step.action === 'install' ? chalk_1.default.green : step.action === 'upgrade' ? chalk_1.default.blue : step.action === 'downgrade' ? chalk_1.default.yellow : chalk_1.default.red; console.log(`${step.order + 1}. ${actionColor(step.action)} ${chalk_1.default.white(step.plugin)} ${chalk_1.default.gray(`v${step.version}`)}`); if (step.optional) { console.log(` ${chalk_1.default.gray('(optional)')}`); } if (step.dependencies.length > 0) { console.log(` Dependencies: ${step.dependencies.join(', ')}`); } }); } // Display dependency node in tree format function displayDependencyNode(node, graph, depth, visited, verbose) { const indent = ' '.repeat(depth); const prefix = depth === 0 ? '' : 'ā”œā”€ '; const status = node.resolved ? chalk_1.default.green('ā—') : chalk_1.default.red('ā—'); console.log(`${indent}${prefix}${status} ${chalk_1.default.white(node.name)} ${chalk_1.default.gray(`v${node.version}`)}`); if (verbose) { console.log(`${indent} Dependencies: ${node.dependencies.size}`); console.log(`${indent} Dependents: ${node.dependents.size}`); } if (visited.has(node.name)) { console.log(`${indent} ${chalk_1.default.yellow('(circular reference)')}`); return; } visited.add(node.name); // Show dependencies const deps = Array.from(node.dependencies).sort(); deps.forEach((depName) => { const depNode = graph.get(depName); if (depNode) { displayDependencyNode(depNode, graph, depth + 1, new Set(visited), verbose); } else { const depIndent = ' '.repeat(depth + 1); console.log(`${depIndent}ā”œā”€ ${chalk_1.default.red('ā—')} ${chalk_1.default.white(depName)} ${chalk_1.default.red('(missing)')}`); } }); visited.delete(node.name); }