atlas-app-services-cli
Version:
The Atlas App Services Command Line Interface
160 lines (132 loc) • 4.39 kB
JavaScript
;
import axios from 'axios';
import decompress from '@xhmikosr/decompress';
import fs from 'fs';
import path from 'path';
const KILOBYTE = 1024;
const MAX_BYTES_READ = 800000;
const manifestURL =
'https://downloads.mongodb.com/app-services-cli/versions/cloud-prod/MANIFEST';
function fetchManifest() {
return axios(manifestURL)
.then(function (res) { return res.data; });
}
function getDownloadURL(manifest) {
const pastReleases = manifest.past_releases || [];
let tag = '';
switch(process.platform) {
case 'linux':
if (process.arch !== 'x64' && process.arch !== 'arm64') {
throw new Error('Only Linux 64 bits supported.');
}
if (process.arch === 'x64') {
tag = 'linux-amd64';
} else if (process.arch === 'arm64') {
tag = 'linux-arm64';
}
break;
case 'darwin':
case 'freebsd':
if (process.arch !== 'x64' && process.arch !== 'arm64') {
throw new Error('Only Mac 64 bits supported.');
}
if (process.arch === 'x64') {
tag = 'darwin-amd64';
} else if (process.arch === 'arm64') {
tag = 'darwin-arm64';
}
break;
case 'win32':
if (process.arch !== 'x64') {
throw new Error('Only Windows 64 bits supported.');
}
tag = 'windows-amd64';
break;
default:
throw new Error(`Unexpected platform or architecture: ${process.platform} ${process.arch}`);
}
const packageMetadata = JSON.parse(fs.readFileSync('./package.json'))
if (manifest.version !== packageMetadata.version) {
const matchingPastRelease = pastReleases.find((pastRelease) => pastRelease.version === packageMetadata.version);
if (matchingPastRelease) return matchingPastRelease.info[tag].url;
}
return manifest.info[tag].url;
}
function requestArchive(downloadURL) {
console.log(`downloading appservices cli archive from "${downloadURL}"`);
const archiveName = downloadURL.split("/").pop()
return new Promise(function (resolve, reject) {
let count = 0;
let notifiedCount = 0;
const filePath = path.join(process.cwd(), archiveName);
const outFile = fs.openSync(filePath, 'w');
axios.get(downloadURL, { responseType: 'stream' })
.then(function (res) { return res.data; })
.then(function (stream) {
stream.on('error', function (err) {
reject(new Error(`Error with http(s) request: ${err}`));
});
stream.on('data', function (data) {
fs.writeSync(outFile, data, 0, data.length, null);
count += data.length;
if (count - notifiedCount > MAX_BYTES_READ) {
process.stdout.write(`Received ${Math.floor(count / KILOBYTE)} K...\r`);
notifiedCount = count;
}
});
stream.on('end', function () {
console.log(`Received ${Math.floor(count / KILOBYTE)} K total.`);
fs.closeSync(outFile);
fixFilePermissions(filePath);
resolve(archiveName);
});
})
.catch(reject);
});
}
const unzip = (path) => {
return decompress(path, ".", {
map: file => {
// remove wrapping directory to write contents of zip in cwd
file.path = file.path.split('/').slice(1).join('/')
return file
}
})
}
const untar = (path) => {
return decompress(path, ".", {
map: file => {
// remove wrapping directory to write contents of tar in cwd
file.path = file.path.split('/').slice(1).join('/')
return file
}
})
}
function decompressArchive(filepath) {
if (filepath.slice(-3) === "zip") {
return unzip(filepath)
}
if (filepath.slice(-6) === "tar.gz") {
return untar(filepath)
}
throw new Error(`could not decompress archive: unexpected archive type for file: ${filepath}`)
}
function fixFilePermissions(filePath) {
// Check that the binary is user-executable and fix it if it isn't
if (process.platform !== 'win32') {
const stat = fs.statSync(filePath);
// 64 == 0100 (no octal literal in strict mode)
// eslint-disable-next-line no-bitwise
if (!(stat.mode & 64)) {
fs.chmodSync(filePath, '755');
}
}
}
fetchManifest()
.then(getDownloadURL)
.then(requestArchive)
.then(decompressArchive)
.catch(function (err) {
console.error('failed to download Atlas App Services CLI:', err);
process.exit(1);
});