azion
Version:
Azion Packages for Edge Computing.
293 lines (252 loc) • 9.97 kB
JavaScript
import chalk from 'chalk';
import { execSync } from 'child_process';
import fs from 'fs';
import https from 'https';
import os from 'os';
import path from 'path';
import { fileURLToPath } from 'url';
const defaultVersion = '2.2.0';
const version = process.env.AZION_CLI_VERSION || defaultVersion;
const baseUrl = `https://github.com/aziontech/azion/releases/download/${version}`;
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
// Navigate up the directory tree to find the root directory of the installed library
let packageRoot = __dirname;
while (!fs.existsSync(path.join(packageRoot, 'package.json'))) {
const parentDir = path.dirname(packageRoot);
if (parentDir === packageRoot) {
throw new Error('Could not find the root directory of the library');
}
packageRoot = parentDir;
}
const binDir = path.join(packageRoot, 'bin');
const log = {
info: (msg) => console.log(chalk.blue('ℹ ') + msg),
success: (msg) => console.log(chalk.green('✔ ') + msg),
warning: (msg) => console.log(chalk.yellow('⚠ ') + msg),
error: (msg) => console.error(chalk.red('✖ ') + msg),
highlight: (msg) => console.log(chalk.hex('#FFA500')('🚀 ' + msg)),
url: (msg) => chalk.hex('#0000AA')(msg),
};
function getPlatform() {
const platform = os.platform();
const arch = os.arch();
if (platform === 'darwin') {
return { os: 'darwin', arch: arch === 'x64' ? 'amd64' : 'arm64', ext: 'tar.gz' };
} else if (platform === 'linux') {
return { os: 'linux', arch: arch === 'x64' ? 'amd64' : 'arm64', ext: 'tar.gz' };
} else if (platform === 'win32') {
return { os: 'windows', arch: 'amd64', ext: 'zip' };
} else {
throw new Error(`Unsupported platform: ${platform}`);
}
}
function downloadFile(url, dest) {
return new Promise((resolve, reject) => {
log.info(`Downloading from ${chalk.blackBright(url)}`);
https
.get(url, (response) => {
if (response.statusCode === 302) {
// Handle redirect
return downloadFile(response.headers.location, dest).then(resolve).catch(reject);
}
const file = fs.createWriteStream(dest);
response.pipe(file);
file.on('finish', () => {
file.close();
const fileSize = fs.statSync(dest).size;
log.success(`File downloaded: ${chalk.cyan(dest)}`);
log.info(`File size: ${chalk.yellow(fileSize)} bytes`);
if (fileSize === 0) {
reject(new Error('The downloaded file is empty'));
} else {
resolve();
}
});
})
.on('error', (err) => {
fs.unlink(dest, () => reject(err));
});
});
}
function listDirectoryContents(dir) {
const files = fs.readdirSync(dir);
log.info(`Directory contents ${chalk.cyan(dir)}:`);
files.forEach((file) => {
const filePath = path.join(dir, file);
const stats = fs.statSync(filePath);
console.log(
` ${chalk.cyan(file)} (${stats.isDirectory() ? 'directory' : 'file'}, ${chalk.yellow(stats.size)} bytes)`,
);
});
}
async function downloadAndExtract(platform) {
const fileName = `azion_${version}_${platform.os}_${platform.arch}.${platform.ext}`;
const url = `${baseUrl}/${fileName}`;
const filePath = path.join(binDir, fileName);
try {
await downloadFile(url, filePath);
log.info(`Extracting ${chalk.cyan(fileName)}...`);
log.info(`File path: ${chalk.cyan(filePath)}`);
log.info(`Destination directory: ${chalk.cyan(binDir)}`);
try {
if (platform.ext === 'tar.gz') {
log.info('Executing tar command...');
execSync(`tar -xzvf "${filePath}" -C "${binDir}"`, { stdio: 'inherit' });
} else if (platform.ext === 'zip') {
log.info('Executing unzip command...');
execSync(`unzip -o "${filePath}" -d "${binDir}"`, { stdio: 'inherit' });
}
} catch (error) {
log.error(`Error extracting file: ${error.message}`);
log.info('File contents:');
execSync(`file "${filePath}"`, { stdio: 'inherit' });
throw error;
}
log.success('Extraction completed. Verifying directory contents:');
listDirectoryContents(binDir);
fs.unlinkSync(filePath);
log.info(`Compressed file removed: ${chalk.cyan(filePath)}`);
// Find the extracted binary
const files = fs.readdirSync(binDir);
const extractedBinary = files.find((file) => file.startsWith('azion'));
if (!extractedBinary) {
log.error('Extracted binary not found. Directory contents:');
listDirectoryContents(binDir);
throw new Error('Extracted binary not found');
}
const extractedPath = path.join(binDir, extractedBinary);
const finalName = platform.os === 'windows' ? 'azion.exe' : 'azion';
const finalPath = path.join(binDir, finalName);
// Rename the extracted binary
fs.renameSync(extractedPath, finalPath);
log.success(`Binary renamed from ${chalk.cyan(extractedPath)} to ${chalk.cyan(finalPath)}`);
// Set execution permissions on Unix
if (platform.os !== 'windows') {
fs.chmodSync(finalPath, '755');
log.success(`Execution permissions set for ${chalk.cyan(finalPath)}`);
}
log.success(`Azion CLI installed at: ${chalk.cyan(finalPath)}`);
} catch (error) {
log.error(`Error during download or extraction: ${error.message}`);
if (fs.existsSync(filePath)) {
log.info(`Removing corrupted file: ${chalk.cyan(filePath)}`);
fs.unlinkSync(filePath);
}
throw error;
}
}
function checkExistingCliVersion() {
try {
const output = execSync('azion -v', { stdio: 'pipe' }).toString().trim();
const versionMatch = output.match(/v(\d+\.\d+\.\d+)/);
return versionMatch ? versionMatch[1] : null;
} catch (error) {
return null;
}
}
async function getLatestVersion() {
return new Promise((resolve, reject) => {
log.info('Fetching latest version from GitHub API...');
const options = {
hostname: 'api.github.com',
path: '/repos/aziontech/azion/releases/latest',
headers: {
'User-Agent': 'Azion-CLI-Installer',
},
};
https
.get(options, (response) => {
let data = '';
response.on('data', (chunk) => (data += chunk));
response.on('end', () => {
try {
const release = JSON.parse(data);
const version = release.tag_name.replace(/^v/, '');
if (/^\d+\.\d+\.\d+$/.test(version)) {
log.success(`Latest version found from API: ${version}`);
resolve(version);
} else {
log.warning(`Invalid version format from API: ${version}`);
log.info(`Using default version: ${defaultVersion}`);
resolve(defaultVersion);
}
} catch (err) {
log.warning(`Error processing API response: ${err.message}`);
log.info(`Using default version: ${defaultVersion}`);
resolve(defaultVersion);
}
});
})
.on('error', (err) => {
log.warning(`Could not fetch latest version: ${err.message}`);
log.info(`Using default version: ${defaultVersion}`);
resolve(defaultVersion);
});
});
}
async function main() {
try {
let selectedVersion;
if (process.env.AZION_CLI_VERSION) {
selectedVersion = process.env.AZION_CLI_VERSION;
log.info(`Using version from environment variable: ${selectedVersion}`);
} else {
selectedVersion = await getLatestVersion();
log.info(`Using latest version: ${selectedVersion}`);
}
// Manter a URL base original
const baseUrl = `https://github.com/aziontech/azion/releases/download/v${selectedVersion}`;
log.highlight(`Checking Azion CLI v${selectedVersion}`);
console.log();
const existingVersion = checkExistingCliVersion();
if (existingVersion) {
log.info(`Azion CLI is already installed (version ${existingVersion})`);
if (existingVersion === selectedVersion) {
log.success(`Azion CLI v${selectedVersion} is already installed and up to date.`);
process.exit(0);
} else {
log.info(
`Current version (${existingVersion}) differs from desired (${selectedVersion}). Proceeding with update...`,
);
}
}
const platform = getPlatform();
const finalName = platform.os === 'windows' ? 'azion.exe' : 'azion';
const finalPath = path.join(binDir, finalName);
if (fs.existsSync(finalPath)) {
log.info(`Azion CLI binary found at: ${chalk.cyan(finalPath)}`);
// Check current binary version
try {
const currentVersion = execSync(`"${finalPath}" -v`).toString().trim();
const versionMatch = currentVersion.match(/v(\d+\.\d+\.\d+)/);
if (versionMatch && versionMatch[1] === selectedVersion) {
log.success(`Azion CLI v${selectedVersion} is already installed and up to date.`);
process.exit(0);
} else {
log.info(
`Current version (${versionMatch ? versionMatch[1] : 'unknown'}) differs from desired (${selectedVersion}). Updating...`,
);
}
} catch (error) {
log.warning(`Unable to verify current version. Proceeding with installation.`);
}
}
if (!fs.existsSync(binDir)) {
fs.mkdirSync(binDir, { recursive: true, mode: 0o755 });
log.success(`Directory created: ${chalk.cyan(binDir)}`);
}
log.info(`Detected platform: ${chalk.cyan(JSON.stringify(platform))}`);
await downloadAndExtract(platform).catch((error) => {
log.error(`Error during download or extraction: ${error.message}`);
process.exit(0);
});
log.highlight('Installation completed successfully!');
log.info(`Azion CLI has been installed in: ${chalk.cyan(binDir)}`);
process.exit(0);
} catch (error) {
log.error(`Error during installation: ${error.message}`);
process.exit(1);
}
}
main();