buckshotplusplus
Version:
BuckshotPlusPlus - A simple and efficient web development language
134 lines (116 loc) • 4.07 kB
JavaScript
const fs = require('fs');
const path = require('path');
const os = require('os');
const https = require('https');
const StreamZip = require('node-stream-zip');
const platform = os.platform();
const arch = os.arch();
const version = process.env.npm_package_version;
const getBinaryInfo = () => {
const platformMap = {
'win32-x64': 'windows-x64',
'win32-arm64': 'windows-arm64',
'linux-x64': 'linux-x64',
'linux-arm64': 'linux-arm64',
'darwin-x64': 'macos-x64',
'darwin-arm64': 'macos-arm64'
};
const platformKey = `${platform}-${arch}`;
const assetName = platformMap[platformKey];
if (!assetName) {
throw new Error(`Unsupported platform: ${platformKey}`);
}
return {
url: `https://github.com/BuckshotPlusPlus/BuckshotPlusPlus/releases/download/v${version}/${assetName}.zip`,
binaryName: platform === 'win32' ? 'BuckshotPlusPlus.exe' : 'BuckshotPlusPlus'
};
};
const downloadWithRetry = (url, destPath, retries = 3) => {
return new Promise((resolve, reject) => {
const tryDownload = (attemptsLeft) => {
const file = fs.createWriteStream(destPath);
https.get(url, (response) => {
if (response.statusCode === 302 || response.statusCode === 301) {
// Handle redirect
https.get(response.headers.location, (redirectedResponse) => {
if (redirectedResponse.statusCode !== 200) {
if (attemptsLeft > 0) {
console.log(`Retrying download... ${attemptsLeft} attempts left`);
tryDownload(attemptsLeft - 1);
} else {
reject(new Error(`Failed to download after ${retries} attempts`));
}
return;
}
redirectedResponse.pipe(file);
file.on('finish', () => {
file.close();
resolve();
});
}).on('error', (err) => {
if (attemptsLeft > 0) {
console.log(`Retrying download... ${attemptsLeft} attempts left`);
tryDownload(attemptsLeft - 1);
} else {
reject(err);
}
});
} else if (response.statusCode !== 200) {
if (attemptsLeft > 0) {
console.log(`Retrying download... ${attemptsLeft} attempts left`);
tryDownload(attemptsLeft - 1);
} else {
reject(new Error(`Failed to download: ${response.statusCode}`));
}
return;
} else {
response.pipe(file);
file.on('finish', () => {
file.close();
resolve();
});
}
}).on('error', (err) => {
if (attemptsLeft > 0) {
console.log(`Retrying download... ${attemptsLeft} attempts left`);
tryDownload(attemptsLeft - 1);
} else {
reject(err);
}
});
};
tryDownload(retries);
});
};
const extractZip = async (zipPath, destDir) => {
const zip = new StreamZip.async({ file: zipPath });
await zip.extract(null, destDir);
await zip.close();
};
const main = async () => {
try {
const { url, binaryName } = getBinaryInfo();
const binaryDir = path.join(__dirname, '..', 'lib', 'binaries', `${platform}-${arch}`);
const zipPath = path.join(binaryDir, 'temp.zip');
// Create directories
fs.mkdirSync(binaryDir, { recursive: true });
// Download and extract binary
console.log(`Downloading binary from GitHub releases: ${url}`);
await downloadWithRetry(url, zipPath);
console.log('Extracting binary...');
await extractZip(zipPath, binaryDir);
// Cleanup
fs.unlinkSync(zipPath);
// Set executable permissions on Unix-like systems
if (platform !== 'win32') {
const binaryPath = path.join(binaryDir, binaryName);
fs.chmodSync(binaryPath, '755');
console.log('Set executable permissions');
}
console.log('Installation completed successfully');
} catch (error) {
console.error('Installation failed:', error);
process.exit(1);
}
};
main();