refactor: streamline Bun and uv installation checks and paths

This commit is contained in:
Alex Newman
2025-12-12 23:29:42 -05:00
parent 5cd68f4a96
commit 0fb6f3cf4e
+52 -128
View File
@@ -14,28 +14,14 @@ const ROOT = join(homedir(), '.claude', 'plugins', 'marketplaces', 'thedotmack')
const MARKER = join(ROOT, '.install-version'); const MARKER = join(ROOT, '.install-version');
const IS_WINDOWS = process.platform === 'win32'; const IS_WINDOWS = process.platform === 'win32';
/** // Common installation paths (handles fresh installs before PATH reload)
* Check if Bun is installed and accessible const BUN_COMMON_PATHS = IS_WINDOWS
*/ ? [join(homedir(), '.bun', 'bin', 'bun.exe')]
function isBunInstalled() { : [join(homedir(), '.bun', 'bin', 'bun'), '/usr/local/bin/bun'];
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
}
// Check common installation paths (handles fresh installs before PATH reload) const UV_COMMON_PATHS = IS_WINDOWS
const bunPaths = IS_WINDOWS ? [join(homedir(), '.local', 'bin', 'uv.exe'), join(homedir(), '.cargo', 'bin', 'uv.exe')]
? [join(homedir(), '.bun', 'bin', 'bun.exe')] : [join(homedir(), '.local', 'bin', 'uv'), join(homedir(), '.cargo', 'bin', 'uv'), '/usr/local/bin/uv'];
: [join(homedir(), '.bun', 'bin', 'bun'), '/usr/local/bin/bun'];
return bunPaths.some(existsSync);
}
/** /**
* Get the Bun executable path (from PATH or common install locations) * Get the Bun executable path (from PATH or common install locations)
@@ -54,15 +40,14 @@ function getBunPath() {
} }
// Check common installation paths // Check common installation paths
const bunPaths = IS_WINDOWS return BUN_COMMON_PATHS.find(existsSync) || null;
? [join(homedir(), '.bun', 'bin', 'bun.exe')] }
: [join(homedir(), '.bun', 'bin', 'bun'), '/usr/local/bin/bun'];
for (const bunPath of bunPaths) { /**
if (existsSync(bunPath)) return bunPath; * Check if Bun is installed and accessible
} */
function isBunInstalled() {
return null; 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 { try {
const result = spawnSync('uv', ['--version'], { const result = spawnSync('uv', ['--version'], {
encoding: 'utf-8', encoding: 'utf-8',
stdio: ['pipe', 'pipe', 'pipe'], stdio: ['pipe', 'pipe', 'pipe'],
shell: IS_WINDOWS shell: IS_WINDOWS
}); });
if (result.status === 0) return true; if (result.status === 0) return 'uv';
} catch { } catch {
// PATH check failed, try common installation paths // Not in PATH
} }
// Check common installation paths (handles fresh installs before PATH reload) // Check common installation paths
const uvPaths = IS_WINDOWS return UV_COMMON_PATHS.find(existsSync) || null;
? [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'];
return uvPaths.some(existsSync); /**
* Check if uv is installed and accessible
*/
function isUvInstalled() {
return getUvPath() !== null;
} }
/** /**
* Get uv version if installed * Get uv version if installed
*/ */
function getUvVersion() { function getUvVersion() {
const uvPath = getUvPath();
if (!uvPath) return null;
try { try {
const result = spawnSync('uv', ['--version'], { const result = spawnSync(uvPath, ['--version'], {
encoding: 'utf-8', encoding: 'utf-8',
stdio: ['pipe', 'pipe', 'pipe'], stdio: ['pipe', 'pipe', 'pipe'],
shell: IS_WINDOWS shell: IS_WINDOWS
@@ -131,14 +123,12 @@ function installBun() {
try { try {
if (IS_WINDOWS) { if (IS_WINDOWS) {
// Windows: Use PowerShell installer
console.error(' Installing via PowerShell...'); console.error(' Installing via PowerShell...');
execSync('powershell -c "irm bun.sh/install.ps1 | iex"', { execSync('powershell -c "irm bun.sh/install.ps1 | iex"', {
stdio: 'inherit', stdio: 'inherit',
shell: true shell: true
}); });
} else { } else {
// Unix/macOS: Use curl installer
console.error(' Installing via curl...'); console.error(' Installing via curl...');
execSync('curl -fsSL https://bun.sh/install | bash', { execSync('curl -fsSL https://bun.sh/install | bash', {
stdio: 'inherit', stdio: 'inherit',
@@ -146,35 +136,17 @@ function installBun() {
}); });
} }
// Verify installation if (!isBunInstalled()) {
if (isBunInstalled()) { throw new Error(
const version = getBunVersion(); 'Bun installation completed but binary not found. ' +
console.error(`✅ Bun ${version} installed successfully`); 'Please restart your terminal and try again.'
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');
} }
const version = getBunVersion();
console.error(`✅ Bun ${version} installed successfully`);
} catch (error) { } catch (error) {
console.error('❌ Failed to install Bun automatically'); console.error('❌ Failed to install Bun');
console.error(' Please install manually:'); console.error(' Please install manually:');
if (IS_WINDOWS) { if (IS_WINDOWS) {
console.error(' - winget install Oven-sh.Bun'); console.error(' - winget install Oven-sh.Bun');
@@ -196,14 +168,12 @@ function installUv() {
try { try {
if (IS_WINDOWS) { if (IS_WINDOWS) {
// Windows: Use PowerShell installer
console.error(' Installing via PowerShell...'); console.error(' Installing via PowerShell...');
execSync('powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"', { execSync('powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"', {
stdio: 'inherit', stdio: 'inherit',
shell: true shell: true
}); });
} else { } else {
// Unix/macOS: Use curl installer
console.error(' Installing via curl...'); console.error(' Installing via curl...');
execSync('curl -LsSf https://astral.sh/uv/install.sh | sh', { execSync('curl -LsSf https://astral.sh/uv/install.sh | sh', {
stdio: 'inherit', stdio: 'inherit',
@@ -211,35 +181,17 @@ function installUv() {
}); });
} }
// Verify installation if (!isUvInstalled()) {
if (isUvInstalled()) { throw new Error(
const version = getUvVersion(); 'uv installation completed but binary not found. ' +
console.error(`✅ uv ${version} installed successfully`); 'Please restart your terminal and try again.'
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');
} }
const version = getUvVersion();
console.error(`✅ uv ${version} installed successfully`);
} catch (error) { } catch (error) {
console.error('❌ Failed to install uv automatically'); console.error('❌ Failed to install uv');
console.error(' Please install manually:'); console.error(' Please install manually:');
if (IS_WINDOWS) { if (IS_WINDOWS) {
console.error(' - winget install astral-sh.uv'); console.error(' - winget install astral-sh.uv');
@@ -281,12 +233,7 @@ function installDeps() {
// Quote path for Windows paths with spaces // Quote path for Windows paths with spaces
const bunCmd = IS_WINDOWS && bunPath.includes(' ') ? `"${bunPath}"` : bunPath; const bunCmd = IS_WINDOWS && bunPath.includes(' ') ? `"${bunPath}"` : bunPath;
try { execSync(`${bunCmd} install`, { cwd: ROOT, stdio: 'inherit', shell: IS_WINDOWS });
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 });
}
// Write version marker // Write version marker
const pkg = JSON.parse(readFileSync(join(ROOT, 'package.json'), 'utf-8')); const pkg = JSON.parse(readFileSync(join(ROOT, 'package.json'), 'utf-8'));
@@ -300,31 +247,8 @@ function installDeps() {
// Main execution // Main execution
try { try {
// Step 1: Ensure Bun is installed (REQUIRED) if (!isBunInstalled()) installBun();
if (!isBunInstalled()) { if (!isUvInstalled()) installUv();
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 (needsInstall()) { if (needsInstall()) {
installDeps(); installDeps();
console.error('✅ Dependencies installed'); console.error('✅ Dependencies installed');