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

835 lines (834 loc) 31.5 kB
"use strict"; 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; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.PackageManagerDetector = exports.PackageManager = void 0; exports.getPackageManagerDetector = getPackageManagerDetector; exports.detectPackageManager = detectPackageManager; exports.getRecommendedPackageManager = getRecommendedPackageManager; const events_1 = require("events"); const fs = __importStar(require("fs-extra")); const path = __importStar(require("path")); const child_process_1 = require("child_process"); const os = __importStar(require("os")); var PackageManager; (function (PackageManager) { PackageManager["NPM"] = "npm"; PackageManager["YARN"] = "yarn"; PackageManager["PNPM"] = "pnpm"; PackageManager["BUN"] = "bun"; PackageManager["DENO"] = "deno"; PackageManager["CARGO"] = "cargo"; PackageManager["PIP"] = "pip"; PackageManager["POETRY"] = "poetry"; PackageManager["BUNDLER"] = "bundler"; PackageManager["COMPOSER"] = "composer"; PackageManager["MAVEN"] = "maven"; PackageManager["GRADLE"] = "gradle"; PackageManager["GO"] = "go"; PackageManager["DOTNET"] = "dotnet"; PackageManager["UNKNOWN"] = "unknown"; })(PackageManager || (exports.PackageManager = PackageManager = {})); class PackageManagerDetector extends events_1.EventEmitter { constructor() { super(); this.initialize(); } async initialize() { if (PackageManagerDetector.initialized) return; await this.loadManagerDefinitions(); await this.detectInstalledManagers(); PackageManagerDetector.initialized = true; } async loadManagerDefinitions() { // Node.js Package Managers PackageManagerDetector.managerInfo.set(PackageManager.NPM, { name: PackageManager.NPM, version: '', path: '', isInstalled: false, performance: { installSpeed: 'medium', cacheEfficiency: 'medium', parallelism: true, diskUsage: 'medium', memoryUsage: 'medium', startupTime: 500 }, features: { workspaces: true, lockfiles: true, peerDependencies: true, patchSupport: false, offlineMode: true, securityAudit: true, autoInstall: false, deterministicInstalls: true, pluginSystem: false }, commands: { install: 'npm install', add: 'npm install', remove: 'npm uninstall', update: 'npm update', run: 'npm run', test: 'npm test', build: 'npm run build', publish: 'npm publish', audit: 'npm audit', cache: 'npm cache' } }); PackageManagerDetector.managerInfo.set(PackageManager.YARN, { name: PackageManager.YARN, version: '', path: '', isInstalled: false, performance: { installSpeed: 'fast', cacheEfficiency: 'high', parallelism: true, diskUsage: 'low', memoryUsage: 'medium', startupTime: 300 }, features: { workspaces: true, lockfiles: true, peerDependencies: true, patchSupport: true, offlineMode: true, securityAudit: true, autoInstall: true, deterministicInstalls: true, pluginSystem: true }, commands: { install: 'yarn install', add: 'yarn add', remove: 'yarn remove', update: 'yarn upgrade', run: 'yarn', test: 'yarn test', build: 'yarn build', publish: 'yarn publish', audit: 'yarn audit', cache: 'yarn cache' } }); PackageManagerDetector.managerInfo.set(PackageManager.PNPM, { name: PackageManager.PNPM, version: '', path: '', isInstalled: false, performance: { installSpeed: 'fast', cacheEfficiency: 'high', parallelism: true, diskUsage: 'low', memoryUsage: 'low', startupTime: 200 }, features: { workspaces: true, lockfiles: true, peerDependencies: true, patchSupport: true, offlineMode: true, securityAudit: true, autoInstall: false, deterministicInstalls: true, pluginSystem: false }, commands: { install: 'pnpm install', add: 'pnpm add', remove: 'pnpm remove', update: 'pnpm update', run: 'pnpm', test: 'pnpm test', build: 'pnpm build', publish: 'pnpm publish', audit: 'pnpm audit', cache: 'pnpm store' } }); PackageManagerDetector.managerInfo.set(PackageManager.BUN, { name: PackageManager.BUN, version: '', path: '', isInstalled: false, performance: { installSpeed: 'fast', cacheEfficiency: 'high', parallelism: true, diskUsage: 'low', memoryUsage: 'low', startupTime: 100 }, features: { workspaces: true, lockfiles: true, peerDependencies: true, patchSupport: false, offlineMode: true, securityAudit: false, autoInstall: true, deterministicInstalls: true, pluginSystem: false }, commands: { install: 'bun install', add: 'bun add', remove: 'bun remove', update: 'bun update', run: 'bun run', test: 'bun test', build: 'bun build', publish: 'bun publish', audit: '', cache: '' } }); // Other Language Package Managers PackageManagerDetector.managerInfo.set(PackageManager.PIP, { name: PackageManager.PIP, version: '', path: '', isInstalled: false, performance: { installSpeed: 'medium', cacheEfficiency: 'medium', parallelism: false, diskUsage: 'medium', memoryUsage: 'low', startupTime: 400 }, features: { workspaces: false, lockfiles: false, peerDependencies: false, patchSupport: false, offlineMode: true, securityAudit: false, autoInstall: false, deterministicInstalls: false, pluginSystem: false }, commands: { install: 'pip install', add: 'pip install', remove: 'pip uninstall', update: 'pip install --upgrade', run: 'python', test: 'pytest', build: 'python setup.py build', publish: 'python setup.py upload', audit: '', cache: 'pip cache' } }); PackageManagerDetector.managerInfo.set(PackageManager.POETRY, { name: PackageManager.POETRY, version: '', path: '', isInstalled: false, performance: { installSpeed: 'medium', cacheEfficiency: 'high', parallelism: true, diskUsage: 'low', memoryUsage: 'medium', startupTime: 600 }, features: { workspaces: false, lockfiles: true, peerDependencies: false, patchSupport: false, offlineMode: true, securityAudit: true, autoInstall: false, deterministicInstalls: true, pluginSystem: true }, commands: { install: 'poetry install', add: 'poetry add', remove: 'poetry remove', update: 'poetry update', run: 'poetry run', test: 'poetry run pytest', build: 'poetry build', publish: 'poetry publish', audit: 'poetry check', cache: 'poetry cache' } }); // Add more package managers as needed... } async detectInstalledManagers() { for (const [manager, info] of PackageManagerDetector.managerInfo) { try { const result = await this.checkManagerInstallation(manager); if (result.isInstalled) { info.isInstalled = true; info.version = result.version; info.path = result.path; } } catch (error) { // Manager not installed info.isInstalled = false; } } } async checkManagerInstallation(manager) { const commands = { [PackageManager.NPM]: 'npm --version', [PackageManager.YARN]: 'yarn --version', [PackageManager.PNPM]: 'pnpm --version', [PackageManager.BUN]: 'bun --version', [PackageManager.DENO]: 'deno --version', [PackageManager.CARGO]: 'cargo --version', [PackageManager.PIP]: 'pip --version', [PackageManager.POETRY]: 'poetry --version', [PackageManager.BUNDLER]: 'bundle --version', [PackageManager.COMPOSER]: 'composer --version', [PackageManager.MAVEN]: 'mvn --version', [PackageManager.GRADLE]: 'gradle --version', [PackageManager.GO]: 'go version', [PackageManager.DOTNET]: 'dotnet --version', [PackageManager.UNKNOWN]: '' }; const command = commands[manager]; if (!command) { return { isInstalled: false, version: '', path: '' }; } try { const version = (0, child_process_1.execSync)(command, { encoding: 'utf8' }).trim(); const pathCommand = process.platform === 'win32' ? 'where' : 'which'; const path = (0, child_process_1.execSync)(`${pathCommand} ${manager}`, { encoding: 'utf8' }).trim().split('\n')[0]; return { isInstalled: true, version, path }; } catch { return { isInstalled: false, version: '', path: '' }; } } async detect(context) { this.emit('detection:start', context); const detectionMethods = [ this.detectByLockFile.bind(this), this.detectByConfigFile.bind(this), this.detectByProjectType.bind(this), this.detectByEnvironment.bind(this), this.detectByUserPreference.bind(this) ]; const results = []; for (const method of detectionMethods) { const result = await method(context); if (result) { results.push(result); } } // Sort by confidence results.sort((a, b) => b.confidence - a.confidence); if (results.length === 0) { return { detected: PackageManager.UNKNOWN, confidence: 0, reason: 'No package manager detected', alternatives: [] }; } const detected = results[0]; const alternatives = results.slice(1); // Performance analysis const performanceAnalysis = await this.analyzePerformance(context, results.map(r => r.manager)); const result = { detected: detected.manager, confidence: detected.confidence, reason: detected.reason, alternatives, recommendation: performanceAnalysis.recommended, performanceAnalysis }; this.emit('detection:complete', result); return result; } async detectByLockFile(context) { const lockFiles = [ { file: 'package-lock.json', manager: PackageManager.NPM }, { file: 'yarn.lock', manager: PackageManager.YARN }, { file: 'pnpm-lock.yaml', manager: PackageManager.PNPM }, { file: 'bun.lockb', manager: PackageManager.BUN }, { file: 'Pipfile.lock', manager: PackageManager.PIP }, { file: 'poetry.lock', manager: PackageManager.POETRY }, { file: 'Gemfile.lock', manager: PackageManager.BUNDLER }, { file: 'composer.lock', manager: PackageManager.COMPOSER }, { file: 'Cargo.lock', manager: PackageManager.CARGO }, { file: 'go.sum', manager: PackageManager.GO } ]; for (const { file, manager } of lockFiles) { const lockPath = path.join(context.projectPath, file); if (await fs.pathExists(lockPath)) { return { manager, confidence: 100, reason: `Found ${file} lock file` }; } } return null; } async detectByConfigFile(context) { // Check package.json for specific fields const packageJsonPath = path.join(context.projectPath, 'package.json'); if (await fs.pathExists(packageJsonPath)) { try { const packageJson = await fs.readJson(packageJsonPath); // Check for packageManager field (corepack) if (packageJson.packageManager) { const manager = packageJson.packageManager.split('@')[0]; return { manager: manager, confidence: 95, reason: 'Specified in package.json packageManager field' }; } // Check for workspace configuration if (packageJson.workspaces) { if (packageJson.workspaces.packages) { return { manager: PackageManager.YARN, confidence: 80, reason: 'Yarn workspaces configuration detected' }; } } // Check for pnpm workspace const pnpmWorkspacePath = path.join(context.projectPath, 'pnpm-workspace.yaml'); if (await fs.pathExists(pnpmWorkspacePath)) { return { manager: PackageManager.PNPM, confidence: 90, reason: 'PNPM workspace configuration detected' }; } } catch (error) { // Invalid package.json } } // Check for other config files const configFiles = [ { file: '.yarnrc.yml', manager: PackageManager.YARN }, { file: '.npmrc', manager: PackageManager.NPM }, { file: '.pnpmfile.cjs', manager: PackageManager.PNPM }, { file: 'pyproject.toml', manager: PackageManager.POETRY }, { file: 'Pipfile', manager: PackageManager.PIP }, { file: 'requirements.txt', manager: PackageManager.PIP }, { file: 'Gemfile', manager: PackageManager.BUNDLER }, { file: 'composer.json', manager: PackageManager.COMPOSER }, { file: 'Cargo.toml', manager: PackageManager.CARGO }, { file: 'go.mod', manager: PackageManager.GO }, { file: 'pom.xml', manager: PackageManager.MAVEN }, { file: 'build.gradle', manager: PackageManager.GRADLE } ]; for (const { file, manager } of configFiles) { const configPath = path.join(context.projectPath, file); if (await fs.pathExists(configPath)) { return { manager, confidence: 70, reason: `Found ${file} configuration file` }; } } return null; } async detectByProjectType(context) { if (!context.projectType || context.projectType === 'unknown') { return null; } const typeManagers = { node: PackageManager.NPM, python: PackageManager.PIP, ruby: PackageManager.BUNDLER, java: PackageManager.MAVEN, go: PackageManager.GO, rust: PackageManager.CARGO, php: PackageManager.COMPOSER, dotnet: PackageManager.DOTNET }; const manager = typeManagers[context.projectType]; if (manager) { return { manager, confidence: 50, reason: `Default for ${context.projectType} projects` }; } return null; } async detectByEnvironment(context) { // Check environment variables const envManagers = [ { env: 'npm_config_user_agent', manager: PackageManager.NPM }, { env: 'YARN_VERSION', manager: PackageManager.YARN }, { env: 'PNPM_HOME', manager: PackageManager.PNPM }, { env: 'BUN_INSTALL', manager: PackageManager.BUN } ]; for (const { env, manager } of envManagers) { if (process.env[env]) { return { manager, confidence: 60, reason: `${env} environment variable detected` }; } } // Check which managers are installed const installed = Array.from(PackageManagerDetector.managerInfo.values()) .filter(info => info.isInstalled); if (installed.length === 1) { return { manager: installed[0].name, confidence: 40, reason: 'Only package manager installed on system' }; } return null; } async detectByUserPreference(context) { // Check user's global configuration const userConfig = path.join(os.homedir(), '.re-shell', 'config.yaml'); if (await fs.pathExists(userConfig)) { try { const yaml = require('js-yaml'); const config = yaml.load(await fs.readFile(userConfig, 'utf8')); if (config.defaultPackageManager) { return { manager: config.defaultPackageManager, confidence: 30, reason: 'User preference in global configuration' }; } } catch (error) { // Invalid config } } return null; } async analyzePerformance(context, managers) { const analysis = {}; for (const manager of managers) { const info = PackageManagerDetector.managerInfo.get(manager); if (!info || !info.isInstalled) continue; const score = this.calculatePerformanceScore(info, context); const { pros, cons } = this.analyzeManagerProsAndCons(info, context); analysis[manager] = { score, pros, cons }; } // Determine winners const entries = Object.entries(analysis); const fastest = entries.reduce((a, b) => a[1].score > b[1].score ? a : b)[0]; const mostEfficient = this.determineMostEfficient(analysis, context); const recommended = this.determineRecommended(analysis, context); return { fastest, mostEfficient, recommended, analysis }; } calculatePerformanceScore(info, context) { let score = 0; // Speed scoring switch (info.performance.installSpeed) { case 'fast': score += 30; break; case 'medium': score += 20; break; case 'slow': score += 10; break; } // Cache efficiency switch (info.performance.cacheEfficiency) { case 'high': score += 20; break; case 'medium': score += 10; break; case 'low': score += 5; break; } // Parallelism bonus if (info.performance.parallelism) score += 15; // Disk usage (inverse scoring) switch (info.performance.diskUsage) { case 'low': score += 15; break; case 'medium': score += 10; break; case 'high': score += 5; break; } // Memory usage (inverse scoring) switch (info.performance.memoryUsage) { case 'low': score += 10; break; case 'medium': score += 5; break; case 'high': score += 0; break; } // Startup time (inverse scoring) if (info.performance.startupTime < 200) score += 10; else if (info.performance.startupTime < 500) score += 5; // Context-specific bonuses if (context.isMonorepo && info.features.workspaces) score += 20; if (context.size === 'large' && info.performance.cacheEfficiency === 'high') score += 15; return score; } analyzeManagerProsAndCons(info, context) { const pros = []; const cons = []; // Performance pros/cons if (info.performance.installSpeed === 'fast') { pros.push('Fast installation speed'); } else if (info.performance.installSpeed === 'slow') { cons.push('Slow installation speed'); } if (info.performance.cacheEfficiency === 'high') { pros.push('Excellent cache efficiency'); } if (info.performance.parallelism) { pros.push('Parallel package installation'); } else { cons.push('No parallel installation support'); } if (info.performance.diskUsage === 'low') { pros.push('Low disk usage'); } else if (info.performance.diskUsage === 'high') { cons.push('High disk usage'); } // Feature pros/cons if (info.features.workspaces) { pros.push('Native workspace support'); } else if (context.isMonorepo) { cons.push('No workspace support for monorepos'); } if (info.features.lockfiles) { pros.push('Deterministic installs with lockfiles'); } else { cons.push('No lockfile support'); } if (info.features.securityAudit) { pros.push('Built-in security auditing'); } if (info.features.offlineMode) { pros.push('Offline mode support'); } if (info.features.patchSupport) { pros.push('Package patching support'); } return { pros, cons }; } determineMostEfficient(analysis, context) { // Consider cache efficiency and disk usage let bestManager = PackageManager.UNKNOWN; let bestScore = 0; for (const [manager, data] of Object.entries(analysis)) { const info = PackageManagerDetector.managerInfo.get(manager); if (!info) continue; let efficiencyScore = data.score; // Weight cache efficiency highly if (info.performance.cacheEfficiency === 'high') efficiencyScore += 20; // Weight disk usage if (info.performance.diskUsage === 'low') efficiencyScore += 15; // Consider memory usage for large projects if (context.size === 'large' && info.performance.memoryUsage === 'low') { efficiencyScore += 10; } if (efficiencyScore > bestScore) { bestScore = efficiencyScore; bestManager = manager; } } return bestManager; } determineRecommended(analysis, context) { // Holistic recommendation based on context const recommendations = []; for (const [manager, data] of Object.entries(analysis)) { const info = PackageManagerDetector.managerInfo.get(manager); if (!info) continue; let recommendationScore = data.score; // Context-specific adjustments if (context.isMonorepo) { if (manager === PackageManager.PNPM) recommendationScore += 30; // PNPM excels at monorepos if (manager === PackageManager.YARN) recommendationScore += 20; // Yarn also good for monorepos } if (context.size === 'large') { if (info.performance.cacheEfficiency === 'high') recommendationScore += 20; if (info.performance.parallelism) recommendationScore += 15; } if (context.projectType === 'node') { // Prefer Node.js-specific managers if ([PackageManager.PNPM, PackageManager.YARN, PackageManager.BUN].includes(manager)) { recommendationScore += 10; } } recommendations.push({ manager: manager, score: recommendationScore }); } recommendations.sort((a, b) => b.score - a.score); return recommendations[0]?.manager || PackageManager.NPM; } async benchmark(context, managers) { this.emit('benchmark:start', { context, managers }); const results = new Map(); const managersToTest = managers || Array.from(PackageManagerDetector.managerInfo.keys()) .filter(m => PackageManagerDetector.managerInfo.get(m)?.isInstalled); for (const manager of managersToTest) { try { const result = await this.runBenchmark(manager, context); results.set(manager, result); this.emit('benchmark:progress', { manager, result }); } catch (error) { this.emit('benchmark:error', { manager, error }); } } this.emit('benchmark:complete', results); return results; } async runBenchmark(manager, context) { // This is a placeholder for actual benchmarking // In a real implementation, this would: // 1. Create a temporary test project // 2. Run install commands and measure time // 3. Clear cache and re-run to measure cache performance // 4. Monitor disk and memory usage const info = PackageManagerDetector.managerInfo.get(manager); if (!info) { throw new Error(`Manager ${manager} not found`); } // Simulated benchmark results based on known characteristics const baseInstallTime = info.performance.startupTime; const installTime = baseInstallTime + Math.random() * 1000; const cacheHitTime = installTime * 0.3; const diskUsage = info.performance.diskUsage === 'low' ? 50 : info.performance.diskUsage === 'medium' ? 100 : 200; const memoryPeak = info.performance.memoryUsage === 'low' ? 128 : info.performance.memoryUsage === 'medium' ? 256 : 512; return { installTime, cacheHitTime, diskUsage, memoryPeak }; } getInstalledManagers() { return Array.from(PackageManagerDetector.managerInfo.entries()) .filter(([_, info]) => info.isInstalled) .map(([manager, _]) => manager); } getManagerInfo(manager) { return PackageManagerDetector.managerInfo.get(manager); } async getRecommendedManager(context) { const result = await this.detect(context); return result.recommendation || result.detected; } async ensureManagerInstalled(manager) { const info = PackageManagerDetector.managerInfo.get(manager); if (!info || !info.isInstalled) { this.emit('manager:not_installed', manager); return false; } return true; } } exports.PackageManagerDetector = PackageManagerDetector; PackageManagerDetector.managerInfo = new Map(); PackageManagerDetector.initialized = false; PackageManagerDetector.performanceCache = new Map(); // Global instance let globalDetector = null; function getPackageManagerDetector() { if (!globalDetector) { globalDetector = new PackageManagerDetector(); } return globalDetector; } async function detectPackageManager(context) { const detector = getPackageManagerDetector(); return detector.detect(context); } async function getRecommendedPackageManager(context) { const result = await detectPackageManager(context); return result.recommendation || result.detected; }