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 {
if (!fs.existsSync('Cargo.toml')) {
throw new Error('Cargo.toml not found');
}
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);
if (!fs.existsSync(targetDir)) {
fs.mkdirSync(targetDir, { recursive: true });
}
fs.copyFileSync(sourcePath, targetPath);
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;
}
}
function downloadBinary() {
const { target } = getPlatform();
const version = require('./package.json').version;
const pkg = require('./package.json');
const repoUrl = pkg.repository?.url || pkg.repository;
if (!repoUrl) {
throw new Error('Repository URL not found in package.json');
}
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);
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();
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 {
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 };