mrapids 0.1.31

Your OpenAPI, but executable
Documentation
#!/usr/bin/env node

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

const VERSION = '0.1.27';
const RELEASES_BASE_URL = 'https://github.com/microrapids/mrapids-releases/releases/download';

function getBinaryName() {
  const platform = os.platform();
  const arch = os.arch();
  
  if (platform === 'darwin') {
    return arch === 'arm64' ? 'mrapids-macos-arm64' : 'mrapids-macos-x64';
  } else if (platform === 'linux') {
    return 'mrapids-linux-x64';
  } else if (platform === 'win32') {
    return 'mrapids-windows-x64.exe';
  }
  
  throw new Error(`Unsupported platform: ${platform}-${arch}`);
}

function getBinaryPath() {
  const binaryName = getBinaryName();
  const binDir = path.join(__dirname, '..', 'bin');
  return path.join(binDir, binaryName);
}

async function downloadBinary() {
  const binaryName = getBinaryName();
  const binaryPath = getBinaryPath();
  
  // Check if binary already exists
  if (fs.existsSync(binaryPath)) {
    return binaryPath;
  }
  
  console.log(`Downloading mrapids v${VERSION} for ${os.platform()}-${os.arch()}...`);
  
  const isWindows = os.platform() === 'win32';
  const archiveName = isWindows ? `${binaryName}.zip` : `${binaryName}.tar.gz`;
  const downloadUrl = `${RELEASES_BASE_URL}/v${VERSION}/${archiveName}`;
  
  const binDir = path.dirname(binaryPath);
  if (!fs.existsSync(binDir)) {
    fs.mkdirSync(binDir, { recursive: true });
  }
  
  // Download archive
  const archivePath = path.join(binDir, archiveName);
  await downloadFile(downloadUrl, archivePath);
  
  // Extract archive
  console.log('Extracting binary...');
  if (isWindows) {
    // Use PowerShell to extract ZIP on Windows
    const extractCmd = `Expand-Archive -Path "${archivePath}" -DestinationPath "${binDir}" -Force`;
    require('child_process').execSync(extractCmd, { shell: 'powershell.exe' });
  } else {
    // Use tar for Unix systems
    require('child_process').execSync(`tar -xzf "${archivePath}" -C "${binDir}"`, { stdio: 'inherit' });
  }
  
  // Clean up archive
  fs.unlinkSync(archivePath);
  
  // Make binary executable (Unix only)
  if (os.platform() !== 'win32') {
    fs.chmodSync(binaryPath, 0o755);
  }
  
  console.log(`Successfully installed mrapids v${VERSION}`);
  return binaryPath;
}

function downloadFile(url, dest) {
  return new Promise((resolve, reject) => {
    const file = fs.createWriteStream(dest);
    
    const request = https.get(url, (response) => {
      // Handle redirects
      if (response.statusCode === 302 || response.statusCode === 301) {
        https.get(response.headers.location, (redirectResponse) => {
          redirectResponse.pipe(file);
          file.on('finish', () => {
            file.close(resolve);
          });
        }).on('error', reject);
      } else if (response.statusCode === 200) {
        response.pipe(file);
        file.on('finish', () => {
          file.close(resolve);
        });
      } else {
        reject(new Error(`Failed to download: ${response.statusCode}`));
      }
    });
    
    request.on('error', reject);
  });
}

async function main() {
  try {
    const binaryPath = await downloadBinary();
    
    // Run the binary with all arguments
    const args = process.argv.slice(2);
    const child = spawn(binaryPath, args, {
      stdio: 'inherit',
      shell: false
    });
    
    child.on('exit', (code) => {
      process.exit(code);
    });
    
    child.on('error', (err) => {
      console.error('Failed to run mrapids:', err.message);
      process.exit(1);
    });
  } catch (error) {
    console.error('Error:', error.message);
    process.exit(1);
  }
}

main();