UNPKG

seb-cli-tool

Version:

SEB CLI - Smart Embedded Board Configuration Tool - Cloud-First MCU Management

401 lines (340 loc) 14.2 kB
#!/usr/bin/env node const { spawn, execSync } = require('child_process'); const path = require('path'); const fs = require('fs'); const which = require('which'); console.log('🔧 Setting up SEB CLI Python dependencies...'); // Check Windows-specific prerequisites function checkWindowsPrerequisites() { const isWindows = process.platform === 'win32'; if (!isWindows) return; console.log('🔍 Checking Windows prerequisites...'); // Check if running as Administrator (optional warning) try { const { execSync } = require('child_process'); execSync('net session', { stdio: 'ignore' }); console.log('✅ Running with Administrator privileges'); } catch (e) { console.log('⚠️ Not running as Administrator (this might cause issues)'); console.log('💡 If installation fails, try running as Administrator'); } // Check PowerShell execution policy (skip if module not available) try { const { execSync } = require('child_process'); const policy = execSync('powershell -Command "Get-ExecutionPolicy"', { encoding: 'utf8' }).trim(); if (policy === 'Restricted') { console.log('⚠️ PowerShell execution policy is Restricted'); console.log('💡 Run: Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser'); } else { console.log(`✅ PowerShell execution policy: ${policy}`); } } catch (e) { console.log('⚠️ Could not check PowerShell execution policy (continuing anyway)'); } } // Find Python executable function findPython() { const isWindows = process.platform === 'win32'; try { // Try python3 first return which.sync('python3'); } catch (e) { try { // Fallback to python return which.sync('python'); } catch (e) { // On Windows, try common Python installation paths if (isWindows) { const commonPaths = [ 'C:\\Python310\\python.exe', 'C:\\Python311\\python.exe', 'C:\\Python312\\python.exe', 'C:\\Users\\' + process.env.USERNAME + '\\AppData\\Local\\Programs\\Python\\Python310\\python.exe', 'C:\\Users\\' + process.env.USERNAME + '\\AppData\\Local\\Programs\\Python\\Python311\\python.exe', 'C:\\Users\\' + process.env.USERNAME + '\\AppData\\Local\\Programs\\Python\\Python312\\python.exe' ]; for (const pythonPath of commonPaths) { if (fs.existsSync(pythonPath)) { console.log(`✅ Found Python at: ${pythonPath}`); return pythonPath; } } } console.error('❌ Python not found. Please install Python 3.10+ from https://www.python.org/downloads/'); if (isWindows) { console.error('💡 Make sure to check "Add Python to PATH" during installation'); console.error('💡 Or try running: npm run setup-windows'); } process.exit(1); } } } // Check Python version function checkPythonVersion(pythonPath) { try { const version = execSync(`"${pythonPath}" --version`, { encoding: 'utf8' }); const match = version.match(/Python (\d+)\.(\d+)/); if (match) { const major = parseInt(match[1]); const minor = parseInt(match[2]); if (major < 3 || (major === 3 && minor < 10)) { console.error('❌ Python 3.10+ is required. Found:', version.trim()); process.exit(1); } console.log(`✅ Found Python ${version.trim()}`); return true; } } catch (e) { console.error('❌ Could not check Python version:', e.message); process.exit(1); } } // Create virtual environment function createVirtualEnv(pythonPath) { const isWindows = process.platform === 'win32'; const isGlobalInstall = process.env.npm_config_global === 'true' || process.argv.includes('--global'); let venvPath; if (isGlobalInstall) { const userHome = process.env.HOME || process.env.USERPROFILE; const sebHome = path.join(userHome, '.seb'); venvPath = path.join(sebHome, 'venv'); // Create .seb directory if it doesn't exist if (!fs.existsSync(sebHome)) { try { fs.mkdirSync(sebHome, { recursive: true }); } catch (error) { console.error('❌ Could not create .seb directory:', error.message); if (isWindows) { console.error('💡 Try running as Administrator or check folder permissions'); console.error('💡 Alternative: Try installing in a different location'); } throw error; } } } else { // For local installations, use package directory const packageDir = path.dirname(__dirname); venvPath = path.join(packageDir, 'seb_env'); } // Windows-specific: Check for path length issues if (isWindows && venvPath.length > 200) { console.warn('⚠️ Warning: Path is very long, this might cause issues on Windows'); console.warn(` Path length: ${venvPath.length} characters`); console.warn(' Consider installing in a shorter path'); } if (fs.existsSync(venvPath)) { console.log('✅ Virtual environment already exists'); return venvPath; } console.log('🔧 Creating virtual environment...'); return new Promise((resolve, reject) => { const venvDir = path.dirname(venvPath); const venvName = path.basename(venvPath); console.log(`📁 Creating venv in: ${venvDir}`); console.log(`📁 Venv name: ${venvName}`); const venvProcess = spawn(pythonPath, ['-m', 'venv', venvName], { stdio: 'inherit', cwd: venvDir }); venvProcess.on('close', (code) => { if (code === 0) { console.log('✅ Virtual environment created'); resolve(venvPath); } else { console.error('❌ Failed to create virtual environment'); if (isWindows) { console.error('💡 Common Windows issues:'); console.error(' - Run as Administrator'); console.error(' - Check antivirus is not blocking'); console.error(' - Try: npm run setup-windows'); console.error(' - Try installing in a different location (shorter path)'); // Try alternative approach for Windows console.log('🔄 Trying alternative virtual environment creation...'); tryAlternativeVenvCreation(pythonPath, venvPath).then(resolve).catch(reject); } else { reject(new Error(`venv creation failed with code ${code}`)); } } }); venvProcess.on('error', (error) => { console.error('❌ Error creating virtual environment:', error.message); if (isWindows) { console.error('💡 Try running: npm run setup-windows'); } reject(error); }); }); } // Alternative virtual environment creation for Windows function tryAlternativeVenvCreation(pythonPath, originalVenvPath) { return new Promise((resolve, reject) => { console.log('🔄 Trying alternative virtual environment creation...'); // Try creating in a shorter path const userHome = process.env.USERPROFILE; const alternativePath = path.join(userHome, 'seb_venv'); console.log(`📁 Trying alternative path: ${alternativePath}`); const altVenvProcess = spawn(pythonPath, ['-m', 'venv', alternativePath], { stdio: 'inherit', cwd: userHome }); altVenvProcess.on('close', (code) => { if (code === 0) { console.log('✅ Alternative virtual environment created successfully'); console.log(`📁 Location: ${alternativePath}`); resolve(alternativePath); } else { console.error('❌ Alternative virtual environment creation also failed'); console.error('💡 Manual installation required:'); console.error(' 1. Open Command Prompt as Administrator'); console.error(' 2. Run: python -m venv C:\\seb_venv'); console.error(' 3. Run: C:\\seb_venv\\Scripts\\activate'); console.error(' 4. Run: pip install -r requirements.txt'); reject(new Error('All virtual environment creation methods failed')); } }); altVenvProcess.on('error', (error) => { console.error('❌ Alternative virtual environment creation error:', error.message); reject(error); }); }); } // Get virtual environment Python path function getVenvPython(venvPath) { const isWindows = process.platform === 'win32'; const pythonName = isWindows ? 'python.exe' : 'python'; const pythonPath = path.join(venvPath, isWindows ? 'Scripts' : 'bin', pythonName); if (fs.existsSync(pythonPath)) { return pythonPath; } // Try python3 const python3Name = isWindows ? 'python3.exe' : 'python3'; const python3Path = path.join(venvPath, isWindows ? 'Scripts' : 'bin', python3Name); if (fs.existsSync(python3Path)) { return python3Path; } throw new Error('Could not find Python in virtual environment'); } // Install Python dependencies in virtual environment function installPythonDeps(venvPython) { const packageDir = path.dirname(__dirname); const requirementsPath = path.join(packageDir, 'requirements.txt'); const isWindows = process.platform === 'win32'; if (!fs.existsSync(requirementsPath)) { console.log('⚠️ No requirements.txt found, skipping Python dependency installation'); return Promise.resolve(); } console.log('📦 Installing Python dependencies...'); console.log(`📁 Requirements file: ${requirementsPath}`); return new Promise((resolve, reject) => { const pipProcess = spawn(venvPython, ['-m', 'pip', 'install', '-r', requirementsPath], { stdio: 'inherit', cwd: packageDir }); pipProcess.on('close', (code) => { if (code === 0) { console.log('✅ Python dependencies installed successfully'); resolve(); } else { console.error('❌ Failed to install Python dependencies'); if (isWindows) { console.error('💡 Common Windows pip issues:'); console.error(' - Check internet connection'); console.error(' - Try: pip install --upgrade pip'); console.error(' - Try: npm run setup-windows'); console.error(' - Try running as Administrator'); console.error(' - Check antivirus/firewall settings'); // Provide manual installation steps console.error('💡 Manual installation steps:'); console.error(' 1. Open Command Prompt as Administrator'); console.error(' 2. Navigate to virtual environment: cd %USERPROFILE%\\.seb\\venv\\Scripts'); console.error(' 3. Activate: activate.bat'); console.error(' 4. Install: pip install -r requirements.txt'); } reject(new Error(`pip install failed with code ${code}`)); } }); pipProcess.on('error', (error) => { console.error('❌ Error running pip:', error.message); if (isWindows) { console.error('💡 Try running: npm run setup-windows'); } reject(error); }); }); } // Install the SEB package in development mode function installSebPackage(venvPython) { const packageDir = path.dirname(__dirname); const setupPath = path.join(packageDir, 'setup.py'); if (!fs.existsSync(setupPath)) { console.log('⚠️ No setup.py found, skipping package installation'); return Promise.resolve(); } console.log('🔧 Installing SEB package in development mode...'); return new Promise((resolve, reject) => { const installProcess = spawn(venvPython, ['-m', 'pip', 'install', '-e', '.'], { stdio: 'inherit', cwd: packageDir }); installProcess.on('close', (code) => { if (code === 0) { console.log('✅ SEB package installed successfully'); resolve(); } else { console.error('❌ Failed to install SEB package'); reject(new Error(`pip install -e failed with code ${code}`)); } }); installProcess.on('error', (error) => { console.error('❌ Error installing SEB package:', error.message); reject(error); }); }); } // Create configuration file for global installations function createConfigFile(venvPath) { const isGlobalInstall = process.env.npm_config_global === 'true' || process.argv.includes('--global'); if (isGlobalInstall) { const userHome = process.env.HOME || process.env.USERPROFILE; const sebHome = path.join(userHome, '.seb'); const configPath = path.join(sebHome, 'config.json'); const isWindows = process.platform === 'win32'; const config = { venv_path: venvPath, python_path: path.join(venvPath, isWindows ? 'Scripts' : 'bin', isWindows ? 'python.exe' : 'python'), created_at: new Date().toISOString(), platform: process.platform, analytics_enabled: true // Enable analytics by default }; fs.writeFileSync(configPath, JSON.stringify(config, null, 2)); console.log('✅ Configuration file created for global installation'); } } // Main installation process async function main() { try { // Check Windows prerequisites first checkWindowsPrerequisites(); const pythonPath = findPython(); checkPythonVersion(pythonPath); // Always create virtual environment to avoid externally-managed-environment issues const venvPath = await createVirtualEnv(pythonPath); const venvPython = getVenvPython(venvPath); await installPythonDeps(venvPython); await installSebPackage(venvPython); // Create configuration file for global installations createConfigFile(venvPath); console.log('🎉 SEB CLI setup complete!'); console.log(`💡 Virtual environment: ${venvPath}`); console.log('💡 You can now use: seb --help'); } catch (error) { console.error('❌ Setup failed:', error.message); console.log('💡 Try running: npm run setup-python'); process.exit(1); } } // Run if called directly if (require.main === module) { main(); } module.exports = { main, findPython, checkPythonVersion, createVirtualEnv, getVenvPython, installPythonDeps, installSebPackage, createConfigFile };