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