ls-plus 0.0.1

Enhanced ls command with modern features - supports both cargo and npm installation
#!/usr/bin/env node

const fs = require('fs');
const path = require('path');
const https = require('https');
const { execSync } = require('child_process');

// 获取平台和架构信息
function getPlatform() {
  const platform = process.platform;
  const arch = process.arch;
  
  let target;
  if (platform === 'darwin') {
    if (arch === 'x64') {
      target = 'x86_64-apple-darwin';
    } else if (arch === 'arm64') {
      target = 'aarch64-apple-darwin';
    }
  } else if (platform === 'linux') {
    if (arch === 'x64') {
      target = 'x86_64-unknown-linux-gnu';
    } else if (arch === 'arm64') {
      target = 'aarch64-unknown-linux-gnu';
    }
  } else if (platform === 'win32') {
    if (arch === 'x64') {
      target = 'x86_64-pc-windows-msvc';
    }
  }
  
  if (!target) {
    console.error(`Unsupported platform: ${platform}-${arch}`);
    process.exit(1);
  }
  
  return { platform, arch, target };
}

// 构建本地二进制文件(开发模式)
function buildLocalBinary() {
  console.log('Building local Rust binary...');
  
  try {
    // 检查是否有 Cargo.toml
    if (!fs.existsSync('Cargo.toml')) {
      throw new Error('Cargo.toml not found');
    }
    
    // 构建 release 版本
    execSync('cargo build --release', { stdio: 'inherit' });
    
    const { platform } = getPlatform();
    const binaryName = platform === 'win32' ? 'ls-plus.exe' : 'ls-plus';
    const sourcePath = path.join('target', 'release', binaryName);
    const targetDir = path.join(__dirname, 'bin');
    const targetPath = path.join(targetDir, binaryName);
    
    // 创建 bin 目录
    if (!fs.existsSync(targetDir)) {
      fs.mkdirSync(targetDir, { recursive: true });
    }
    
    // 复制二进制文件
    fs.copyFileSync(sourcePath, targetPath);
    
    // 在 Unix 系统上设置执行权限
    if (platform !== 'win32') {
      fs.chmodSync(targetPath, '755');
    }
    
    console.log(`Binary built and copied to ${targetPath}`);
    return true;
  } catch (error) {
    console.error('Failed to build local binary:', error.message);
    return false;
  }
}

// 从 GitHub releases 下载二进制文件(生产模式)
function downloadBinary() {
  const { target } = getPlatform();
  const version = require('./package.json').version;
  
  // 从 package.json 中获取仓库 URL,更加灵活
  const pkg = require('./package.json');
  const repoUrl = pkg.repository?.url || pkg.repository;
  
  if (!repoUrl) {
    throw new Error('Repository URL not found in package.json');
  }
  
  // 解析 GitHub 仓库 URL
  const match = repoUrl.match(/github\.com[\/:]([^\/]+)\/([^\/\.]+)/);
  if (!match) {
    throw new Error('Invalid GitHub repository URL format');
  }
  
  const [, owner, repo] = match;
  const baseUrl = `https://github.com/${owner}/${repo}/releases/download`;
  const binaryName = target.includes('windows') ? 'ls-plus.exe' : 'ls-plus';
  const downloadUrl = `${baseUrl}/v${version}/ls-plus-${target}`;
  
  console.log(`Downloading binary from ${downloadUrl}...`);
  
  return new Promise((resolve, reject) => {
    const targetDir = path.join(__dirname, 'bin');
    const targetPath = path.join(targetDir, binaryName);
    
    // 创建 bin 目录
    if (!fs.existsSync(targetDir)) {
      fs.mkdirSync(targetDir, { recursive: true });
    }
    
    const file = fs.createWriteStream(targetPath);
    
    https.get(downloadUrl, (response) => {
      if (response.statusCode === 200) {
        response.pipe(file);
        file.on('finish', () => {
          file.close();
          // 在 Unix 系统上设置执行权限
          if (!target.includes('windows')) {
            fs.chmodSync(targetPath, '755');
          }
          console.log(`Binary downloaded to ${targetPath}`);
          resolve();
        });
      } else {
        reject(new Error(`Download failed with status ${response.statusCode}`));
      }
    }).on('error', reject);
  });
}

// 主安装逻辑
async function install() {
  console.log('🚀 Installing ls-plus...');
  
  try {
    // 检查是否在开发环境(存在 Cargo.toml)
    const isDevEnv = fs.existsSync(path.join(__dirname, 'Cargo.toml'));
    
    if (isDevEnv) {
      console.log('📦 Development environment detected, attempting local build...');
      if (buildLocalBinary()) {
        console.log('✅ Installation completed using local build.');
        return;
      }
      console.log('⚠️  Local build failed, falling back to prebuilt binary...');
    } else {
      console.log('📥 Production install, downloading prebuilt binary...');
    }
    
    // 如果本地构建失败或不在开发环境,尝试下载预构建的二进制文件
    await downloadBinary();
    console.log('✅ Installation completed using downloaded binary.');
  } catch (error) {
    console.error('❌ Installation failed:', error.message);
    
    // 提供更具体的错误指导
    if (error.message.includes('Repository URL')) {
      console.error('💡 Please ensure the repository field is properly configured in package.json');
    } else if (error.message.includes('Download failed')) {
      console.error('💡 Please check your internet connection and ensure the release exists on GitHub');
    } else if (error.message.includes('Cargo.toml')) {
      console.error('💡 For development: Please ensure Rust is installed (https://rustup.rs/)');
    }
    
    console.error('\n🔧 Troubleshooting:');
    console.error('   1. Check your internet connection');
    console.error('   2. Verify GitHub releases exist for this version');
    console.error('   3. For development, install Rust: https://rustup.rs/');
    process.exit(1);
  }
}

// 只在直接运行时执行安装
if (require.main === module) {
  install();
}

module.exports = { install };