From 0fb6f3cf4e85aeffae5c8cbba2dff740fcd2121d Mon Sep 17 00:00:00 2001 From: Alex Newman Date: Fri, 12 Dec 2025 23:29:42 -0500 Subject: [PATCH] refactor: streamline Bun and uv installation checks and paths --- scripts/smart-install.js | 180 +++++++++++---------------------------- 1 file changed, 52 insertions(+), 128 deletions(-) diff --git a/scripts/smart-install.js b/scripts/smart-install.js index 1a04fd24..cc786e41 100644 --- a/scripts/smart-install.js +++ b/scripts/smart-install.js @@ -14,28 +14,14 @@ const ROOT = join(homedir(), '.claude', 'plugins', 'marketplaces', 'thedotmack') const MARKER = join(ROOT, '.install-version'); const IS_WINDOWS = process.platform === 'win32'; -/** - * Check if Bun is installed and accessible - */ -function isBunInstalled() { - try { - const result = spawnSync('bun', ['--version'], { - encoding: 'utf-8', - stdio: ['pipe', 'pipe', 'pipe'], - shell: IS_WINDOWS - }); - if (result.status === 0) return true; - } catch { - // PATH check failed, try common installation paths - } +// Common installation paths (handles fresh installs before PATH reload) +const BUN_COMMON_PATHS = IS_WINDOWS + ? [join(homedir(), '.bun', 'bin', 'bun.exe')] + : [join(homedir(), '.bun', 'bin', 'bun'), '/usr/local/bin/bun']; - // Check common installation paths (handles fresh installs before PATH reload) - const bunPaths = IS_WINDOWS - ? [join(homedir(), '.bun', 'bin', 'bun.exe')] - : [join(homedir(), '.bun', 'bin', 'bun'), '/usr/local/bin/bun']; - - return bunPaths.some(existsSync); -} +const UV_COMMON_PATHS = IS_WINDOWS + ? [join(homedir(), '.local', 'bin', 'uv.exe'), join(homedir(), '.cargo', 'bin', 'uv.exe')] + : [join(homedir(), '.local', 'bin', 'uv'), join(homedir(), '.cargo', 'bin', 'uv'), '/usr/local/bin/uv']; /** * Get the Bun executable path (from PATH or common install locations) @@ -54,15 +40,14 @@ function getBunPath() { } // Check common installation paths - const bunPaths = IS_WINDOWS - ? [join(homedir(), '.bun', 'bin', 'bun.exe')] - : [join(homedir(), '.bun', 'bin', 'bun'), '/usr/local/bin/bun']; + return BUN_COMMON_PATHS.find(existsSync) || null; +} - for (const bunPath of bunPaths) { - if (existsSync(bunPath)) return bunPath; - } - - return null; +/** + * Check if Bun is installed and accessible + */ +function isBunInstalled() { + return getBunPath() !== null; } /** @@ -85,34 +70,41 @@ function getBunVersion() { } /** - * Check if uv is installed and accessible + * Get the uv executable path (from PATH or common install locations) */ -function isUvInstalled() { +function getUvPath() { + // Try PATH first try { const result = spawnSync('uv', ['--version'], { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'], shell: IS_WINDOWS }); - if (result.status === 0) return true; + if (result.status === 0) return 'uv'; } catch { - // PATH check failed, try common installation paths + // Not in PATH } - // Check common installation paths (handles fresh installs before PATH reload) - const uvPaths = IS_WINDOWS - ? [join(homedir(), '.local', 'bin', 'uv.exe'), join(homedir(), '.cargo', 'bin', 'uv.exe')] - : [join(homedir(), '.local', 'bin', 'uv'), join(homedir(), '.cargo', 'bin', 'uv'), '/usr/local/bin/uv']; + // Check common installation paths + return UV_COMMON_PATHS.find(existsSync) || null; +} - return uvPaths.some(existsSync); +/** + * Check if uv is installed and accessible + */ +function isUvInstalled() { + return getUvPath() !== null; } /** * Get uv version if installed */ function getUvVersion() { + const uvPath = getUvPath(); + if (!uvPath) return null; + try { - const result = spawnSync('uv', ['--version'], { + const result = spawnSync(uvPath, ['--version'], { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'], shell: IS_WINDOWS @@ -131,14 +123,12 @@ function installBun() { try { if (IS_WINDOWS) { - // Windows: Use PowerShell installer console.error(' Installing via PowerShell...'); execSync('powershell -c "irm bun.sh/install.ps1 | iex"', { stdio: 'inherit', shell: true }); } else { - // Unix/macOS: Use curl installer console.error(' Installing via curl...'); execSync('curl -fsSL https://bun.sh/install | bash', { stdio: 'inherit', @@ -146,35 +136,17 @@ function installBun() { }); } - // Verify installation - if (isBunInstalled()) { - const version = getBunVersion(); - console.error(`✅ Bun ${version} installed successfully`); - return true; - } else { - // Bun may be installed but not in PATH yet for this session - // Try common installation paths - const bunPaths = IS_WINDOWS - ? [join(homedir(), '.bun', 'bin', 'bun.exe')] - : [join(homedir(), '.bun', 'bin', 'bun'), '/usr/local/bin/bun']; - - for (const bunPath of bunPaths) { - if (existsSync(bunPath)) { - console.error(`✅ Bun installed at ${bunPath}`); - console.error('⚠️ Please restart your terminal or add Bun to PATH:'); - if (IS_WINDOWS) { - console.error(` $env:Path += ";${join(homedir(), '.bun', 'bin')}"`); - } else { - console.error(` export PATH="$HOME/.bun/bin:$PATH"`); - } - return true; - } - } - - throw new Error('Bun installation completed but binary not found'); + if (!isBunInstalled()) { + throw new Error( + 'Bun installation completed but binary not found. ' + + 'Please restart your terminal and try again.' + ); } + + const version = getBunVersion(); + console.error(`✅ Bun ${version} installed successfully`); } catch (error) { - console.error('❌ Failed to install Bun automatically'); + console.error('❌ Failed to install Bun'); console.error(' Please install manually:'); if (IS_WINDOWS) { console.error(' - winget install Oven-sh.Bun'); @@ -196,14 +168,12 @@ function installUv() { try { if (IS_WINDOWS) { - // Windows: Use PowerShell installer console.error(' Installing via PowerShell...'); execSync('powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"', { stdio: 'inherit', shell: true }); } else { - // Unix/macOS: Use curl installer console.error(' Installing via curl...'); execSync('curl -LsSf https://astral.sh/uv/install.sh | sh', { stdio: 'inherit', @@ -211,35 +181,17 @@ function installUv() { }); } - // Verify installation - if (isUvInstalled()) { - const version = getUvVersion(); - console.error(`✅ uv ${version} installed successfully`); - return true; - } else { - // uv may be installed but not in PATH yet for this session - // Try common installation paths - const uvPaths = IS_WINDOWS - ? [join(homedir(), '.local', 'bin', 'uv.exe'), join(homedir(), '.cargo', 'bin', 'uv.exe')] - : [join(homedir(), '.local', 'bin', 'uv'), join(homedir(), '.cargo', 'bin', 'uv'), '/usr/local/bin/uv']; - - for (const uvPath of uvPaths) { - if (existsSync(uvPath)) { - console.error(`✅ uv installed at ${uvPath}`); - console.error('⚠️ Please restart your terminal or add uv to PATH:'); - if (IS_WINDOWS) { - console.error(` $env:Path += ";${join(homedir(), '.local', 'bin')}"`); - } else { - console.error(` export PATH="$HOME/.local/bin:$PATH"`); - } - return true; - } - } - - throw new Error('uv installation completed but binary not found'); + if (!isUvInstalled()) { + throw new Error( + 'uv installation completed but binary not found. ' + + 'Please restart your terminal and try again.' + ); } + + const version = getUvVersion(); + console.error(`✅ uv ${version} installed successfully`); } catch (error) { - console.error('❌ Failed to install uv automatically'); + console.error('❌ Failed to install uv'); console.error(' Please install manually:'); if (IS_WINDOWS) { console.error(' - winget install astral-sh.uv'); @@ -281,12 +233,7 @@ function installDeps() { // Quote path for Windows paths with spaces const bunCmd = IS_WINDOWS && bunPath.includes(' ') ? `"${bunPath}"` : bunPath; - try { - execSync(`${bunCmd} install`, { cwd: ROOT, stdio: 'inherit', shell: IS_WINDOWS }); - } catch { - // Retry with force flag - execSync(`${bunCmd} install --force`, { cwd: ROOT, stdio: 'inherit', shell: IS_WINDOWS }); - } + execSync(`${bunCmd} install`, { cwd: ROOT, stdio: 'inherit', shell: IS_WINDOWS }); // Write version marker const pkg = JSON.parse(readFileSync(join(ROOT, 'package.json'), 'utf-8')); @@ -300,31 +247,8 @@ function installDeps() { // Main execution try { - // Step 1: Ensure Bun is installed (REQUIRED) - if (!isBunInstalled()) { - installBun(); - - // Re-check after installation - if (!isBunInstalled()) { - console.error('❌ Bun is required but not available in PATH'); - console.error(' Please restart your terminal after installation'); - process.exit(1); - } - } - - // Step 2: Ensure uv is installed (REQUIRED for vector search) - if (!isUvInstalled()) { - installUv(); - - // Re-check after installation - if (!isUvInstalled()) { - console.error('❌ uv is required but not available in PATH'); - console.error(' Please restart your terminal after installation'); - process.exit(1); - } - } - - // Step 3: Install dependencies if needed + if (!isBunInstalled()) installBun(); + if (!isUvInstalled()) installUv(); if (needsInstall()) { installDeps(); console.error('✅ Dependencies installed');