unjar-from-url
Version:
Downloads JAR files from urls and unzipps them right away from your package.json Edit
231 lines (196 loc) • 7.75 kB
JavaScript
;
/**
* Downloads a list of jar files, and unzippes them inside the node_modules directory.
* @return {boolean} result when download was ok
* @author Emre Avsar <emre.avsar92@gmail.com>
*/
module.exports = function () {
var unjarConfigFromPackageJsonFile = getUnjarConfigurationFromPackageJson(module);
// var unjarConfigFromArguments = getUnjarConfigurationFromArguments(args);
var unjarConfigFromArguments = getUnjarConfigurationFromArgs();
// put both configurations together:
var unjarConfig = unjarConfigFromArguments.concat(unjarConfigFromPackageJsonFile);
for (var i = 0; i < unjarConfig.length; i++) {
downloadJar(unjarConfig[i]['nodeModulesDir'], unjarConfig[i]['directory'], unjarConfig[i]['url']);
}
return
};
/**
* Finds the configuration passed by command line arguments.
*
* CLI args are limited, thus one have to pass the following CLI arguments:
* --urls = list of urls to download the jars from
* --download-dirs = names of the directories to put the jars into (uncompress jar into this directory)
* --destination-dirs = names of the directories where the directory (download-dirs) will be
*
* Example for usage with command line args:
* <pre><code>
* --urls http://selenium-release.storage.googleapis.com/2.43/selenium-server-standalone-2.43.1.jar
* --download-dirs selenium-server-standalone
* --destination-dirs=/data
* --urls http://otherurl.com/file.jar
* --download-dirs otherurl-directory
* --destination-dirs=/tmp
* </pre></code>
*
* This would download the selenium server standalone 2.4.32.1 jar into /data/selenium-server-standalone/ and uncompress the jar there
* and file.jar downloaded from http://otherurl.com/file.jar into /tmp/otherurl-directory/ and uncompress the jar there
*
* Important: the order does matter (first urls argument matches to first download-dirs and destination-dirs etc.)
*/
var getUnjarConfigurationFromArgs = function () {
// looking for keys passed as cli arguments with urls and download-dirs
const urlsKey = "urls";
const downloadDirsKey = "download-dirs";
const destinationDir = "destination-dirs";
// keys used in the array (same as in configuration via package.json) for each item (so urls => url)
const confUrlsKey = "url";
const confDownloadDirsKey = "directory";
const confDestinationDir = "nodeModulesDir";
// getting cli arguments
var argv = require('minimist')(process.argv.slice(2));
var unjarConfigFromArguments = [];
if (argv[urlsKey] != null) {
// only 1 object passed
if (typeof argv[urlsKey] === 'string') {
// put into an array, so as it can be used the same way as multiple args
argv[urlsKey] = [argv[urlsKey]];
argv[downloadDirsKey] = [argv[downloadDirsKey]];
argv[destinationDir] = [argv[destinationDir]];
}
// put them together so that the array has a object with the attributes: nodeModulesDir, directory, url
for (var i = 0; i < argv[urlsKey].length; i++) {
var configItem = {};
configItem[confUrlsKey] = argv[urlsKey][i];
configItem[confDownloadDirsKey] = argv[downloadDirsKey][i];
configItem[confDestinationDir] = argv[destinationDir][i];
unjarConfigFromArguments.push(configItem);
}
}
return unjarConfigFromArguments;
}
/**
* Searches the unjar configuration inside the highest parent's package.json. This is typically used when this module is used inside another project
* which has the configuration inside the package.json of the project itself.
*
* Returns unjar configuration as a js object.
*
* Example for configuration:
* <pre><code>
* // package.json of your project
* ...
* unjar-config: [
* {
* "directory": "selenium-server-standalone",
* "url": "http://selenium-release.storage.googleapis.com/2.43/selenium-server-standalone-2.43.1.jar"
* },
* {
* // other jars
* }
* ]
* </pre></code>
*
* @param {module} module to start searching the configuration file
*/
var getUnjarConfigurationFromPackageJson = function (module) {
const configKey = 'unjar-from-url-config';
if (module == null) {
return [];
}
var highestParent;
if (module.parent != null) {
highestParent = module.parent;
} else {
highestParent = module;
}
var parentFound = false;
// iterate up to all parents, until parent is undefined => root of all
while (!parentFound) {
parentFound = highestParent.parent == undefined || highestParent.parent == null;
// go to upper parent
if (!parentFound) {
highestParent = highestParent.parent;
}
}
// get the path to project itself (where the package.json is)
var pathToNodeModules = highestParent.paths[0].split("node_modules")[0];
// read the package json
var packageJson = require(pathToNodeModules + "package.json");
var unjarFromUrlConfig;
if (packageJson != null && packageJson[configKey] != null) {
unjarFromUrlConfig = packageJson[configKey];
}
if (unjarFromUrlConfig != null) {
// add the highest parent path (used as nodeModulesDir later) to each item
var nodeModulesDir = highestParent.paths != null ? highestParent.paths[0] : '';
unjarFromUrlConfig.forEach(function (item) {
item.nodeModulesDir = nodeModulesDir
});
} else {
console.warn("No config found in package.json: ", pathToNodeModules + "package.json");
unjarFromUrlConfig = [];
}
return unjarFromUrlConfig;
}
/**
* Downloads and uncompresses a jar from given url into node_modules directory.
* @param {string} nodeModulesDir absolute path to node_modules directory where a directory gets created where the jar gets uncompressed
* @param {string} unzipDirectory name of the directory where the jar file gets uncompressed in
* @param {string} url to jar to download
*/
var downloadJar = function (nodeModulesDir, unzipDirectory, url) {
const download = require('download');
const fs = require('fs');
const zlib = require('zlib');
var exec = require('child_process').exec,
child;
var path = require("path");
// extracting filename from url
var filename = path.basename(url);
var fileDirectory = nodeModulesDir + "/" + unzipDirectory;
console.log("nodeModules directory = ", nodeModulesDir);
console.log("downloading file from url=", url);
console.log("unzipping to directory=", unzipDirectory);
console.log("fileDriectory=", fileDirectory);
console.log("filename = ", filename);
// makes programming easier (create the directory anyway)
if (!fs.existsSync(fileDirectory)) {
// mkdir -p fileDirectory
fileDirectory.split('/').forEach((dir, index, splits) => {
const parent = splits.slice(0, index).join('/');
const dirPath = path.resolve(parent, dir);
if (!fs.existsSync(dirPath)) {
fs.mkdirSync(dirPath);
}
});
}
// delete directory with file in it, and after that download the file into newly created folder
exec('rm -r ' + fileDirectory, function (err, stdout, stderr) {
fs.mkdirSync(fileDirectory);
// fs.writeFileSync(fileDirectory + "/download.jar", content);
// download process
download(url, fileDirectory).then(() => {
console.log("downloaded file successful. unzipping...");
var DecompressZip = require('decompress-zip');
console.log("file to decompress: " + fileDirectory + "/" + filename);
var unzipper = new DecompressZip(fileDirectory + "/" + filename);
unzipper.on('error', function (err) {
console.log('Caught an error', err);
});
unzipper.on('extract', function (log) {
console.log('Finished extracting');
});
unzipper.on('progress', function (fileIndex, fileCount) {
console.log('Extracted file ' + (fileIndex + 1) + ' of ' + fileCount);
});
unzipper.extract({
path: fileDirectory,
filter: function (file) {
return file.type !== "SymbolicLink";
}
});
});
});
};
module.exports()