Demo for query storing
Change-Id: I947bcac841992c3f6cfd01ab337c265b0d01cb70
diff --git a/node_modules/bin-wrapper/index.js b/node_modules/bin-wrapper/index.js
new file mode 100644
index 0000000..1aba001
--- /dev/null
+++ b/node_modules/bin-wrapper/index.js
@@ -0,0 +1,208 @@
+'use strict';
+const fs = require('fs');
+const path = require('path');
+const url = require('url');
+const pify = require('pify');
+const importLazy = require('import-lazy')(require);
+
+const binCheck = importLazy('bin-check');
+const binVersionCheck = importLazy('bin-version-check');
+const download = importLazy('download');
+const osFilterObj = importLazy('os-filter-obj');
+
+const statAsync = pify(fs.stat);
+const chmodAsync = pify(fs.chmod);
+
+/**
+ * Initialize a new `BinWrapper`
+ *
+ * @param {Object} options
+ * @api public
+ */
+module.exports = class BinWrapper {
+ constructor(options = {}) {
+ this.options = options;
+
+ if (this.options.strip <= 0) {
+ this.options.strip = 0;
+ } else if (!this.options.strip) {
+ this.options.strip = 1;
+ }
+ }
+
+ /**
+ * Get or set files to download
+ *
+ * @param {String} src
+ * @param {String} os
+ * @param {String} arch
+ * @api public
+ */
+ src(src, os, arch) {
+ if (arguments.length === 0) {
+ return this._src;
+ }
+
+ this._src = this._src || [];
+ this._src.push({
+ url: src,
+ os,
+ arch
+ });
+
+ return this;
+ }
+
+ /**
+ * Get or set the destination
+ *
+ * @param {String} dest
+ * @api public
+ */
+ dest(dest) {
+ if (arguments.length === 0) {
+ return this._dest;
+ }
+
+ this._dest = dest;
+ return this;
+ }
+
+ /**
+ * Get or set the binary
+ *
+ * @param {String} bin
+ * @api public
+ */
+ use(bin) {
+ if (arguments.length === 0) {
+ return this._use;
+ }
+
+ this._use = bin;
+ return this;
+ }
+
+ /**
+ * Get or set a semver range to test the binary against
+ *
+ * @param {String} range
+ * @api public
+ */
+ version(range) {
+ if (arguments.length === 0) {
+ return this._version;
+ }
+
+ this._version = range;
+ return this;
+ }
+
+ /**
+ * Get path to the binary
+ *
+ * @api public
+ */
+ path() {
+ return path.join(this.dest(), this.use());
+ }
+
+ /**
+ * Run
+ *
+ * @param {Array} cmd
+ * @api public
+ */
+ run(cmd = ['--version']) {
+ return this.findExisting().then(() => {
+ if (this.options.skipCheck) {
+ return;
+ }
+
+ return this.runCheck(cmd);
+ });
+ }
+
+ /**
+ * Run binary check
+ *
+ * @param {Array} cmd
+ * @api private
+ */
+ runCheck(cmd) {
+ return binCheck(this.path(), cmd).then(works => {
+ if (!works) {
+ throw new Error(`The \`${this.path()}\` binary doesn't seem to work correctly`);
+ }
+
+ if (this.version()) {
+ return binVersionCheck(this.path(), this.version());
+ }
+
+ return Promise.resolve();
+ });
+ }
+
+ /**
+ * Find existing files
+ *
+ * @api private
+ */
+ findExisting() {
+ return statAsync(this.path()).catch(error => {
+ if (error && error.code === 'ENOENT') {
+ return this.download();
+ }
+
+ return Promise.reject(error);
+ });
+ }
+
+ /**
+ * Download files
+ *
+ * @api private
+ */
+ download() {
+ const files = osFilterObj(this.src() || []);
+ const urls = [];
+
+ if (files.length === 0) {
+ return Promise.reject(new Error('No binary found matching your system. It\'s probably not supported.'));
+ }
+
+ files.forEach(file => urls.push(file.url));
+
+ return Promise.all(urls.map(url => download(url, this.dest(), {
+ extract: true,
+ strip: this.options.strip
+ }))).then(result => {
+ const resultingFiles = flatten(result.map((item, index) => {
+ if (Array.isArray(item)) {
+ return item.map(file => file.path);
+ }
+
+ const parsedUrl = url.parse(files[index].url);
+ const parsedPath = path.parse(parsedUrl.pathname);
+
+ return parsedPath.base;
+ }));
+
+ return Promise.all(resultingFiles.map(fileName => {
+ return chmodAsync(path.join(this.dest(), fileName), 0o755);
+ }));
+ });
+ }
+};
+
+function flatten(arr) {
+ return arr.reduce((acc, elem) => {
+ if (Array.isArray(elem)) {
+ acc.push(...elem);
+ } else {
+ acc.push(elem);
+ }
+
+ return acc;
+ }, []);
+}