diff --git a/Jenkinsfile b/Jenkinsfile index 44df8f9c..88583ac5 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -3,19 +3,31 @@ pipeline { stages { stage('Install') { steps { - sh 'curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.11/install.sh | bash' - sh 'chmod +x "$HOME/.nvm/nvm.sh"' - sh '$HOME/.nvm/nvm.sh install 8' - sh 'npm install' - sh 'npm prune' + script { + try { + sh 'curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.11/install.sh | bash' + sh 'chmod +x "$HOME/.nvm/nvm.sh"' + sh '$HOME/.nvm/nvm.sh install 8' + sh 'npm install' + sh 'npm prune' + } catch (e) { + echo e + } + } } } stage('Build') { steps { - sh 'npm run dist:linux:deb' - sh 'npm run dist:linux:appimage' - sh 'npm run dist:linux:snap' - sh 'mv ./*.snap ./dist/.' + script { + try { + sh 'npm run dist:linux:deb' + sh 'npm run dist:linux:appimage' + sh 'npm run dist:linux:snap' + sh 'mv ./*.snap ./dist/.' + } catch (e) { + echo e + } + } } } } diff --git a/build.js b/build.js index 8b74a8c2..baf25a7b 100755 --- a/build.js +++ b/build.js @@ -12,10 +12,10 @@ Author: Marius Gripsgard const builder = require("electron-builder") const cli = require("commander"); -const utils = require("./src/utils"); const unzip = require("unzipper"); const path = require("path"); const fs = require("fs-extra"); +const download = require('download'); const events = require("events"); class event extends events {} const Platform = builder.Platform @@ -142,8 +142,12 @@ switch (cli.package) { case "": break; default: - console.log("Building " + cli.package + " is not configured!"); - process.exit(1); + if (!cli.downloadOnly) { + console.log("Building " + cli.package + " is not configured!"); + process.exit(1); + } else { + break; + } } var build = () => { @@ -175,31 +179,16 @@ var build = () => { // Download platform tools if (cli.platformTools) { - const downloadEvent = new event(); - utils.downloadFiles(getAndroidPlatformTools(), downloadEvent); - downloadEvent.on("download:done", () => { + download(getAndroidPlatformTools()[0].url,getAndroidPlatformTools()[0].path).then(() => { + console.log('files downloaded!'); extractPlatformTools(getAndroidPlatformTools(), () => { console.log("Platform tools downloaded successfully!"); if (!cli.downloadOnly) build(); }); - }); - downloadEvent.on("download:error", (r) => { - console.log("Download error " + r); + }).catch(() => { + console.error("Failed to download files!") process.exit(1); }); - downloadEvent.on("error", (r) => { - console.log("Error: " + r); - process.exit(1); - }); - downloadEvent.on("download:start", (r) => { - console.log("Starting download of " + r + " files"); - }); - downloadEvent.on("download:next", (i) => { - console.log(`Downloading next file, ${i} left`); - }); - downloadEvent.on("download:progress", (i) => { - process.stdout.write(`Downloading file, ${Math.ceil(i.percent*100)}% complete\r`); - }); } else { build(); } diff --git a/buildconfig-generic.json b/buildconfig-generic.json index 6cd44d8a..90323d2c 100644 --- a/buildconfig-generic.json +++ b/buildconfig-generic.json @@ -1,7 +1,7 @@ { "appId": "com.ubports.installer", "productName": "ubports-installer", - "copyright": "Copyright © year UBports Foundation", + "copyright": "Copyright © 2017-2019 UBports Foundation", "publish": [], "files": [ "src/**/*", diff --git a/package-lock.json b/package-lock.json index d6343016..5208f11c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "ubports-installer", - "version": "0.2.7-beta", + "version": "0.3.2-beta", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -10,6 +10,131 @@ "integrity": "sha512-AsnBZN3a8/JcNt+KPkGGODaA4c7l3W5+WpeKgGSbstSLxqWtTXqd1ieJGBQ8IFCtRg8DmmKUcSkIkUc0A4p3YA==", "dev": true }, + "@babel/code-frame": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz", + "integrity": "sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==", + "requires": { + "@babel/highlight": "^7.0.0" + } + }, + "@babel/generator": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.6.2.tgz", + "integrity": "sha512-j8iHaIW4gGPnViaIHI7e9t/Hl8qLjERI6DcV9kEpAIDJsAOrcnXqRS7t+QbhL76pwbtqP+QCQLL0z1CyVmtjjQ==", + "requires": { + "@babel/types": "^7.6.0", + "jsesc": "^2.5.1", + "lodash": "^4.17.13", + "source-map": "^0.5.0" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + } + } + }, + "@babel/helper-function-name": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz", + "integrity": "sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw==", + "requires": { + "@babel/helper-get-function-arity": "^7.0.0", + "@babel/template": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz", + "integrity": "sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ==", + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.4.tgz", + "integrity": "sha512-Ro/XkzLf3JFITkW6b+hNxzZ1n5OQ80NvIUdmHspih1XAhtN3vPTuUFT4eQnela+2MaZ5ulH+iyP513KJrxbN7Q==", + "requires": { + "@babel/types": "^7.4.4" + } + }, + "@babel/highlight": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.5.0.tgz", + "integrity": "sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ==", + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.6.2.tgz", + "integrity": "sha512-mdFqWrSPCmikBoaBYMuBulzTIKuXVPtEISFbRRVNwMWpCms/hmE2kRq0bblUHaNRKrjRlmVbx1sDHmjmRgD2Xg==" + }, + "@babel/template": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.6.0.tgz", + "integrity": "sha512-5AEH2EXD8euCk446b7edmgFdub/qfH1SN6Nii3+fyXP807QRx9Q73A2N5hNwRRslC2H9sNzaFhsPubkS4L8oNQ==", + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/parser": "^7.6.0", + "@babel/types": "^7.6.0" + } + }, + "@babel/traverse": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.6.2.tgz", + "integrity": "sha512-8fRE76xNwNttVEF2TwxJDGBLWthUkHWSldmfuBzVRmEDWOtu4XdINTgN7TDWzuLg4bbeIMLvfMFD9we5YcWkRQ==", + "requires": { + "@babel/code-frame": "^7.5.5", + "@babel/generator": "^7.6.2", + "@babel/helper-function-name": "^7.1.0", + "@babel/helper-split-export-declaration": "^7.4.4", + "@babel/parser": "^7.6.2", + "@babel/types": "^7.6.0", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.13" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, + "@babel/types": { + "version": "7.6.1", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.6.1.tgz", + "integrity": "sha512-X7gdiuaCmA0uRjCmRtYJNAVCc/q+5xSgsfKJHqMN4iNLILX39677fJE1O40arPMh0TTtS9ItH67yre6c7k6t0g==", + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + }, + "dependencies": { + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=" + } + } + }, "@sindresorhus/is": { "version": "0.14.0", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", @@ -182,18 +307,6 @@ } } }, - "ansi-colors": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz", - "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==", - "dev": true - }, - "ansi-escapes": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", - "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", - "dev": true - }, "ansi-regex": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", @@ -204,7 +317,6 @@ "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, "requires": { "color-convert": "^1.9.0" } @@ -270,128 +382,34 @@ } } }, - "archiver": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/archiver/-/archiver-2.1.1.tgz", - "integrity": "sha1-/2YrSnggFJSj7lRNOjP+dJZQnrw=", - "dev": true, + "append-transform": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-1.0.0.tgz", + "integrity": "sha512-P009oYkeHyU742iSZJzZZywj4QRJdnTWffaKuJQLablCZ1uz6/cW4yaRgcDaoQ+uwOxxnt0gRUcwfsNP2ri0gw==", "requires": { - "archiver-utils": "^1.3.0", - "async": "^2.0.0", - "buffer-crc32": "^0.2.1", - "glob": "^7.0.0", - "lodash": "^4.8.0", - "readable-stream": "^2.0.0", - "tar-stream": "^1.5.0", - "zip-stream": "^1.2.0" - }, - "dependencies": { - "glob": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", - "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "readable-stream": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } + "default-require-extensions": "^2.0.0" } }, - "archiver-utils": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-1.3.0.tgz", - "integrity": "sha1-5QtMCccL89aA4y/xt5lOn52JUXQ=", - "dev": true, + "archive-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/archive-type/-/archive-type-4.0.0.tgz", + "integrity": "sha1-+S5yIzBW38aWlHJ0nCZ72wRrHXA=", "requires": { - "glob": "^7.0.0", - "graceful-fs": "^4.1.0", - "lazystream": "^1.0.0", - "lodash": "^4.8.0", - "normalize-path": "^2.0.0", - "readable-stream": "^2.0.0" + "file-type": "^4.2.0" }, "dependencies": { - "glob": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", - "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "readable-stream": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } + "file-type": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-4.4.0.tgz", + "integrity": "sha1-G2AOX8ofvcboDApwxxyNul95BsU=" } } }, + "archy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", + "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=" + }, "argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", @@ -493,12 +511,6 @@ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" }, - "atob": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", - "dev": true - }, "author-regex": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/author-regex/-/author-regex-1.0.0.tgz", @@ -548,8 +560,7 @@ "base64-js": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz", - "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==", - "dev": true + "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==" }, "bcrypt-pbkdf": { "version": "1.0.2", @@ -579,7 +590,6 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.2.tgz", "integrity": "sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA==", - "dev": true, "requires": { "readable-stream": "^2.3.5", "safe-buffer": "^5.1.1" @@ -588,14 +598,12 @@ "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" }, "readable-stream": { "version": "2.3.6", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, "requires": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -610,7 +618,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, "requires": { "safe-buffer": "~5.1.0" } @@ -711,7 +718,6 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.2.1.tgz", "integrity": "sha512-c+Ko0loDaFfuPWiL02ls9Xd3GO3cPVmUobQ6t3rXNUk304u6hGq+8N/kFi+QEIKhzK3uwolVhLzszmfLmMLnqg==", - "dev": true, "requires": { "base64-js": "^1.0.2", "ieee754": "^1.1.4" @@ -721,7 +727,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", - "dev": true, "requires": { "buffer-alloc-unsafe": "^1.1.0", "buffer-fill": "^1.0.0" @@ -730,20 +735,17 @@ "buffer-alloc-unsafe": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", - "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==", - "dev": true + "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==" }, "buffer-crc32": { "version": "0.2.13", "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", - "dev": true + "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=" }, "buffer-fill": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", - "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=", - "dev": true + "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=" }, "buffer-from": { "version": "1.1.1", @@ -862,6 +864,33 @@ } } }, + "caching-transform": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-3.0.2.tgz", + "integrity": "sha512-Mtgcv3lh3U0zRii/6qVgQODdPA4G3zhG+jtbCWj39RXuUFTMzH0vcdMtaJS1jPowd+It2Pqr6y3NJMQqOqCE2w==", + "requires": { + "hasha": "^3.0.0", + "make-dir": "^2.0.0", + "package-hash": "^3.0.0", + "write-file-atomic": "^2.4.2" + }, + "dependencies": { + "make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "requires": { + "pify": "^4.0.1", + "semver": "^5.6.0" + } + }, + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==" + } + } + }, "camelcase": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", @@ -890,6 +919,17 @@ "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" }, + "caw": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/caw/-/caw-2.0.1.tgz", + "integrity": "sha512-Cg8/ZSBEa8ZVY9HspcGUYaK63d/bN7rqS3CYCzEGUxuYv6UlmcjzDUz2fCFFHyTvUW5Pk0I+3hkA3iXlIj6guA==", + "requires": { + "get-proxy": "^2.0.0", + "isurl": "^1.0.0-alpha5", + "tunnel-agent": "^0.6.0", + "url-to-options": "^1.0.1" + } + }, "center-align": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", @@ -900,46 +940,22 @@ } }, "chai": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/chai/-/chai-3.5.0.tgz", - "integrity": "sha1-TQJjewZ/6Vi9v906QOxW/vc3Mkc=", - "dev": true, + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz", + "integrity": "sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw==", "requires": { - "assertion-error": "^1.0.1", - "deep-eql": "^0.1.3", - "type-detect": "^1.0.0" - }, - "dependencies": { - "deep-eql": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-0.1.3.tgz", - "integrity": "sha1-71WKyrjeJSBs1xOQbXTlaTDrafI=", - "dev": true, - "requires": { - "type-detect": "0.1.1" - }, - "dependencies": { - "type-detect": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-0.1.1.tgz", - "integrity": "sha1-C6XsKohWQORw6k6FBZcZANrFiCI=", - "dev": true - } - } - }, - "type-detect": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-1.0.0.tgz", - "integrity": "sha1-diIXzAbbJY7EiQihKY6LlRIejqI=", - "dev": true - } + "assertion-error": "^1.1.0", + "check-error": "^1.0.2", + "deep-eql": "^3.0.1", + "get-func-name": "^2.0.0", + "pathval": "^1.1.0", + "type-detect": "^4.0.5" } }, "chai-as-promised": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/chai-as-promised/-/chai-as-promised-6.0.0.tgz", - "integrity": "sha1-GgKkM6byTa+sY7nJb6FoTbGqjaY=", - "dev": true, + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/chai-as-promised/-/chai-as-promised-7.1.1.tgz", + "integrity": "sha512-azL6xMoi+uxu6z4rhWQ1jbdUhOMhis2PvscD/xjLqNMkv3BPPp2JyyuTHOrf9BOosGpNQ11v6BKv/g57RXbiaA==", "requires": { "check-error": "^1.0.2" } @@ -957,7 +973,6 @@ "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, "requires": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -967,14 +982,12 @@ "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" }, "supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, "requires": { "has-flag": "^3.0.0" } @@ -989,12 +1002,6 @@ "is-regex": "^1.0.3" } }, - "chardet": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz", - "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=", - "dev": true - }, "check-error": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", @@ -1034,21 +1041,6 @@ "integrity": "sha512-gpaBrMAizVEANOpfZp/EEUixTXDyGt7DFzdK5hU+UbWt/J0lB0w20ncZj59Z9a93xHb9u12zF5BS6i9RKbtg4w==", "dev": true }, - "cli-cursor": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", - "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", - "dev": true, - "requires": { - "restore-cursor": "^2.0.0" - } - }, - "cli-width": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", - "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", - "dev": true - }, "cliui": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", @@ -1070,7 +1062,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", - "dev": true, "requires": { "mimic-response": "^1.0.0" } @@ -1085,7 +1076,6 @@ "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, "requires": { "color-name": "1.1.3" } @@ -1093,8 +1083,7 @@ "color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" }, "colors": { "version": "1.0.3", @@ -1109,32 +1098,37 @@ "delayed-stream": "~1.0.0" } }, - "command-exists": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/command-exists/-/command-exists-1.2.8.tgz", - "integrity": "sha512-PM54PkseWbiiD/mMsbvW351/u+dafwTJ0ye2qB60G1aGQP9j3xK2gmMDc+R34L3nDtx4qMCitXT75mkbkGJDLw==" - }, "commander": { "version": "2.20.0", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz", "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==" }, + "commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=" + }, "compare-version": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/compare-version/-/compare-version-0.1.2.tgz", "integrity": "sha1-AWLsLZNR9d3VmpICy6k1NmpyUIA=", "dev": true }, - "compress-commons": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-1.2.2.tgz", - "integrity": "sha1-UkqfEJA/OoEzibAiXSfEi7dRiQ8=", + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", "dev": true, "requires": { - "buffer-crc32": "^0.2.1", - "crc32-stream": "^2.0.0", - "normalize-path": "^2.0.0", - "readable-stream": "^2.0.0" + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" }, "dependencies": { "isarray": { @@ -1169,59 +1163,19 @@ } } }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + "config-chain": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.12.tgz", + "integrity": "sha512-a1eOIcu8+7lUInge4Rpf/n4Krkf3Dd9lqhljRzII1/Zno/kRtUWnznPO3jOKBmTEktkt3fkxisUcivoj0ebzoA==", + "requires": { + "ini": "^1.3.4", + "proto-list": "~1.2.1" + } }, - "concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "readable-stream": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "configstore": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/configstore/-/configstore-4.0.0.tgz", - "integrity": "sha512-CmquAXFBocrzaSM8mtGPMM/HiWmyIpr4CcJl/rgY2uCObZ/S7cKU0silxslqJejl+t/T9HS8E0PUNQD81JGUEQ==", + "configstore": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-4.0.0.tgz", + "integrity": "sha512-CmquAXFBocrzaSM8mtGPMM/HiWmyIpr4CcJl/rgY2uCObZ/S7cKU0silxslqJejl+t/T9HS8E0PUNQD81JGUEQ==", "dev": true, "requires": { "dot-prop": "^4.1.0", @@ -1243,6 +1197,22 @@ "babylon": "^6.18.0" } }, + "content-disposition": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", + "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "requires": { + "safe-buffer": "5.1.2" + } + }, + "convert-source-map": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.6.0.tgz", + "integrity": "sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==", + "requires": { + "safe-buffer": "~5.1.1" + } + }, "core-js": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.9.tgz", @@ -1273,54 +1243,31 @@ } } }, - "crc": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/crc/-/crc-3.8.0.tgz", - "integrity": "sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ==", - "dev": true, - "requires": { - "buffer": "^5.1.0" - } - }, - "crc32-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-2.0.0.tgz", - "integrity": "sha1-483TtN8xaN10494/u8t7KX/pCPQ=", - "dev": true, + "cp-file": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/cp-file/-/cp-file-6.2.0.tgz", + "integrity": "sha512-fmvV4caBnofhPe8kOcitBwSn2f39QLjnAnGq3gO9dfd75mUytzKNZB1hde6QHunW2Rt+OwuBOMc3i1tNElbszA==", "requires": { - "crc": "^3.4.4", - "readable-stream": "^2.0.0" + "graceful-fs": "^4.1.2", + "make-dir": "^2.0.0", + "nested-error-stacks": "^2.0.0", + "pify": "^4.0.1", + "safe-buffer": "^5.0.1" }, "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "readable-stream": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, + "make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "pify": "^4.0.1", + "semver": "^5.6.0" } }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==" } } }, @@ -1341,33 +1288,6 @@ "integrity": "sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4=", "dev": true }, - "css": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/css/-/css-2.2.4.tgz", - "integrity": "sha512-oUnjmWpy0niI3x/mPL8dVEI1l7MnG3+HHyRPHf+YFSbK+svOhXpmSOcDURUh2aOCgl2grzrOPt1nHLuCVFULLw==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "source-map": "^0.6.1", - "source-map-resolve": "^0.5.2", - "urix": "^0.1.0" - } - }, - "css-parse": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/css-parse/-/css-parse-2.0.0.tgz", - "integrity": "sha1-pGjuZnwW2BzPBcWMONKpfHgNv9Q=", - "dev": true, - "requires": { - "css": "^2.0.0" - } - }, - "css-value": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/css-value/-/css-value-0.0.1.tgz", - "integrity": "sha1-Xv1sLupeof1rasV+wEJ7GEUkJOo=", - "dev": true - }, "cuint": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/cuint/-/cuint-0.2.2.tgz", @@ -1412,18 +1332,128 @@ "decode-uri-component": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", - "dev": true + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" + }, + "decompress": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/decompress/-/decompress-4.2.0.tgz", + "integrity": "sha1-eu3YVCflqS2s/lVnSnxQXpbQH50=", + "requires": { + "decompress-tar": "^4.0.0", + "decompress-tarbz2": "^4.0.0", + "decompress-targz": "^4.0.0", + "decompress-unzip": "^4.0.1", + "graceful-fs": "^4.1.10", + "make-dir": "^1.0.0", + "pify": "^2.3.0", + "strip-dirs": "^2.0.0" + } }, "decompress-response": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", - "dev": true, "requires": { "mimic-response": "^1.0.0" } }, + "decompress-tar": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/decompress-tar/-/decompress-tar-4.1.1.tgz", + "integrity": "sha512-JdJMaCrGpB5fESVyxwpCx4Jdj2AagLmv3y58Qy4GE6HMVjWz1FeVQk1Ct4Kye7PftcdOo/7U7UKzYBJgqnGeUQ==", + "requires": { + "file-type": "^5.2.0", + "is-stream": "^1.1.0", + "tar-stream": "^1.5.2" + }, + "dependencies": { + "file-type": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-5.2.0.tgz", + "integrity": "sha1-LdvqfHP/42No365J3DOMBYwritY=" + } + } + }, + "decompress-tarbz2": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/decompress-tarbz2/-/decompress-tarbz2-4.1.1.tgz", + "integrity": "sha512-s88xLzf1r81ICXLAVQVzaN6ZmX4A6U4z2nMbOwobxkLoIIfjVMBg7TeguTUXkKeXni795B6y5rnvDw7rxhAq9A==", + "requires": { + "decompress-tar": "^4.1.0", + "file-type": "^6.1.0", + "is-stream": "^1.1.0", + "seek-bzip": "^1.0.5", + "unbzip2-stream": "^1.0.9" + }, + "dependencies": { + "file-type": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-6.2.0.tgz", + "integrity": "sha512-YPcTBDV+2Tm0VqjybVd32MHdlEGAtuxS3VAYsumFokDSMG+ROT5wawGlnHDoz7bfMcMDt9hxuXvXwoKUx2fkOg==" + } + } + }, + "decompress-targz": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/decompress-targz/-/decompress-targz-4.1.1.tgz", + "integrity": "sha512-4z81Znfr6chWnRDNfFNqLwPvm4db3WuZkqV+UgXQzSngG3CEKdBkw5jrv3axjjL96glyiiKjsxJG3X6WBZwX3w==", + "requires": { + "decompress-tar": "^4.1.1", + "file-type": "^5.2.0", + "is-stream": "^1.1.0" + }, + "dependencies": { + "file-type": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-5.2.0.tgz", + "integrity": "sha1-LdvqfHP/42No365J3DOMBYwritY=" + } + } + }, + "decompress-unzip": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/decompress-unzip/-/decompress-unzip-4.0.1.tgz", + "integrity": "sha1-3qrM39FK6vhVePczroIQ+bSEj2k=", + "requires": { + "file-type": "^3.8.0", + "get-stream": "^2.2.0", + "pify": "^2.3.0", + "yauzl": "^2.4.2" + }, + "dependencies": { + "fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", + "requires": { + "pend": "~1.2.0" + } + }, + "file-type": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz", + "integrity": "sha1-JXoHg4TR24CHvESdEH1SpSZyuek=" + }, + "get-stream": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-2.3.1.tgz", + "integrity": "sha1-Xzj5PzRgCWZu4BUKBUFn+Rvdld4=", + "requires": { + "object-assign": "^4.0.1", + "pinkie-promise": "^2.0.0" + } + }, + "yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", + "requires": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + } + } + }, "decompress-zip": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/decompress-zip/-/decompress-zip-0.3.2.tgz", @@ -1458,11 +1488,20 @@ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=" }, - "deepmerge": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-2.0.1.tgz", - "integrity": "sha512-VIPwiMJqJ13ZQfaCsIFnp5Me9tnjURiaIFxfz7EH0Ci0dTSQpZtSLrqOicXqEd/z2r+z+Klk9GzmnRsgpgbOsQ==", - "dev": true + "default-require-extensions": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-2.0.0.tgz", + "integrity": "sha1-9fj7sYp9bVCyH2QfZJ67Uiz+JPc=", + "requires": { + "strip-bom": "^3.0.0" + }, + "dependencies": { + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=" + } + } }, "defer-to-connect": { "version": "1.0.2", @@ -1470,34 +1509,11 @@ "integrity": "sha512-k09hcQcTDY+cwgiwa6PYKLm3jlagNzQ+RSvhjzESOGOx+MNOuXkxTfEvPrO1IOQ81tArCFYQgi631clB70RpQw==", "dev": true }, - "define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", - "dev": true, - "requires": { - "object-keys": "^1.0.12" - }, - "dependencies": { - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true - } - } - }, "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" }, - "dev-null": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/dev-null/-/dev-null-0.1.1.tgz", - "integrity": "sha1-WiBc48Ky73e2I41roXnrdMag6Bg=", - "dev": true - }, "diff": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/diff/-/diff-3.3.1.tgz", @@ -1545,6 +1561,123 @@ "integrity": "sha1-3vHxyl1gWdJKdm5YeULCEQbOEnU=", "dev": true }, + "download": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/download/-/download-7.1.0.tgz", + "integrity": "sha512-xqnBTVd/E+GxJVrX5/eUJiLYjCGPwMpdL+jGhGU57BvtcA7wwhtHVbXBeUk51kOpW3S7Jn3BQbN9Q1R1Km2qDQ==", + "requires": { + "archive-type": "^4.0.0", + "caw": "^2.0.1", + "content-disposition": "^0.5.2", + "decompress": "^4.2.0", + "ext-name": "^5.0.0", + "file-type": "^8.1.0", + "filenamify": "^2.0.0", + "get-stream": "^3.0.0", + "got": "^8.3.1", + "make-dir": "^1.2.0", + "p-event": "^2.1.0", + "pify": "^3.0.0" + }, + "dependencies": { + "@sindresorhus/is": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.7.0.tgz", + "integrity": "sha512-ONhaKPIufzzrlNbqtWFFd+jlnemX6lJAgq9ZeiZtS7I1PIf/la7CW4m83rTXRnVnsMbW2k56pGYu7AUFJD9Pow==" + }, + "cacheable-request": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-2.1.4.tgz", + "integrity": "sha1-DYCIAbY0KtM8kd+dC0TcCbkeXD0=", + "requires": { + "clone-response": "1.0.2", + "get-stream": "3.0.0", + "http-cache-semantics": "3.8.1", + "keyv": "3.0.0", + "lowercase-keys": "1.0.0", + "normalize-url": "2.0.1", + "responselike": "1.0.2" + }, + "dependencies": { + "lowercase-keys": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.0.tgz", + "integrity": "sha1-TjNms55/VFfjXxMkvfb4jQv8cwY=" + } + } + }, + "got": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/got/-/got-8.3.2.tgz", + "integrity": "sha512-qjUJ5U/hawxosMryILofZCkm3C84PLJS/0grRIpjAwu+Lkxxj5cxeCU25BG0/3mDSpXKTyZr8oh8wIgLaH0QCw==", + "requires": { + "@sindresorhus/is": "^0.7.0", + "cacheable-request": "^2.1.1", + "decompress-response": "^3.3.0", + "duplexer3": "^0.1.4", + "get-stream": "^3.0.0", + "into-stream": "^3.1.0", + "is-retry-allowed": "^1.1.0", + "isurl": "^1.0.0-alpha5", + "lowercase-keys": "^1.0.0", + "mimic-response": "^1.0.0", + "p-cancelable": "^0.4.0", + "p-timeout": "^2.0.1", + "pify": "^3.0.0", + "safe-buffer": "^5.1.1", + "timed-out": "^4.0.1", + "url-parse-lax": "^3.0.0", + "url-to-options": "^1.0.1" + } + }, + "http-cache-semantics": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz", + "integrity": "sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w==" + }, + "keyv": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.0.0.tgz", + "integrity": "sha512-eguHnq22OE3uVoSYG0LVWNP+4ppamWr9+zWBe1bsNcovIMy6huUJFPgy4mGwCd/rnl3vOLGW1MTlu4c57CT1xA==", + "requires": { + "json-buffer": "3.0.0" + } + }, + "normalize-url": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-2.0.1.tgz", + "integrity": "sha512-D6MUW4K/VzoJ4rJ01JFKxDrtY1v9wrgzCX5f2qj/lzH1m/lW6MhUZFKerVsnyjOhOsYzI9Kqqak+10l4LvLpMw==", + "requires": { + "prepend-http": "^2.0.0", + "query-string": "^5.0.1", + "sort-keys": "^2.0.0" + } + }, + "p-cancelable": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-0.4.1.tgz", + "integrity": "sha512-HNa1A8LvB1kie7cERyy21VNeHb2CWJJYqyyC2o3klWFfMGlFmWv2Z7sFgZH8ZiaYL95ydToKTFVXgMV/Os0bBQ==" + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" + }, + "sort-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-2.0.0.tgz", + "integrity": "sha1-ZYU1WEhh7JfXMNbPQYIuH1ZoQSg=", + "requires": { + "is-plain-obj": "^1.0.0" + } + }, + "timed-out": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", + "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=" + } + } + }, "duplexer2": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", @@ -1589,8 +1722,7 @@ "duplexer3": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", - "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", - "dev": true + "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=" }, "ecc-jsbn": { "version": "0.1.2", @@ -1712,124 +1844,43 @@ } } }, - "electron-chromedriver": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/electron-chromedriver/-/electron-chromedriver-1.8.0.tgz", - "integrity": "sha512-m1f3nle5MaGp94bcDTtMZZMMOgPO54+TXoPBlTbBSUjfINR5SJ46yQXLfuE79/qsFfJKslZB1UzWURDDFIRmpQ==", + "electron-download": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/electron-download/-/electron-download-3.3.0.tgz", + "integrity": "sha1-LP1U1pZsAZxNSa1l++Zcyc3vaMg=", "dev": true, "requires": { - "electron-download": "^4.1.0", - "extract-zip": "^1.6.5" + "debug": "^2.2.0", + "fs-extra": "^0.30.0", + "home-path": "^1.0.1", + "minimist": "^1.2.0", + "nugget": "^2.0.0", + "path-exists": "^2.1.0", + "rc": "^1.1.2", + "semver": "^5.3.0", + "sumchecker": "^1.2.0" }, "dependencies": { - "electron-download": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/electron-download/-/electron-download-4.1.1.tgz", - "integrity": "sha512-FjEWG9Jb/ppK/2zToP+U5dds114fM1ZOJqMAR4aXXL5CvyPE9fiqBK/9YcwC9poIFQTEJk/EM/zyRwziziRZrg==", + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, "requires": { - "debug": "^3.0.0", - "env-paths": "^1.0.0", - "fs-extra": "^4.0.1", - "minimist": "^1.2.0", - "nugget": "^2.0.1", - "path-exists": "^3.0.0", - "rc": "^1.2.1", - "semver": "^5.4.1", - "sumchecker": "^2.0.2" + "ms": "2.0.0" } }, "fs-extra": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.3.tgz", - "integrity": "sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg==", + "version": "0.30.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz", + "integrity": "sha1-8jP/zAjU2n1DLapEl3aYnbHfk/A=", "dev": true, "requires": { "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - }, - "jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6" - } - }, - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true - }, - "sumchecker": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-2.0.2.tgz", - "integrity": "sha1-D0LBDl0F2l1C7qPlbDOZo31sWz4=", - "dev": true, - "requires": { - "debug": "^2.2.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - } - } - } - } - }, - "electron-download": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/electron-download/-/electron-download-3.3.0.tgz", - "integrity": "sha1-LP1U1pZsAZxNSa1l++Zcyc3vaMg=", - "dev": true, - "requires": { - "debug": "^2.2.0", - "fs-extra": "^0.30.0", - "home-path": "^1.0.1", - "minimist": "^1.2.0", - "nugget": "^2.0.0", - "path-exists": "^2.1.0", - "rc": "^1.1.2", - "semver": "^5.3.0", - "sumchecker": "^1.2.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "fs-extra": { - "version": "0.30.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz", - "integrity": "sha1-8jP/zAjU2n1DLapEl3aYnbHfk/A=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "jsonfile": "^2.1.0", - "klaw": "^1.0.0", - "path-is-absolute": "^1.0.0", - "rimraf": "^2.2.8" + "jsonfile": "^2.1.0", + "klaw": "^1.0.0", + "path-is-absolute": "^1.0.0", + "rimraf": "^2.2.8" } }, "minimist": { @@ -2065,22 +2116,15 @@ "pug": "^2.0.3" } }, - "electron-sudo": { - "version": "3.0.13", - "resolved": "https://registry.npmjs.org/electron-sudo/-/electron-sudo-3.0.13.tgz", - "integrity": "sha1-TIUM3C878PPlQ7j9IcvWVka9V+o=" - }, "emoji-regex": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" }, "end-of-stream": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", - "dev": true, "requires": { "once": "^1.4.0" } @@ -2095,43 +2139,14 @@ "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, "requires": { "is-arrayish": "^0.2.1" } }, - "es-abstract": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.13.0.tgz", - "integrity": "sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg==", - "dev": true, - "requires": { - "es-to-primitive": "^1.2.0", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "is-callable": "^1.1.4", - "is-regex": "^1.0.4", - "object-keys": "^1.0.12" - }, - "dependencies": { - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true - } - } - }, - "es-to-primitive": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz", - "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==", - "dev": true, - "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - } + "es6-error": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", + "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==" }, "es6-promise": { "version": "4.2.8", @@ -2202,12 +2217,21 @@ "strip-eof": "^1.0.0" } }, - "executable": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/executable/-/executable-4.1.1.tgz", - "integrity": "sha512-8iA79xD3uAch729dUG8xaaBBFGaEa0wdD2VkYLFHwlqosEj/jT66AzcreRDSgV7ehnNLBW2WR5jIXwGKjVdTLg==", + "ext-list": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/ext-list/-/ext-list-2.2.2.tgz", + "integrity": "sha512-u+SQgsubraE6zItfVA0tBuCBhfU9ogSRnsvygI7wht9TS510oLkBRXBsqopeUG/GBOIQyKZO9wjTqIu/sf5zFA==", + "requires": { + "mime-db": "^1.28.0" + } + }, + "ext-name": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ext-name/-/ext-name-5.0.0.tgz", + "integrity": "sha512-yblEwXAbGv1VQDmow7s38W77hzAgJAO50ztBLMcUyUBfxv1HC+LGwtiEN+Co6LtlqT/5uwVOxsD4TNIilWhwdQ==", "requires": { - "pify": "^2.2.0" + "ext-list": "^2.0.0", + "sort-keys-length": "^1.0.0" } }, "extend": { @@ -2215,28 +2239,6 @@ "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" }, - "external-editor": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz", - "integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==", - "dev": true, - "requires": { - "chardet": "^0.4.0", - "iconv-lite": "^0.4.17", - "tmp": "^0.0.33" - }, - "dependencies": { - "tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", - "dev": true, - "requires": { - "os-tmpdir": "~1.0.2" - } - } - } - }, "extract-zip": { "version": "1.6.7", "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.6.7.tgz", @@ -2294,13 +2296,50 @@ "pend": "~1.2.0" } }, - "figures": { + "file-type": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-8.1.0.tgz", + "integrity": "sha512-qyQ0pzAy78gVoJsmYeNgl8uH8yKhr1lVhW7JbzJmnlRi0I4R2eEDEJZVKG8agpDnLpacwNbDhLNG/LMdxHD2YQ==" + }, + "filename-reserved-regex": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", - "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", - "dev": true, + "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz", + "integrity": "sha1-q/c9+rc10EVECr/qLZHzieu/oik=" + }, + "filenamify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-2.1.0.tgz", + "integrity": "sha512-ICw7NTT6RsDp2rnYKVd8Fu4cr6ITzGy3+u4vUujPkabyaz+03F24NWEX7fs5fp+kBonlaqPH8fAO2NM+SXt/JA==", + "requires": { + "filename-reserved-regex": "^2.0.0", + "strip-outer": "^1.0.0", + "trim-repeated": "^1.0.0" + } + }, + "find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", "requires": { - "escape-string-regexp": "^1.0.5" + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + }, + "dependencies": { + "make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "requires": { + "pify": "^4.0.1", + "semver": "^5.6.0" + } + }, + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==" + } } }, "find-up": { @@ -2313,23 +2352,6 @@ "pinkie-promise": "^2.0.0" } }, - "flat": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.0.tgz", - "integrity": "sha512-Px/TiLIznH7gEDlPXcUD4KnBusa6kR6ayRUVcnEAbreRIuhkqow/mun59BuRXwoYk7ZQOLW1ZM05ilIvK38hFw==", - "dev": true, - "requires": { - "is-buffer": "~2.0.3" - }, - "dependencies": { - "is-buffer": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.3.tgz", - "integrity": "sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw==", - "dev": true - } - } - }, "flora-colossus": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/flora-colossus/-/flora-colossus-1.0.1.tgz", @@ -2377,6 +2399,26 @@ } } }, + "foreground-child": { + "version": "1.5.6", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-1.5.6.tgz", + "integrity": "sha1-T9ca0t/elnibmApcCilZN8svXOk=", + "requires": { + "cross-spawn": "^4", + "signal-exit": "^3.0.0" + }, + "dependencies": { + "cross-spawn": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-4.0.2.tgz", + "integrity": "sha1-e5JHYhwjrf3ThWAEqCPL45dCTUE=", + "requires": { + "lru-cache": "^4.0.1", + "which": "^1.2.9" + } + } + } + }, "forever-agent": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", @@ -2392,33 +2434,48 @@ "mime-types": "^2.1.12" } }, - "formatio": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/formatio/-/formatio-1.1.1.tgz", - "integrity": "sha1-XtPM1jZVEJc4NGXZlhmRAOhhYek=", - "dev": true, + "from2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", + "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", "requires": { - "samsam": "~1.1" + "inherits": "^2.0.1", + "readable-stream": "^2.0.0" }, "dependencies": { - "samsam": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/samsam/-/samsam-1.1.3.tgz", - "integrity": "sha1-n1CHQZtNCR8jJXHn+lLpCw9VJiE=", - "dev": true + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } } } }, - "forward-emitter": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/forward-emitter/-/forward-emitter-0.1.1.tgz", - "integrity": "sha1-Vu3QwIIlDtujNOC5Iv/SwBk53uE=" - }, "fs-constants": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", - "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", - "dev": true + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" }, "fs-extra": { "version": "2.1.2", @@ -2516,20 +2573,10 @@ } } }, - "gaze": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.3.tgz", - "integrity": "sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g==", - "dev": true, - "requires": { - "globule": "^1.0.0" - } - }, "get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" }, "get-func-name": { "version": "2.0.0", @@ -2656,6 +2703,14 @@ } } }, + "get-proxy": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/get-proxy/-/get-proxy-2.1.0.tgz", + "integrity": "sha512-zmZIaQTWnNQb4R4fJUEp/FC51eZsc6EkErspy3xtIYStaq8EB/hDIWipxsal+E8rz0qD7f2sL/NA9Xee4RInJw==", + "requires": { + "npm-conf": "^1.1.0" + } + }, "get-stdin": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", @@ -2665,8 +2720,7 @@ "get-stream": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", - "dev": true + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=" }, "getos": { "version": "3.1.1", @@ -2705,32 +2759,10 @@ "ini": "^1.3.4" } }, - "globule": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/globule/-/globule-1.2.1.tgz", - "integrity": "sha512-g7QtgWF4uYSL5/dn71WxubOrS7JVGCnFPEnoeChJmBnyR9Mw8nGoEwOgJL/RC2Te0WhbsEUCejfH8SZNJ+adYQ==", - "dev": true, - "requires": { - "glob": "~7.1.1", - "lodash": "~4.17.10", - "minimatch": "~3.0.2" - }, - "dependencies": { - "glob": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", - "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - } - } + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==" }, "got": { "version": "9.6.0", @@ -2767,11 +2799,10 @@ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.0.tgz", "integrity": "sha512-jpSvDPV4Cq/bgtpndIWbI5hmYxhQGHPC4d4cqBPb4DLniCfhJokdXhwhaDuLBGLQdvvRum/UiX6ECVIPvDXqdg==" }, - "grapheme-splitter": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", - "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", - "dev": true + "graceful-readlink": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", + "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=" }, "growl": { "version": "1.10.5", @@ -2779,9 +2810,9 @@ "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==" }, "handlebars": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.1.2.tgz", - "integrity": "sha512-nvfrjqvt9xQ8Z/w0ijewdD/vvWDTOweBUm96NTr66Wfvo1mJenBLwcYmPs3TIBP5ruzYGD7Hx/DaM9RmhroGPw==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.4.0.tgz", + "integrity": "sha512-xkRtOt3/3DzTKMOt3xahj2M/EqNhY988T+imYSlMgs5fVhLN2fmKVVj0LtEGmb+3UUYV5Qmm1052Mm3dIQxOvw==", "requires": { "neo-async": "^2.6.0", "optimist": "^0.6.1", @@ -2837,11 +2868,18 @@ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=" }, - "has-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", - "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", - "dev": true + "has-symbol-support-x": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz", + "integrity": "sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw==" + }, + "has-to-string-tag-x": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz", + "integrity": "sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw==", + "requires": { + "has-symbol-support-x": "^1.4.1" + } }, "has-yarn": { "version": "2.1.0", @@ -2849,6 +2887,14 @@ "integrity": "sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==", "dev": true }, + "hasha": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hasha/-/hasha-3.0.0.tgz", + "integrity": "sha1-UqMvq4Vp1BymmmH/GiFPjrfIvTk=", + "requires": { + "is-stream": "^1.0.1" + } + }, "he": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", @@ -2863,8 +2909,7 @@ "hosted-git-info": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz", - "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==", - "dev": true + "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==" }, "http-cache-semantics": { "version": "4.0.3", @@ -2894,8 +2939,7 @@ "ieee754": { "version": "1.1.13", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", - "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==", - "dev": true + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" }, "import-lazy": { "version": "2.1.0", @@ -2906,8 +2950,7 @@ "imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" }, "indent-string": { "version": "2.1.0", @@ -2937,58 +2980,19 @@ "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" }, - "inquirer": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz", - "integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==", - "dev": true, + "into-stream": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/into-stream/-/into-stream-3.1.0.tgz", + "integrity": "sha1-lvsKk2wSur1v8XUqF9BWFqvQlMY=", "requires": { - "ansi-escapes": "^3.0.0", - "chalk": "^2.0.0", - "cli-cursor": "^2.1.0", - "cli-width": "^2.0.0", - "external-editor": "^2.0.4", - "figures": "^2.0.0", - "lodash": "^4.3.0", - "mute-stream": "0.0.7", - "run-async": "^2.2.0", - "rx-lite": "^4.0.8", - "rx-lite-aggregates": "^4.0.8", - "string-width": "^2.1.0", - "strip-ansi": "^4.0.0", - "through": "^2.3.6" + "from2": "^2.1.1", + "p-is-promise": "^1.1.0" }, "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } + "p-is-promise": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-1.1.0.tgz", + "integrity": "sha1-nJRWmJ6fZYgBewQ01WCXZ1w9oF4=" } } }, @@ -2998,29 +3002,16 @@ "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==", "dev": true }, - "is-arguments": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.0.4.tgz", - "integrity": "sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA==", - "dev": true - }, "is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" }, "is-buffer": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" }, - "is-callable": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", - "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==", - "dev": true - }, "is-ci": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", @@ -3030,12 +3021,6 @@ "ci-info": "^2.0.0" } }, - "is-date-object": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", - "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", - "dev": true - }, "is-electron-renderer": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-electron-renderer/-/is-electron-renderer-2.0.1.tgz", @@ -3075,12 +3060,6 @@ "number-is-nan": "^1.0.0" } }, - "is-generator-function": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.7.tgz", - "integrity": "sha512-YZc5EwyO4f2kWCax7oegfuSr9mFz1ZvieNYBEjmukLxgXfBUbxAWGVF7GZf0zidYtoBl3WvC07YK0wT76a+Rtw==", - "dev": true - }, "is-installed-globally": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.1.0.tgz", @@ -3091,6 +3070,11 @@ "is-path-inside": "^1.0.0" } }, + "is-natural-number": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-natural-number/-/is-natural-number-4.0.1.tgz", + "integrity": "sha1-q5124dtM7VHjXeDHLr7PCfc0zeg=" + }, "is-npm": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-3.0.0.tgz", @@ -3103,6 +3087,11 @@ "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", "dev": true }, + "is-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.1.tgz", + "integrity": "sha1-iVJojF7C/9awPsyF52ngKQMINHA=" + }, "is-path-inside": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", @@ -3112,6 +3101,11 @@ "path-is-inside": "^1.0.1" } }, + "is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=" + }, "is-promise": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", @@ -3125,20 +3119,15 @@ "has": "^1.0.1" } }, + "is-retry-allowed": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz", + "integrity": "sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg==" + }, "is-stream": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", - "dev": true - }, - "is-symbol": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", - "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", - "dev": true, - "requires": { - "has-symbols": "^1.0.0" - } + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" }, "is-typedarray": { "version": "1.0.0", @@ -3221,6 +3210,137 @@ } } }, + "istanbul-lib-coverage": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz", + "integrity": "sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==" + }, + "istanbul-lib-hook": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-2.0.7.tgz", + "integrity": "sha512-vrRztU9VRRFDyC+aklfLoeXyNdTfga2EI3udDGn4cZ6fpSXpHLV9X6CHvfoMCPtggg8zvDDmC4b9xfu0z6/llA==", + "requires": { + "append-transform": "^1.0.0" + } + }, + "istanbul-lib-instrument": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-3.3.0.tgz", + "integrity": "sha512-5nnIN4vo5xQZHdXno/YDXJ0G+I3dAm4XgzfSVTPLQpj/zAV2dV6Juy0yaf10/zrJOJeHoN3fraFe+XRq2bFVZA==", + "requires": { + "@babel/generator": "^7.4.0", + "@babel/parser": "^7.4.3", + "@babel/template": "^7.4.0", + "@babel/traverse": "^7.4.3", + "@babel/types": "^7.4.0", + "istanbul-lib-coverage": "^2.0.5", + "semver": "^6.0.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + } + } + }, + "istanbul-lib-report": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-2.0.8.tgz", + "integrity": "sha512-fHBeG573EIihhAblwgxrSenp0Dby6tJMFR/HvlerBsrCTD5bkUuoNtn3gVh29ZCS824cGGBPn7Sg7cNk+2xUsQ==", + "requires": { + "istanbul-lib-coverage": "^2.0.5", + "make-dir": "^2.1.0", + "supports-color": "^6.1.0" + }, + "dependencies": { + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" + }, + "make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "requires": { + "pify": "^4.0.1", + "semver": "^5.6.0" + } + }, + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==" + }, + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "istanbul-lib-source-maps": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-3.0.6.tgz", + "integrity": "sha512-R47KzMtDJH6X4/YW9XTx+jrLnZnscW4VpNN+1PViSYTejLVPWv7oov+Duf8YQSPyVRUvueQqz1TcsC6mooZTXw==", + "requires": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^2.0.5", + "make-dir": "^2.1.0", + "rimraf": "^2.6.3", + "source-map": "^0.6.1" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "requires": { + "ms": "^2.1.1" + } + }, + "make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "requires": { + "pify": "^4.0.1", + "semver": "^5.6.0" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==" + } + } + }, + "istanbul-reports": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-2.2.6.tgz", + "integrity": "sha512-SKi4rnMyLBKe0Jy2uUdx28h8oG7ph2PPuQPvIAh31d+Ci+lSiEu4C+h3oBPuJ9+mPKhOyW0M8gY4U5NM1WLeXA==", + "requires": { + "handlebars": "^4.1.2" + } + }, + "isurl": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isurl/-/isurl-1.0.0.tgz", + "integrity": "sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w==", + "requires": { + "has-to-string-tag-x": "^1.2.0", + "is-object": "^1.0.1" + } + }, "jquery": { "version": "3.4.1", "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.4.1.tgz", @@ -3236,6 +3356,11 @@ "resolved": "https://registry.npmjs.org/js-stringify/-/js-stringify-1.0.2.tgz", "integrity": "sha1-Fzb939lyTyijaCrcYjCufk6Weds=" }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, "js-yaml": { "version": "3.13.1", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", @@ -3250,11 +3375,20 @@ "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" }, + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==" + }, "json-buffer": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", - "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=", - "dev": true + "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=" + }, + "json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==" }, "json-schema": { "version": "0.2.3", @@ -3367,47 +3501,6 @@ "integrity": "sha512-u93kb2fPbIrfzBuLjZE+w+fJbUUMhNDXxNmMfaqNgpfQf1CO5ZSe2LfsnBqVAk7i/2NF48OSoRj+Xe2VT+lE8Q==", "dev": true }, - "lazystream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", - "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", - "dev": true, - "requires": { - "readable-stream": "^2.0.5" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "readable-stream": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, "lcid": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", @@ -3454,7 +3547,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, "requires": { "p-locate": "^3.0.0", "path-exists": "^3.0.0" @@ -3463,8 +3555,7 @@ "path-exists": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" } } }, @@ -3473,6 +3564,11 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" }, + "lodash.flattendeep": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", + "integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=" + }, "lodash.get": { "version": "4.4.2", "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", @@ -3483,15 +3579,6 @@ "resolved": "https://registry.npmjs.org/log-driver/-/log-driver-1.2.7.tgz", "integrity": "sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg==" }, - "log-symbols": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", - "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", - "dev": true, - "requires": { - "chalk": "^2.0.1" - } - }, "lolex": { "version": "2.7.5", "resolved": "https://registry.npmjs.org/lolex/-/lolex-2.7.5.tgz", @@ -3515,14 +3602,12 @@ "lowercase-keys": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", - "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", - "dev": true + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==" }, "lru-cache": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", - "dev": true, "requires": { "pseudomap": "^1.0.2", "yallist": "^2.1.2" @@ -3532,7 +3617,6 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", - "dev": true, "requires": { "pify": "^3.0.0" }, @@ -3540,8 +3624,7 @@ "pify": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" } } }, @@ -3597,6 +3680,14 @@ } } }, + "merge-source-map": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/merge-source-map/-/merge-source-map-1.1.0.tgz", + "integrity": "sha512-Qkcp7P2ygktpMPh2mCQZaf3jhN6D3Z/qVZHSdWvQ+2Ef5HgRAPBO57A77+ENm0CPx2+1Ce/MYKi3ymqdfuqibw==", + "requires": { + "source-map": "^0.6.1" + } + }, "mime": { "version": "2.4.4", "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz", @@ -3624,8 +3715,7 @@ "mimic-response": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", - "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", - "dev": true + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==" }, "minimatch": { "version": "3.0.4", @@ -3681,106 +3771,31 @@ } }, "mocha": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-6.2.0.tgz", - "integrity": "sha512-qwfFgY+7EKAAUAdv7VYMZQknI7YJSGesxHyhn6qD52DV8UcSZs5XwCifcZGMVIE4a5fbmhvbotxC0DLQ0oKohQ==", - "dev": true, + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-4.1.0.tgz", + "integrity": "sha512-0RVnjg1HJsXY2YFDoTNzcc1NKhYuXKRrBAG2gDygmJJA136Cs2QlRliZG1mA0ap7cuaT30mw16luAeln+4RiNA==", "requires": { - "ansi-colors": "3.2.3", - "browser-stdout": "1.3.1", - "debug": "3.2.6", - "diff": "3.5.0", + "browser-stdout": "1.3.0", + "commander": "2.11.0", + "debug": "3.1.0", + "diff": "3.3.1", "escape-string-regexp": "1.0.5", - "find-up": "3.0.0", - "glob": "7.1.3", - "growl": "1.10.5", - "he": "1.2.0", - "js-yaml": "3.13.1", - "log-symbols": "2.2.0", - "minimatch": "3.0.4", + "glob": "7.1.2", + "growl": "1.10.3", + "he": "1.1.1", "mkdirp": "0.5.1", - "ms": "2.1.1", - "node-environment-flags": "1.0.5", - "object.assign": "4.1.0", - "strip-json-comments": "2.0.1", - "supports-color": "6.0.0", - "which": "1.3.1", - "wide-align": "1.1.3", - "yargs": "13.2.2", - "yargs-parser": "13.0.0", - "yargs-unparser": "1.5.0" + "supports-color": "4.4.0" }, "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true - }, - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true - }, - "cliui": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", - "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", - "dev": true, - "requires": { - "string-width": "^2.1.1", - "strip-ansi": "^4.0.0", - "wrap-ansi": "^2.0.0" - }, - "dependencies": { - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - } - } - } - }, - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "diff": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", - "dev": true - }, - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } + "commander": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz", + "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==" }, "glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", - "dev": true, + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -3790,150 +3805,22 @@ "path-is-absolute": "^1.0.0" } }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "dev": true + "growl": { + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.3.tgz", + "integrity": "sha512-hKlsbA5Vu3xsh1Cg3J7jSmX/WaW6A5oBeqzM88oNbCRQFz+zUaXm6yxS4RVytp1scBoJzSYl4YAEOQIt6O8V1Q==" }, - "is-fullwidth-code-point": { + "has-flag": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - } - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=" }, "supports-color": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz", - "integrity": "sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "wrap-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", - "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", - "dev": true, - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - } - } - }, - "yargs": { - "version": "13.2.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.2.2.tgz", - "integrity": "sha512-WyEoxgyTD3w5XRpAQNYUB9ycVH/PQrToaTXdYXRdOXvEy1l19br+VJsc0vcO8PTGg5ro/l/GY7F/JMEBmI0BxA==", - "dev": true, - "requires": { - "cliui": "^4.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "os-locale": "^3.1.0", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.0.0" - } - }, - "yargs-parser": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.0.0.tgz", - "integrity": "sha512-w2LXjoL8oRdRQN+hOyppuXs+V/fVAYtpcrRxZuF7Kt/Oc+Jr2uAcVntaUTNT6w5ihoWfFDpNY8CPx1QskxZ/pw==", - "dev": true, + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", + "integrity": "sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ==", "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" + "has-flag": "^2.0.0" } } } @@ -3943,17 +3830,16 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, - "mute-stream": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", - "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", - "dev": true - }, "neo-async": { "version": "2.6.1", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.1.tgz", "integrity": "sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==" }, + "nested-error-stacks": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/nested-error-stacks/-/nested-error-stacks-2.1.0.tgz", + "integrity": "sha512-AO81vsIO1k1sM4Zrd6Hu7regmJN1NSiAja10gc4bX3F0wd+9rQmcuHQaHVQCYIEC8iFXnE+mavh23GOt7wBgug==" + }, "nice-try": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", @@ -3988,16 +3874,6 @@ } } }, - "node-environment-flags": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.5.tgz", - "integrity": "sha512-VNYPRfGfmZLx0Ye20jWzHUjyTW/c+6Wq+iLhDzUI4XmhrDd9l/FozXV3F2xOaXjvp0co0+v1YSR3CMP6g+VvLQ==", - "dev": true, - "requires": { - "object.getownpropertydescriptors": "^2.0.3", - "semver": "^5.7.0" - } - }, "nodeify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/nodeify/-/nodeify-1.0.1.tgz", @@ -4037,7 +3913,6 @@ "version": "2.5.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, "requires": { "hosted-git-info": "^2.1.4", "resolve": "^1.10.0", @@ -4045,26 +3920,27 @@ "validate-npm-package-license": "^3.0.1" } }, - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "requires": { - "remove-trailing-separator": "^1.0.1" - } - }, "normalize-url": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.3.0.tgz", "integrity": "sha512-0NLtR71o4k6GLP+mr6Ty34c5GA6CMoEsncKJxvQd8NzPxaHRJNnb5gZE8R1XF4CPIS7QPHLJ74IFszwtNVAHVQ==", "dev": true }, - "npm-install-package": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/npm-install-package/-/npm-install-package-2.1.0.tgz", - "integrity": "sha1-1+/jz816sAYUuJbqUxGdyaslkSU=", - "dev": true + "npm-conf": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/npm-conf/-/npm-conf-1.1.3.tgz", + "integrity": "sha512-Yic4bZHJOt9RCFbRP3GgpqhScOY4HH3V2P8yBj6CeYq118Qr+BLXqT2JvpJ00mryLESpgOxf5XlFv4ZjXxLScw==", + "requires": { + "config-chain": "^1.1.11", + "pify": "^3.0.0" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" + } + } }, "npm-run-path": { "version": "2.0.2", @@ -4119,6 +3995,130 @@ "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", "dev": true }, + "nyc": { + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/nyc/-/nyc-14.1.1.tgz", + "integrity": "sha512-OI0vm6ZGUnoGZv/tLdZ2esSVzDwUC88SNs+6JoSOMVxA+gKMB8Tk7jBwgemLx4O40lhhvZCVw1C+OYLOBOPXWw==", + "requires": { + "archy": "^1.0.0", + "caching-transform": "^3.0.2", + "convert-source-map": "^1.6.0", + "cp-file": "^6.2.0", + "find-cache-dir": "^2.1.0", + "find-up": "^3.0.0", + "foreground-child": "^1.5.6", + "glob": "^7.1.3", + "istanbul-lib-coverage": "^2.0.5", + "istanbul-lib-hook": "^2.0.7", + "istanbul-lib-instrument": "^3.3.0", + "istanbul-lib-report": "^2.0.8", + "istanbul-lib-source-maps": "^3.0.6", + "istanbul-reports": "^2.2.4", + "js-yaml": "^3.13.1", + "make-dir": "^2.1.0", + "merge-source-map": "^1.1.0", + "resolve-from": "^4.0.0", + "rimraf": "^2.6.3", + "signal-exit": "^3.0.2", + "spawn-wrap": "^1.4.2", + "test-exclude": "^5.2.3", + "uuid": "^3.3.2", + "yargs": "^13.2.2", + "yargs-parser": "^13.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" + }, + "cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "requires": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + } + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "requires": { + "locate-path": "^3.0.0" + } + }, + "glob": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", + "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + }, + "make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "requires": { + "pify": "^4.0.1", + "semver": "^5.6.0" + } + }, + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==" + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "requires": { + "ansi-regex": "^4.1.0" + } + }, + "yargs": { + "version": "13.3.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.0.tgz", + "integrity": "sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA==", + "requires": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.1" + } + } + } + }, "oauth-sign": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", @@ -4135,71 +4135,12 @@ "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=", "dev": true }, - "object.assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", - "dev": true, - "requires": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" - }, - "dependencies": { - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true - } - } - }, - "object.entries": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.0.tgz", - "integrity": "sha512-l+H6EQ8qzGRxbkHOd5I/aHRhHDKoQXQ8g0BYt4uSweQU1/J6dZUOyWh9a2Vky35YCKjzmgxOzta2hH6kf9HuXA==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.12.0", - "function-bind": "^1.1.1", - "has": "^1.0.3" - } - }, - "object.getownpropertydescriptors": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz", - "integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=", - "dev": true, - "requires": { - "define-properties": "^1.1.2", - "es-abstract": "^1.5.1" - } - }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "requires": { - "wrappy": "1" - } - }, - "onetime": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", - "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", - "dev": true, - "requires": { - "mimic-fn": "^1.0.0" - }, - "dependencies": { - "mimic-fn": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", - "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", - "dev": true - } + "wrappy": "1" } }, "optimist": { @@ -4230,6 +4171,11 @@ } } }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" + }, "os-locale": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", @@ -4283,7 +4229,8 @@ "os-tmpdir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true }, "p-cancelable": { "version": "1.1.0", @@ -4297,11 +4244,18 @@ "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=", "dev": true }, + "p-event": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/p-event/-/p-event-2.3.1.tgz", + "integrity": "sha512-NQCqOFhbpVTMX4qMe8PF8lbGtzZ+LCiN7pcNrb/413Na7+TRoe1xkKUzuWa/YEJdGQ0FvKtj35EEbDoVPO2kbA==", + "requires": { + "p-timeout": "^2.0.1" + } + }, "p-finally": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", - "dev": true + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=" }, "p-is-promise": { "version": "2.1.0", @@ -4313,7 +4267,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz", "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==", - "dev": true, "requires": { "p-try": "^2.0.0" } @@ -4322,16 +4275,33 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, "requires": { "p-limit": "^2.0.0" } }, + "p-timeout": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-2.0.1.tgz", + "integrity": "sha512-88em58dDVB/KzPEx1X0N3LwFfYZPyDc4B6eF38M1rk9VTZMbxXXgjugz8mmwpS9Ox4BDZ+t6t3QP5+/gazweIA==", + "requires": { + "p-finally": "^1.0.0" + } + }, "p-try": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" + }, + "package-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/package-hash/-/package-hash-3.0.0.tgz", + "integrity": "sha512-lOtmukMDVvtkL84rJHI7dpTYq+0rli8N2wlnqUcBuDWCfVhRUfOmnR9SsoHFMLpACvEV60dX7rd0rFaYDZI+FA==", + "requires": { + "graceful-fs": "^4.1.15", + "hasha": "^3.0.0", + "lodash.flattendeep": "^4.4.0", + "release-zalgo": "^1.0.0" + } }, "package-json": { "version": "6.4.0", @@ -4446,8 +4416,7 @@ "pend": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", - "dev": true + "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=" }, "performance-now": { "version": "2.1.0", @@ -4462,18 +4431,34 @@ "pinkie": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", - "dev": true + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=" }, "pinkie-promise": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "dev": true, "requires": { "pinkie": "^2.0.0" } }, + "pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "requires": { + "find-up": "^3.0.0" + }, + "dependencies": { + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "requires": { + "locate-path": "^3.0.0" + } + } + } + }, "plist": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/plist/-/plist-3.0.1.tgz", @@ -4498,8 +4483,7 @@ "prepend-http": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", - "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=", - "dev": true + "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=" }, "pretty-bytes": { "version": "1.0.4", @@ -4514,8 +4498,7 @@ "process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" }, "progress-stream": { "version": "1.2.0", @@ -4535,11 +4518,36 @@ "asap": "~2.0.3" } }, + "promise-android-tools": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/promise-android-tools/-/promise-android-tools-1.0.2.tgz", + "integrity": "sha512-14jRUvTB7BvCuLp+XE7VNKJtmbQ4a2hbbkpb+WwfI7wIWdkBDbfb1cWbeZjbqMaA6bTW+AfJLLrAzHJGfwp0Jg==", + "requires": { + "chai": "^4.1.2", + "chai-as-promised": "^7.1.1", + "coveralls": "^3.0.0", + "mocha": "^4.0.1", + "nyc": "^14.1.1", + "sinon": "^7.5.0", + "sinon-chai": "^3.3.0" + }, + "dependencies": { + "sinon-chai": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/sinon-chai/-/sinon-chai-3.3.0.tgz", + "integrity": "sha512-r2JhDY7gbbmh5z3Q62pNbrjxZdOAjpsqW/8yxAZRSqLZqowmfGZPGUZPFf3UX36NLis0cv8VEM5IJh9HgkSOAA==" + } + } + }, + "proto-list": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", + "integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=" + }, "pseudomap": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", - "dev": true + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" }, "psl": { "version": "1.1.33", @@ -4686,11 +4694,15 @@ "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" }, - "querystring": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", - "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", - "dev": true + "query-string": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", + "integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==", + "requires": { + "decode-uri-component": "^0.2.0", + "object-assign": "^4.1.0", + "strict-uri-encode": "^1.0.0" + } }, "rc": { "version": "1.2.8", @@ -4834,11 +4846,13 @@ "rc": "^1.2.8" } }, - "remove-trailing-separator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", - "dev": true + "release-zalgo": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz", + "integrity": "sha1-CXALflB0Mpc5Mw5TXFqQ+2eFFzA=", + "requires": { + "es6-error": "^4.0.1" + } }, "repeat-string": { "version": "1.6.1", @@ -4881,25 +4895,15 @@ "uuid": "^3.3.2" } }, - "request-progress": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/request-progress/-/request-progress-3.0.0.tgz", - "integrity": "sha1-TKdUCBx/7GP1BeT6qCWqBs1mnb4=", - "requires": { - "throttleit": "^1.0.0" - } - }, "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" }, "require-main-filename": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" }, "resolve": { "version": "1.11.1", @@ -4909,37 +4913,19 @@ "path-parse": "^1.0.6" } }, - "resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", - "dev": true + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==" }, "responselike": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", - "dev": true, "requires": { "lowercase-keys": "^1.0.0" } }, - "restore-cursor": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", - "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", - "dev": true, - "requires": { - "onetime": "^2.0.0", - "signal-exit": "^3.0.2" - } - }, - "rgb2hex": { - "version": "0.1.9", - "resolved": "https://registry.npmjs.org/rgb2hex/-/rgb2hex-0.1.9.tgz", - "integrity": "sha512-32iuQzhOjyT+cv9aAFRBJ19JgHwzQwbjUhH3Fj2sWW2EEGAW8fpFrDFP5ndoKDxJaLO06x1hE3kyuIFrUQtybQ==", - "dev": true - }, "right-align": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", @@ -4952,7 +4938,6 @@ "version": "2.6.3", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", - "dev": true, "requires": { "glob": "^7.1.3" }, @@ -4961,7 +4946,6 @@ "version": "7.1.4", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", - "dev": true, "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -4973,30 +4957,6 @@ } } }, - "run-async": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", - "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", - "dev": true, - "requires": { - "is-promise": "^2.1.0" - } - }, - "rx-lite": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz", - "integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=", - "dev": true - }, - "rx-lite-aggregates": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz", - "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=", - "dev": true, - "requires": { - "rx-lite": "*" - } - }, "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", @@ -5027,11 +4987,28 @@ "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", "dev": true }, + "seek-bzip": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/seek-bzip/-/seek-bzip-1.0.5.tgz", + "integrity": "sha1-z+kXyz0nS8/6x5J1ivUxc+sfq9w=", + "requires": { + "commander": "~2.8.1" + }, + "dependencies": { + "commander": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.8.1.tgz", + "integrity": "sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ=", + "requires": { + "graceful-readlink": ">= 1.0.0" + } + } + } + }, "semver": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", - "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", - "dev": true + "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==" }, "semver-diff": { "version": "2.1.0", @@ -5045,8 +5022,7 @@ "set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" }, "setimmediate": { "version": "1.0.5", @@ -5072,8 +5048,7 @@ "signal-exit": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", - "dev": true + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" }, "single-line-log": { "version": "1.1.2", @@ -5085,28 +5060,72 @@ } }, "sinon": { - "version": "1.17.7", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-1.17.7.tgz", - "integrity": "sha1-RUKk9JugxFwF6y6d2dID4rjv4L8=", - "dev": true, - "requires": { - "formatio": "1.1.1", - "lolex": "1.3.2", - "samsam": "1.1.2", - "util": ">=0.10.3 <1" + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-7.5.0.tgz", + "integrity": "sha512-AoD0oJWerp0/rY9czP/D6hDTTUYGpObhZjMpd7Cl/A6+j0xBE+ayL/ldfggkBXUs0IkvIiM1ljM8+WkOc5k78Q==", + "requires": { + "@sinonjs/commons": "^1.4.0", + "@sinonjs/formatio": "^3.2.1", + "@sinonjs/samsam": "^3.3.3", + "diff": "^3.5.0", + "lolex": "^4.2.0", + "nise": "^1.5.2", + "supports-color": "^5.5.0" }, "dependencies": { + "@sinonjs/formatio": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-3.2.1.tgz", + "integrity": "sha512-tsHvOB24rvyvV2+zKMmPkZ7dXX6LSLKZ7aOtXY6Edklp0uRcgGpOsQTTGTcWViFyx4uhWc6GV8QdnALbIbIdeQ==", + "requires": { + "@sinonjs/commons": "^1", + "@sinonjs/samsam": "^3.1.0" + } + }, + "@sinonjs/samsam": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-3.3.3.tgz", + "integrity": "sha512-bKCMKZvWIjYD0BLGnNrxVuw4dkWCYsLqFOUWw8VgKF/+5Y+mE7LfHWPIYoDXowH+3a9LsWDMo0uAP8YDosPvHQ==", + "requires": { + "@sinonjs/commons": "^1.3.0", + "array-from": "^2.1.1", + "lodash": "^4.17.15" + } + }, + "diff": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==" + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" + }, "lolex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/lolex/-/lolex-1.3.2.tgz", - "integrity": "sha1-fD2mL/yzDw9agKJWbKJORdigHzE=", - "dev": true + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lolex/-/lolex-4.2.0.tgz", + "integrity": "sha512-gKO5uExCXvSm6zbF562EvM+rd1kQDnB9AZBbiQVzf1ZmdDpxUSvpnAaVOP83N/31mRK8Ml8/VE8DMvsAZQ+7wg==" }, - "samsam": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/samsam/-/samsam-1.1.2.tgz", - "integrity": "sha1-vsEf3IOp/aBjQBIQ5AF2wwJNFWc=", - "dev": true + "nise": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/nise/-/nise-1.5.2.tgz", + "integrity": "sha512-/6RhOUlicRCbE9s+94qCUsyE+pKlVJ5AhIv+jEE7ESKwnbXqulKZ1FYU+XAtHHWE9TinYvAxDUJAb912PwPoWA==", + "requires": { + "@sinonjs/formatio": "^3.2.1", + "@sinonjs/text-encoding": "^0.7.1", + "just-extend": "^4.0.2", + "lolex": "^4.1.0", + "path-to-regexp": "^1.7.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "requires": { + "has-flag": "^3.0.0" + } } } }, @@ -5115,24 +5134,27 @@ "resolved": "https://registry.npmjs.org/sinon-chai/-/sinon-chai-2.14.0.tgz", "integrity": "sha512-9stIF1utB0ywNHNT7RgiXbdmen8QDCRsrTjw+G9TgKt1Yexjiv8TOWZ6WHsTPz57Yky3DIswZvEqX8fpuHNDtQ==" }, + "sort-keys": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz", + "integrity": "sha1-RBttTTRnmPG05J6JIK37oOVD+a0=", + "requires": { + "is-plain-obj": "^1.0.0" + } + }, + "sort-keys-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sort-keys-length/-/sort-keys-length-1.0.1.tgz", + "integrity": "sha1-nLb09OnkgVWmqgZx7dM2/xR5oYg=", + "requires": { + "sort-keys": "^1.0.0" + } + }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" }, - "source-map-resolve": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", - "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", - "dev": true, - "requires": { - "atob": "^2.1.1", - "decode-uri-component": "^0.2.0", - "resolve-url": "^0.2.1", - "source-map-url": "^0.4.0", - "urix": "^0.1.0" - } - }, "source-map-support": { "version": "0.5.12", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.12.tgz", @@ -5143,17 +5165,23 @@ "source-map": "^0.6.0" } }, - "source-map-url": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", - "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", - "dev": true + "spawn-wrap": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-1.4.3.tgz", + "integrity": "sha512-IgB8md0QW/+tWqcavuFgKYR/qIRvJkRLPJDFaoXtLLUaVcCDK0+HeFTkmQHj3eprcYhc+gOl0aEA1w7qZlYezw==", + "requires": { + "foreground-child": "^1.5.6", + "mkdirp": "^0.5.0", + "os-homedir": "^1.0.1", + "rimraf": "^2.6.2", + "signal-exit": "^3.0.2", + "which": "^1.3.0" + } }, "spdx-correct": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", - "dev": true, "requires": { "spdx-expression-parse": "^3.0.0", "spdx-license-ids": "^3.0.0" @@ -5162,14 +5190,12 @@ "spdx-exceptions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", - "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", - "dev": true + "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==" }, "spdx-expression-parse": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", - "dev": true, "requires": { "spdx-exceptions": "^2.1.0", "spdx-license-ids": "^3.0.0" @@ -5178,21 +5204,7 @@ "spdx-license-ids": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.4.tgz", - "integrity": "sha512-7j8LYJLeY/Yb6ACbQ7F76qy5jHkp0U6jgBfJsk97bwWlVUnUWsAgpyaCvo17h0/RQGnQ036tVDomiwoI4pDkQA==", - "dev": true - }, - "spectron": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/spectron/-/spectron-3.8.0.tgz", - "integrity": "sha512-fQ7gFp6UuEaONjXFLifLeIUI022pOsm3b+NFAm696r2umUkSZ9IbnEgHwrvBX+pJ3QUDyCEs5bPHUieYU7FvaQ==", - "dev": true, - "requires": { - "dev-null": "^0.1.1", - "electron-chromedriver": "~1.8.0", - "request": "^2.81.0", - "split": "^1.0.0", - "webdriverio": "^4.8.0" - } + "integrity": "sha512-7j8LYJLeY/Yb6ACbQ7F76qy5jHkp0U6jgBfJsk97bwWlVUnUWsAgpyaCvo17h0/RQGnQ036tVDomiwoI4pDkQA==" }, "speedometer": { "version": "0.1.4", @@ -5200,15 +5212,6 @@ "integrity": "sha1-mHbb0qFp0xFUAtSObqYynIgWpQ0=", "dev": true }, - "split": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", - "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", - "dev": true, - "requires": { - "through": "2" - } - }, "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -5241,6 +5244,11 @@ "integrity": "sha512-QjMLR0A3WwFY2aZdV0okfFEJB5TRjkggXZjxP3A1RsWsNHNu3YPv8btmtc6iCFZ0Rul3FE93OYogvhOUClU+ng==", "dev": true }, + "strict-uri-encode": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", + "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=" + }, "string-width": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", @@ -5276,6 +5284,14 @@ "is-utf8": "^0.2.0" } }, + "strip-dirs": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/strip-dirs/-/strip-dirs-2.1.0.tgz", + "integrity": "sha512-JOCxOeKLm2CAS73y/U4ZeZPTkE+gNVCzKt7Eox84Iej1LT/2pTWYpZKJuxwQpvX1LiZb1xokNR7RLfuBAa7T3g==", + "requires": { + "is-natural-number": "^4.0.1" + } + }, "strip-eof": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", @@ -5297,6 +5313,14 @@ "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", "dev": true }, + "strip-outer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.1.tgz", + "integrity": "sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==", + "requires": { + "escape-string-regexp": "^1.0.2" + } + }, "sumchecker": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-1.3.1.tgz", @@ -5327,12 +5351,14 @@ } }, "system-image-node-module": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/system-image-node-module/-/system-image-node-module-1.0.7.tgz", - "integrity": "sha1-LAMxp0PtBfRMbwzhEcnTK+L8iik=", + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/system-image-node-module/-/system-image-node-module-1.0.9.tgz", + "integrity": "sha512-4KAtlVaSwW0YvsO81eeDUjcO5fPH7GWDir0FQSda8+u+dftpH8YtQIRbJQ7228CI1k5pcDHLPn2JTWRFYWPkxw==", "requires": { "chai": "^4.1.2", + "checksum": "^0.1.1", "coveralls": "^3.0.0", + "download": "^7.1.0", "istanbul": "^0.4.5", "mkdirp": "^0.5.1", "mocha": "^4.0.1", @@ -5442,7 +5468,6 @@ "version": "1.6.2", "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz", "integrity": "sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==", - "dev": true, "requires": { "bl": "^1.0.0", "buffer-alloc": "^1.2.0", @@ -5456,14 +5481,12 @@ "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" }, "readable-stream": { "version": "2.3.6", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, "requires": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -5478,7 +5501,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, "requires": { "safe-buffer": "~5.1.0" } @@ -5486,8 +5508,7 @@ "xtend": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", - "dev": true + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" } } }, @@ -5511,16 +5532,101 @@ "execa": "^0.7.0" } }, - "throttleit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-1.0.0.tgz", - "integrity": "sha1-nnhYNtr0Z0MUWlmEtiaNgoUorGw=" - }, + "test-exclude": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-5.2.3.tgz", + "integrity": "sha512-M+oxtseCFO3EDtAaGH7iiej3CBkzXqFMbzqYAACdzKui4eZA+pq3tZEwChvOdNfa7xxy8BfbmgJSIr43cC/+2g==", + "requires": { + "glob": "^7.1.3", + "minimatch": "^3.0.4", + "read-pkg-up": "^4.0.0", + "require-main-filename": "^2.0.0" + }, + "dependencies": { + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "requires": { + "locate-path": "^3.0.0" + } + }, + "glob": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", + "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + } + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "requires": { + "pify": "^3.0.0" + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" + }, + "read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", + "requires": { + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" + } + }, + "read-pkg-up": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-4.0.0.tgz", + "integrity": "sha512-6etQSH7nJGsK0RbG/2TeDzZFa8shjQ1um+SwQQ5cwKy0dhSXdOncEhb1CPpvQG4h7FyOV6EB6YlV0yJvZQNAkA==", + "requires": { + "find-up": "^3.0.0", + "read-pkg": "^3.0.0" + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=" + } + } + }, "through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", - "dev": true + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" }, "through2": { "version": "0.2.3", @@ -5532,19 +5638,10 @@ "xtend": "~2.1.1" } }, - "tmp": { - "version": "0.0.31", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.31.tgz", - "integrity": "sha1-jzirlDjhcxXl29izZX6L+yd65Kc=", - "requires": { - "os-tmpdir": "~1.0.1" - } - }, "to-buffer": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz", - "integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==", - "dev": true + "integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==" }, "to-fast-properties": { "version": "1.0.3", @@ -5610,6 +5707,14 @@ "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", "dev": true }, + "trim-repeated": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz", + "integrity": "sha1-42RqLqTokTEr9+rObPsFOAvAHCE=", + "requires": { + "escape-string-regexp": "^1.0.2" + } + }, "truncate-utf8-bytes": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz", @@ -5792,6 +5897,15 @@ "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", "optional": true }, + "unbzip2-stream": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.3.3.tgz", + "integrity": "sha512-fUlAF7U9Ah1Q6EieQ4x4zLNejrRvDWUYmxXUpN3uziFYCHapjWFaCAnreY9bGgxzaMCFAPPpYNng57CypwJVhg==", + "requires": { + "buffer": "^5.2.1", + "through": "^2.3.8" + } + }, "unique-string": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-1.0.0.tgz", @@ -5890,71 +6004,29 @@ "punycode": "^2.1.0" } }, - "urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", - "dev": true - }, - "url": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", - "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", - "dev": true, - "requires": { - "punycode": "1.3.2", - "querystring": "0.2.0" - }, - "dependencies": { - "punycode": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", - "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", - "dev": true - } - } - }, "url-parse-lax": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", - "dev": true, "requires": { "prepend-http": "^2.0.0" } }, + "url-to-options": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/url-to-options/-/url-to-options-1.0.1.tgz", + "integrity": "sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k=" + }, "utf8-byte-length": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.4.tgz", "integrity": "sha1-9F8VDExm7uloGGUFq5P8u4rWv2E=", "dev": true }, - "util": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/util/-/util-0.12.0.tgz", - "integrity": "sha512-pPSOFl7VLhZ7LO/SFABPraZEEurkJUWSMn3MuA/r3WQZc+Z1fqou2JqLSOZbCLl73EUIxuUVX8X4jkX2vfJeAA==", - "dev": true, - "requires": { - "inherits": "2.0.3", - "is-arguments": "^1.0.4", - "is-generator-function": "^1.0.7", - "object.entries": "^1.1.0", - "safe-buffer": "^5.1.2" - }, - "dependencies": { - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true - } - } - }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, "uuid": { "version": "3.3.2", @@ -5965,7 +6037,6 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, "requires": { "spdx-correct": "^3.0.0", "spdx-expression-parse": "^3.0.0" @@ -5986,95 +6057,6 @@ "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz", "integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=" }, - "wdio-dot-reporter": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/wdio-dot-reporter/-/wdio-dot-reporter-0.0.10.tgz", - "integrity": "sha512-A0TCk2JdZEn3M1DSG9YYbNRcGdx/YRw19lTiRpgwzH4qqWkO/oRDZRmi3Snn4L2j54KKTfPalBhlOtc8fojVgg==", - "dev": true - }, - "webdriverio": { - "version": "4.14.4", - "resolved": "https://registry.npmjs.org/webdriverio/-/webdriverio-4.14.4.tgz", - "integrity": "sha512-Knp2vzuzP5c5ybgLu+zTwy/l1Gh0bRP4zAr8NWcrStbuomm9Krn9oRF0rZucT6AyORpXinETzmeowFwIoo7mNA==", - "dev": true, - "requires": { - "archiver": "~2.1.0", - "babel-runtime": "^6.26.0", - "css-parse": "^2.0.0", - "css-value": "~0.0.1", - "deepmerge": "~2.0.1", - "ejs": "~2.5.6", - "gaze": "~1.1.2", - "glob": "~7.1.1", - "grapheme-splitter": "^1.0.2", - "inquirer": "~3.3.0", - "json-stringify-safe": "~5.0.1", - "mkdirp": "~0.5.1", - "npm-install-package": "~2.1.0", - "optimist": "~0.6.1", - "q": "~1.5.0", - "request": "^2.83.0", - "rgb2hex": "^0.1.9", - "safe-buffer": "~5.1.1", - "supports-color": "~5.0.0", - "url": "~0.11.0", - "wdio-dot-reporter": "~0.0.8", - "wgxpath": "~1.0.0" - }, - "dependencies": { - "ejs": { - "version": "2.5.9", - "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.5.9.tgz", - "integrity": "sha512-GJCAeDBKfREgkBtgrYSf9hQy9kTb3helv0zGdzqhM7iAkW8FA/ZF97VQDbwFiwIT8MQLLOe5VlPZOEvZAqtUAQ==", - "dev": true - }, - "glob": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", - "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "has-flag": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", - "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", - "dev": true - }, - "optimist": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", - "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", - "dev": true, - "requires": { - "minimist": "~0.0.1", - "wordwrap": "~0.0.2" - } - }, - "supports-color": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.0.1.tgz", - "integrity": "sha512-7FQGOlSQ+AQxBNXJpVDj8efTA/FtyB5wcNE1omXXJ0cq6jm1jjDwuROlYDbnzHqdNPqliWFhcioCWSyav+xBnA==", - "dev": true, - "requires": { - "has-flag": "^2.0.0" - } - } - } - }, - "wgxpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wgxpath/-/wgxpath-1.0.0.tgz", - "integrity": "sha1-7vikudVYzEla06mit1FZfs2a9pA=", - "dev": true - }, "which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", @@ -6086,17 +6068,7 @@ "which-module": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", - "dev": true - }, - "wide-align": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", - "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", - "dev": true, - "requires": { - "string-width": "^1.0.2 || 2" - } + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" }, "widest-line": { "version": "2.0.1", @@ -6140,11 +6112,6 @@ } } }, - "wildcard": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-1.1.2.tgz", - "integrity": "sha1-pwIEUwhNjNLv5wup02liY94XEKU=" - }, "window-size": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", @@ -6188,7 +6155,6 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", - "dev": true, "requires": { "ansi-styles": "^3.2.0", "string-width": "^3.0.0", @@ -6198,20 +6164,17 @@ "ansi-regex": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" }, "is-fullwidth-code-point": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" }, "string-width": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, "requires": { "emoji-regex": "^7.0.1", "is-fullwidth-code-point": "^2.0.0", @@ -6222,7 +6185,6 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, "requires": { "ansi-regex": "^4.1.0" } @@ -6238,7 +6200,6 @@ "version": "2.4.3", "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", - "dev": true, "requires": { "graceful-fs": "^4.1.11", "imurmurhash": "^0.1.4", @@ -6275,14 +6236,12 @@ "y18n": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", - "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", - "dev": true + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==" }, "yallist": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", - "dev": true + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" }, "yargs": { "version": "3.10.0", @@ -6299,7 +6258,6 @@ "version": "13.1.1", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.1.tgz", "integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==", - "dev": true, "requires": { "camelcase": "^5.0.0", "decamelize": "^1.2.0" @@ -6308,167 +6266,7 @@ "camelcase": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true - } - } - }, - "yargs-unparser": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.5.0.tgz", - "integrity": "sha512-HK25qidFTCVuj/D1VfNiEndpLIeJN78aqgR23nL3y4N0U/91cOAzqfHlF8n2BvoNDcZmJKin3ddNSvOxSr8flw==", - "dev": true, - "requires": { - "flat": "^4.1.0", - "lodash": "^4.17.11", - "yargs": "^12.0.5" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true - }, - "cliui": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", - "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", - "dev": true, - "requires": { - "string-width": "^2.1.1", - "strip-ansi": "^4.0.0", - "wrap-ansi": "^2.0.0" - } - }, - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } - }, - "get-caller-file": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", - "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "require-main-filename": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", - "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", - "dev": true - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - }, - "wrap-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", - "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", - "dev": true, - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - } - } - }, - "yargs": { - "version": "12.0.5", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz", - "integrity": "sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==", - "dev": true, - "requires": { - "cliui": "^4.0.0", - "decamelize": "^1.2.0", - "find-up": "^3.0.0", - "get-caller-file": "^1.0.1", - "os-locale": "^3.0.0", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^2.0.0", - "which-module": "^2.0.0", - "y18n": "^3.2.1 || ^4.0.0", - "yargs-parser": "^11.1.1" - } - }, - "yargs-parser": { - "version": "11.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz", - "integrity": "sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" } } }, @@ -6480,50 +6278,6 @@ "requires": { "fd-slicer": "~1.0.1" } - }, - "zip-stream": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-1.2.0.tgz", - "integrity": "sha1-qLxF9MG0lpnGuQGYuqyqzbzUugQ=", - "dev": true, - "requires": { - "archiver-utils": "^1.3.0", - "compress-commons": "^1.2.0", - "lodash": "^4.8.0", - "readable-stream": "^2.0.0" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "readable-stream": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } } } } diff --git a/package.json b/package.json index 12a98e04..d6947a76 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ubports-installer", - "version": "0.2.7-beta", + "version": "0.3.2-beta", "description": "The easy way to install Ubuntu Touch on UBports devices. A friendly cross-platform Installer for Ubuntu Touch. Just connect a supported device to your PC, follow the on-screen instructions and watch this awesome tool do all the rest.", "keywords": [ "Ubuntu", @@ -23,7 +23,6 @@ "main": "src/main.js", "bin": "./src/main.js", "scripts": { - "test-unit": "NODE_ENV=test mocha 'tests/unit-tests/*.js'", "start": "electron .", "dist:mac": "node ./build.js -o 'mac' -p 'dmg'", "dist:win": "node ./build.js -o \"win\" -p \"exe\"", @@ -33,41 +32,28 @@ "dist:linux:snap": "snapcraft cleanbuild" }, "devDependencies": { - "ajv": "^6.10.2", - "chai": "^3.5.0", - "chai-as-promised": "^6.0.0", "electron": "^1.8.8", "electron-builder": "^20.36.2", "electron-packager": "^12.2.0", - "istanbul": "^0.4.5", - "mocha": "^6.2.0", - "sinon": "^1.17.7", - "spectron": "^3.6.0", "unzipper": "^0.9.4" }, "dependencies": { "bootstrap": "^3.3.7", + "download": "^7.1.0", "popper.js": "^1.14.3", "checksum": "^0.1.1", - "command-exists": "^1.2.2", "commander": "^2.9.0", "electron-open-link-in-browser": "^1.0.2", "electron-pug": "^1.5.1", - "electron-sudo": "^3.0.13", - "executable": "^4.1.0", - "forward-emitter": "^0.1.1", "fs-extra": "^2.0.0", "getos": "^3.0.1", - "ini": "^1.3.4", "jquery": "^3.1.1", "jquery-i18next": "^1.2.0", "mkdirp": "^0.5.1", + "promise-android-tools": "^1.0.2", "request": "^2.79.0", - "request-progress": "^3.0.0", - "system-image-node-module": "^1.0.7", + "system-image-node-module": "^1.0.9", "ubports-api-node-module": "^1.0.2", - "tmp": "0.0.31", - "wildcard": "^1.1.2", "winston": "^2.3.1" } } diff --git a/setup-dev.sh b/setup-dev.sh index 6b517e29..5d79080e 100755 --- a/setup-dev.sh +++ b/setup-dev.sh @@ -19,4 +19,7 @@ sudo apt install $packages echo "Setting up node modules..." npm install +echo "Downloading platform tools" +node build.js --download-only --os=linux + echo "Done!" diff --git a/src/adb.js b/src/adb.js deleted file mode 100644 index a80b5704..00000000 --- a/src/adb.js +++ /dev/null @@ -1,349 +0,0 @@ -"use strict"; - -/* - -Adb wrapper, part of ubports-installer - -Author: Marius Gripsgard - -*/ - -const sys = require('util') -const cp = require('child_process'); -const path = require("path"); -const fs = require("fs"); -const events = require("events") -const fEvent = require('forward-emitter'); -const utils = require("./utils"); -const exec = require('child_process').exec; - -// DEFAULT = 5037 -const PORT = 5038 - -class event extends events {} - -// Since we need root anyway, why not start adb with root -const start = (password, sudo, callback) => { - // Make sure the server is not running - stop(err => { - var cmd=""; - if (utils.needRoot() && sudo) - cmd += utils.sudoCommand(password); - cmd += "adb -P " + PORT + " start-server"; - // HACK: Authorize Fairphone 2 vendor ID if necessary - if (utils.isSnap()) - exec("echo 0x2ae5 > ~/.android/adb_usb.ini"); - utils.platformToolsExecAsar("adb", (platformToolsExecAsar) => { - platformToolsExecAsar.exec(cmd, (c, r, e) => { - if (r.includes("incorrect password")) - callback({ - password: true - }); - else - callback(); - platformToolsExecAsar.done(); - }); - }); - }); -} - -const stop = (callback) => { - utils.log.debug("Killing all running adb servers...") - utils.platformToolsExec("adb", ["kill-server"], (err, stdout, stderr) => { - utils.platformToolsExec("adb", ["-P", PORT, "kill-server"], (err, stdout, stderr) => { - // console.log(stdout) - if (err !== null) callback(false); - else callback(); - }); - }); -} - -// TODO: remove lazy override alias, this should be handled by the server -// NOT localy. -const lazyOverrideAlias = (func, arg, callback) => { - var alias = { - "A0001": "bacon", - "a0001": "bacon", - "find7op": "bacon", - "nexus5": "hammerhead", - "fairphone2": "FP2", - "PRO5": "turbo", - "mx4": "arale", - "Aquaris_E45": "krillin", - "Aquaris_E5": "vegetahd", - "Aquaris_M10HD": "cooler", - "Aquaris_M10FHD": "frieza" - } - func(device => { - if (device in alias) - callback(alias[device]); - else - callback(device); - }, arg) -} - -var getDeviceNameFromPropFile = (callback) => { - shell("cat default.prop", (output) => { - output=output.split("\n"); - var ret; - output.forEach((prop) => { - if (prop.includes("ro.product.device") && prop !== undefined && !ret){ - ret = prop.split("=")[1]; - } - }); - callback(ret.replace(/\W/g, "")); - }); -} - -var _getDeviceName = (callback, method) => { - if (!method) method = "device"; - shell("getprop ro.product."+method, (stdout) => { - if (!stdout) { - utils.log.debug("getprop: error"); - callback(false); - return; - } else if (stdout.includes("getprop: not found")){ - utils.log.debug("getprop: not found") - getDeviceNameFromPropFile(callback); - return; - } - utils.log.debug("getprop: "+stdout.replace(/\W/g, "")) - callback(stdout.replace(/\W/g, "")); - }); -} - -var getDeviceName = (callback, method) => { - lazyOverrideAlias(_getDeviceName, method, callback) -} - -var isUbuntuDevice = (callback) => { - shell("cat /etc/system-image/channel.ini", (output) => { - callback(output ? true : false); - }); -} - -var readUbuntuChannelINI = (callback) => { - shell("cat /etc/system-image/channel.ini", (output) => { - if (!output) - return callback(false); - if (!output.startsWith("[service]")) - return callback(false); - var ret = {}; - output.split("\n").forEach(line => { - if (!line.includes(": ")) - return; - var split = line.replace("\r", "").split(": "); - ret[split[0]] = split[1]; - }); - callback(ret); - }) -} - -var isBaseUbuntuCom = callback => { - if (global.installProperties.simulate) { - callback(global.installProperties.currentOs == "ubuntu"); - return; - } - readUbuntuChannelINI(ini => { - if (!ini) - return callback(false); - callback(ini.base.includes("system-image.ubuntu.com")) - }); -} - -var push = (file, dest, pushEvent) => { - if (global.installProperties.simulate) { - return setTimeout(() => { - pushEvent.emit("adbpush:progress", 50); - pushEvent.emit("adbpush:end"); - }, 50); - } - var done; - var hundredEmitted; - var fileSize = fs.statSync(file)["size"]; - var guardedfile = process.platform == "darwin" ? file : '"' + file + '"'; // macos can't handle double quotes - utils.platformToolsExec("adb", ["-P", PORT, "push", guardedfile, dest], (err, stdout, stderr) => { - done=true; - if (err) { - var stdoutShort = stdout && stdout.length > 256 ? "[...]" + stdout.substr(-256, stdout.length) : stdout; - var stderrShort = stderr && stderr.length > 256 ? "[...]" + stderr.substr(-256, stderr.length) : stderr; - if (stderrShort.indexOf("I/O error") != -1) { - utils.log.warn("connection to device lost"); - // TODO: Only restart the event rather than the entire installation - pushEvent.emit("user:connection-lost", () => { location.reload(); }); - } else if (!err.killed && (err.code == 1)) { - hasAdbAccess ((hasAccess) => { - if (hasAccess) { - pushEvent.emit("adbpush:error", err + ", stdout: " + stdoutShort + ", stderr: " + stderrShort); - } else { - utils.log.warn("connection to device lost"); - // TODO: Only restart the event rather than the entire installation - pushEvent.emit("user:connection-lost", () => { location.reload(); }); - } - }); - } else { - pushEvent.emit("adbpush:error", err + ", stdout: " + stdoutShort + ", stderr: " + stderrShort); - } - } - else pushEvent.emit("adbpush:end"); - }); - var progress = () => { - setTimeout(function () { - shell("stat -t "+dest+"/"+path.basename(file), (stat) => { - try { - var currentSize = stat.split(" ")[1]; - var percentage = Math.ceil((currentSize/fileSize)*100); - if(!isNaN(percentage) && !hundredEmitted) pushEvent.emit("adbpush:progress", percentage); - if(percentage == 100) hundredEmitted = true; - if(!done && (percentage < fileSize)) progress(); - } catch (e) { } - }); - }, 1000); - } - progress(); - return pushEvent; -} - -var pushMany = (files, pushManyEvent) => { - var totalLength = files.length; - if (files.length <= 0){ - pushManyEvent.emit("adbpush:error", "No files provided"); - return false; - } - pushManyEvent.emit("adbpush:start", files.length); - push(files[0].src, files[0].dest, pushManyEvent); - pushManyEvent.on("adbpush:end", () => { - files.shift(); - if (files.length <= 0){ - pushManyEvent.emit("adbpush:done"); - return; - } else { - pushManyEvent.emit("adbpush:next", totalLength-files.length+1, totalLength) - push(files[0].src, files[0].dest, pushManyEvent); - } - }); - return pushManyEvent -} - -var shell = (cmd, callback) => { - if (!cmd.startsWith("stat")) utils.log.debug("adb shell: "+cmd); - utils.platformToolsExec("adb", ["-P", PORT, "shell", cmd], (err, stdout, stderr) => { - if (err) callback(false); - else callback(stdout); - }); -} - -var waitForDevice = (callback) => { - if (global.installProperties.simulate) { - setTimeout(() => { - callback(true); - return new event(); - }, 1000); - } - var waitEvent = new event(); - let timer = setInterval(() => { - shell("echo 1", (r) => { - if(r){ - clearInterval(timer); - callback(true); - return; - } - }); - }, 2000); - waitEvent.on("stop", () => { - clearInterval(timer); - }); - return waitEvent; -} - -var hasAdbAccess = (callback) => { - shell("echo 1", (r) => { - callback(r); - }) -} - -var reboot = (state, callback) => { - if (global.installProperties.simulate) { - callback(true); - return; - } - utils.log.debug("reboot to "+state); - utils.platformToolsExec("adb", ["-P", PORT, "reboot", state], (err, stdout, stderr) => { - utils.log.debug("reboot to " + state + " done"); - if (stdout.includes("failed")) callback(true, stdout, stderr); - else if (stderr.includes("failed")) callback(true, stdout, stderr); - else if (err !== null) callback(true, stdout, stderr); - else callback(false); - }); -} - -var format = (partition, callback) => { - if (global.installProperties.simulate) { - callback(true); - return; - } - shell("cat /etc/recovery.fstab", (fstab_) => { - if (!fstab_) { - callback(false, "cannot find recovery.fstab"); - return; - } - var fstab = fstab_.split("\n"); - var block; - fstab.forEach((fs) => { - if (!fs.includes(partition) || block) - return; - block = fs.split(" ")[0]; - if (!block.startsWith("/dev")) - block=false; - }) - if (!block) { - callback(false, "cannot find partition: "+partition); - return; - } - shell("umount /"+partition, () => { - shell("make_ext4fs " + block, (ret) => { - shell("mount /"+partition, () => { - if (ret) - callback(false, "failed to wipe "+partition) - else - callback(true); - }) - }); - }) - }) -} - -var wipeCache = (callback) => { - if (global.installProperties.simulate) { - callback(true); - return; - } - // Try with format; - format("cache", (err) => { - if (!err){ - callback(true); - return; - } - - // If format failed, just rm the contents of cache; - shell("rm -rf /cache/*", callback); - }) -} - -module.exports = { - waitForDevice: waitForDevice, - shell: shell, - getDeviceName: getDeviceName, - push: push, - pushMany: pushMany, - hasAdbAccess: hasAdbAccess, - reboot: reboot, - getDeviceNameFromPropFile: getDeviceNameFromPropFile, - isUbuntuDevice: isUbuntuDevice, - readUbuntuChannelINI: readUbuntuChannelINI, - format: format, - wipeCache: wipeCache, - isBaseUbuntuCom, isBaseUbuntuCom, - start: start, - stop: stop -} diff --git a/src/devices.js b/src/devices.js index bc7cf64c..6f8b7e3d 100644 --- a/src/devices.js +++ b/src/devices.js @@ -1,32 +1,32 @@ "use strict"; /* - -This file is a part of ubports-installer - -Author: Marius Gripsgard - -*/ + * Copyright (C) 2017-2019 UBports Foundation + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ const http = require("request"); const ubportsApi = require("ubports-api-node-module"); -const adb = require("./adb"); -const fastboot = require("./fastboot"); const systemImage = require("./system-image"); const utils = require("./utils"); const os = require("os"); const path = require("path"); -const events = require("events") -const fEvent = require('forward-emitter'); -//const wildcard = require("wildcard"); - -class event extends events {} const devicesApi = new ubportsApi.Devices(); const downloadPath = utils.getUbuntuTouchDir(); -var password; - // HACK: This should be handled by the server, not locally var isLegacyAndroid = (device) => { switch (device) { @@ -36,425 +36,230 @@ var isLegacyAndroid = (device) => { case "frieza": case "turbo": case "arale": - console.log("This is a legacy android device") + utils.log.info("This is a legacy android device"); return true; default: - console.log("This is NOT a legacy android device") + utils.log.debug("This is NOT a legacy android device"); return false; } } -var getNotWorking = (ww) => { - if (!ww) return false; - var notWorking = []; - var whatsWorking = JSON.parse(ww); - for (var i in whatsWorking) { - if (whatsWorking[i] == 1) notWorking.push(i); - } - if (whatsWorking.length == 0) return false; - else return notWorking; -} - -var formatNotWorking = (nw) => { - if (!nw) return false; - return nw.join(", ").replace("/\,(?=[^,]*$)", " and"); -} - -var instructReboot = (state, button, rebootEvent, callback) => { - var rebooted = false; +var instructReboot = (state, button, callback) => { + global.mainEvent.emit("user:write:working", "particles"); + global.mainEvent.emit("user:write:status", "Rebooting to " + state); + global.mainEvent.emit("user:write:under", "Waiting for device to enter " + state + " mode"); var manualReboot = () => { utils.log.info("Instructing manual reboot"); utils.log.info(button[state]["instruction"]); - rebootEvent.emit("user:reboot", { + global.mainEvent.emit("user:reboot", { button: button[state]["button"], instruction: button[state]["instruction"], state: state }); } - adb.hasAdbAccess((hasAccess) => { + var rebootTimeout = setTimeout(() => { manualReboot(); }, 15000); + adb.hasAccess().then((hasAccess) => { if (hasAccess) { - adb.reboot(state, (err, out, eout) => { - if (err) { - utils.log.warn("Adb failed to reboot!, " + out + " : " + eout); - manualReboot(); - } else { - rebootEvent.emit("adb:rebooted"); - } + adb.reboot(state).then(() => { + clearTimeout(rebootTimeout); + global.mainEvent.emit("reboot:done"); + }).catch((err) => { + utils.log.warn("Adb failed to reboot!, " + err); + clearTimeout(rebootTimeout); + manualReboot(); }); } else { + clearTimeout(rebootTimeout); manualReboot(); } if (state === "bootloader") { - requestPassword(rebootEvent, (pass) => { - fastboot.waitForDevice(pass, (err, errM) => { - if (err) { - rebootEvent.emit("Error", errM); - return; - } else { - rebooted = true; - rebootEvent.emit("reboot:done"); - rebootEvent.emit("state:bootloader"); - callback(); - return; - } - }); + fastboot.waitForDevice().then((err, errM) => { + if (err) { + utils.errorToUser(errM, "fastboot.waitForDevice"); + return; + } else { + clearTimeout(rebootTimeout); + global.mainEvent.emit("reboot:done"); + callback(); + return; + } }); } else { - adb.waitForDevice(() => { - rebooted = true; - // We expect the device state to mach installState now - rebootEvent.emit("reboot:done"); - rebootEvent.emit("state:" + state); + adb.waitForDevice().then(() => { + clearTimeout(rebootTimeout); + global.mainEvent.emit("reboot:done"); callback(); return; }); } + }).catch((error) => { + utils.errorToUser(error, "Wait for device") }); - setTimeout(() => { if (!rebooted) manualReboot() }, 15000); } -var requestPassword = (bootstrapEvent, callback) => { - if (!utils.needRoot()) { - callback(""); - return; - } - if (password) { - callback(password); - return; - } - bootstrapEvent.emit("user:password"); - bootstrapEvent.once("password", (p) => { - utils.checkPassword(p, (correct, err) => { - if (correct) { - password=p; - callback(p); - } else if (err.password) { - bootstrapEvent.emit("user:password:wrong"); - requestPassword(bootstrapEvent, callback); - } else { - bootstrapEvent.emit("error", err.message) - } - }); +var downloadImages = (images, device) => { + utils.log.debug(addPathToImages(images, device)); + global.mainEvent.emit("user:write:working", "download"); + global.mainEvent.emit("user:write:status", "Downloading Firmware"); + global.mainEvent.emit("user:write:under", "Downloading"); + utils.downloadFiles(images, (progress, speed) => { + global.mainEvent.emit("download:progress", progress); + global.mainEvent.emit("download:speed", speed); + }, (current, total) => { + if (current != total) utils.log.debug("Downloading bootstrap image " + (current+1) + " of " + total); + }).then((files) => { + utils.log.debug(files) + // Wait for one second until the progress event stops firing + setTimeout(() => { + global.mainEvent.emit("download:done"); + }, 1000); }); } -var instructOemUnlock = (unlockEvent, callback) => { - requestPassword(unlockEvent, (p) => { - fastboot.oemUnlock(password, (err, errM) => { - if (err) { - unlockEvent.emit("error", errM); - callback(true); - } else { - callback(false); - } - }); - }) -} - -var handleBootstrapError = (err, errM, bootstrapEvent, backToFunction) => { - if (err.bootFailed) { - utils.log.warn("fastboot boot failed, does the " + global.installProperties.device + " really support it?"); - bootstrapEvent.emit("bootstrap:done", false); // This will instruct a manual reboot - } else if (err.password) { - bootstrapEvent.emit("user:password:wrong", backToFunction); - } else if (err.connectionLost) { - utils.log.warn("connection to device lost"); - bootstrapEvent.emit("user:connection-lost", backToFunction); - } else if (err.locked) { - bootstrapEvent.emit("user:oem-lock", backToFunction); - } else if (err.lowPower) { - bootstrapEvent.emit("user:low-power"); - } else { - bootstrapEvent.emit("error", errM); - } -} - -var instructBootstrap = (bootstrap, images, bootstrapEvent) => { - //TODO check bootloader name/version/device - var flash = (p) => { - utils.log.info("Flashing images...") - fastboot.flash(images, (err, errM) => { - if (err) { - handleBootstrapError(err, errM, bootstrapEvent, () => { - instructBootstrap(bootstrap, images, bootstrapEvent); - }); - } else { - if (bootstrap) { // The device supports the "fastboot boot" command - utils.log.info("Booting into recovery image..."); - // find recovery image - var recoveryImg; - images.forEach((image) => { - if (image.type === "recovery") - recoveryImg = image; - }); - // If we can't find it, report error! - if (!recoveryImg) { - bootstrapEvent.emit("error", "Cant find recoveryImg to boot: "+images); - } else { - fastboot.boot(recoveryImg, p, (err, errM) => { - if (err) { - handleBootstrapError(err, errM, bootstrapEvent, () => { - instructBootstrap(bootstrap, images, bootstrapEvent); - }); - } else { - bootstrapEvent.emit("bootstrap:done", bootstrap); - } - }); - } - } else { // The device needs to be rebooted manually - bootstrapEvent.emit("bootstrap:done", false); - } - } - }, p); - } - bootstrapEvent.emit("bootstrap:flashing") - bootstrapEvent.emit("user:write:status", "Flashing images") - if (!utils.needRoot()) { - flash(false); - } else { - requestPassword(bootstrapEvent, (p) => { - flash(p); - }); - } -} - -var addPathToImages = (images, device) => { +function addPathToImages(images, device) { var ret = []; images.forEach((image) => { + image["partition"] = image.type; image["path"] = path.join(downloadPath, "images", device); + image["file"] = path.join(downloadPath, "images", device, path.basename(image.url)); ret.push(image); }); return ret; } -var setEvents = (downloadEvent) => { - downloadEvent.on("download:done", () => { - utils.log.info("Download complete"); - downloadEvent.emit("user:write:progress", 0); - }); - downloadEvent.on("download:error", (r) => { - utils.log.error("Devices: Download error "+r); - }); - downloadEvent.on("error", (r) => { - downloadEvent.emit("user:error", r); - utils.log.error("Devices: Error: "+r); - }); - downloadEvent.on("download:checking", () => { - utils.log.info("Download checking file"); - }); - downloadEvent.on("download:startCheck", () => { - downloadEvent.emit("user:write:status", "Checking Ubuntu Touch files"); - utils.log.debug("Download startCheck"); - }); - downloadEvent.on("download:start", (total) => { - downloadEvent.nextTotal = total; - downloadEvent.nextCurrent = 1; - downloadEvent.nextBaseProgress = 0; - utils.log.info("Starting download of "+total+" files"); - downloadEvent.emit("user:write:status", "Downloading Ubuntu Touch"); - downloadEvent.emit("user:write:next", "Downloading", 1, total); - }); - downloadEvent.on("download:next", (current, total) => { - downloadEvent.nextCurrent = current; - downloadEvent.nextBaseProgress = Math.abs(Math.ceil((current-1)/total*100)); - utils.log.info(`Downloading file ${downloadEvent.nextCurrent}/${downloadEvent.nextTotal}`); - downloadEvent.emit("user:write:next", "Downloading", downloadEvent.nextCurrent, downloadEvent.nextTotal); - downloadEvent.emit("user:write:progress", downloadEvent.nextBaseProgress); - }); - downloadEvent.on("download:progress", (percent) => { - utils.log.debug(`Downloading file ${downloadEvent.nextCurrent} of ${downloadEvent.nextTotal}, ${Math.ceil(percent)}% complete`); - downloadEvent.emit("user:write:progress", Math.ceil(percent/downloadEvent.nextTotal+downloadEvent.nextBaseProgress)); - }); - downloadEvent.on("adbpush:done", () => { - utils.log.info("Done pushing files"); - utils.log.info("Rebooting to recovery to flash"); - downloadEvent.emit("system-image:done"); - downloadEvent.emit("user:write:status", "Rebooting to recovery to start the flashing process"); - downloadEvent.emit("user:write:progress", 0); - }); - downloadEvent.on("adbpush:error", (e) => { - downloadEvent.emit("error", "Adb push error: " + e) - utils.log.error("Devices: Adb push error: "+ e) - }); - downloadEvent.on("adbpush:progress", (percent) => { - if (percent != NaN && percent != 100) { - utils.log.debug(`Pushing file ${downloadEvent.nextCurrent} of ${downloadEvent.nextTotal}, ${Math.ceil(percent)}% complete`); - downloadEvent.emit("user:write:progress", Math.ceil(percent/downloadEvent.nextTotal+downloadEvent.nextBaseProgress)); - } - }); - downloadEvent.on("adbpush:next", (current, total) => { - downloadEvent.nextCurrent = current; - downloadEvent.nextBaseProgress = Math.abs(Math.ceil((current-1)/total*100)); - utils.log.info(`Pushing file ${downloadEvent.nextCurrent}/${downloadEvent.nextTotal}`); - downloadEvent.emit("user:write:next", "Pushing", downloadEvent.nextCurrent, downloadEvent.nextTotal); - downloadEvent.emit("user:write:progress", downloadEvent.nextBaseProgress); - }); - downloadEvent.on("adbpush:start", (total) => { - downloadEvent.nextTotal = total; - downloadEvent.nextCurrent = 1; - downloadEvent.nextBaseProgress = 0; - utils.log.info("Start pushing " + total + " files"); - downloadEvent.emit("user:write:status", "Pushing files to device"); - downloadEvent.emit("user:write:start", "Pushing", total); - }); -} +global.mainEvent.on("download:progress", (percent) => { + global.mainEvent.emit("user:write:progress", percent*100); +}); +global.mainEvent.on("download:speed", (speed) => { + global.mainEvent.emit("user:write:speed", Math.round(speed*100)/100); +}); var install = (options) => { - // helper vars for progress events - var nextCurrent; - var nextTotal; - var nextBaseProgress; if (!options) return false; - const installEvent = new event(); - utils.log.debug("install event started with options: " + JSON.stringify(options)) devicesApi.getInstallInstructs(options.device).then((instructs) => { - setEvents(installEvent); - installEvent.on("images:startDownload", () => { - installEvent.emit("user:write:status", "Downloading images"); - utils.downloadFiles(addPathToImages(instructs.images, options.device), installEvent); - }); - installEvent.on("system-image:start", () => { - systemImage.installLatestVersion({ - device: options.device, - channel: options.channel, - event: installEvent, - wipe: options.wipe - }); - }); - installEvent.on("system-image:done", () => { - instructReboot("recovery", instructs.buttons, installEvent, () => { - installEvent.emit("user:write:done"); + global.mainEvent.once("adbpush:done", () => { + utils.log.info("Done pushing files"); + utils.log.info("Rebooting to recovery to flash"); + global.mainEvent.emit("user:write:progress", 0); + global.mainEvent.emit("user:write:working", "particles"); + instructReboot("recovery", instructs.buttons, () => { + global.mainEvent.emit("user:write:done"); }); }); - installEvent.on("bootstrap:done", (bootstrap) => { + global.mainEvent.once("bootstrap:done", (bootstrap) => { utils.log.info("bootstrap done: " + (bootstrap ? "rebooting automatically" : "rebooting manually")); - if (!bootstrap){ - instructReboot("recovery", instructs.buttons, installEvent, () => { - installEvent.emit("system-image:start"); + if (!bootstrap) { + instructReboot("recovery", instructs.buttons, () => { + systemImage.installLatestVersion({ + device: options.device, + channel: options.channel, + wipe: options.wipe + }); }); } else { - installEvent.emit("user:write:status", "Waiting for device to enter recovery mode"); - adb.waitForDevice(() => { - installEvent.emit("system-image:start"); - }); + global.mainEvent.emit("user:write:status", "Rebooting to recovery"); + global.mainEvent.emit("user:write:under", "Waiting for device to enter recovery mode"); + adb.waitForDevice().then(() => { + systemImage.installLatestVersion({ + device: options.device, + channel: options.channel, + wipe: options.wipe + }); + }).catch((error) => { utils.errorToUser(error, "Wait for device"); }); } }); if (instructs.images.length > 0) { // If images are specified, flash them (bootstrapping) // We need to be in bootloader - instructReboot("bootloader", instructs.buttons, installEvent, () => { - installEvent.once("download:done", () => { - instructBootstrap(instructs.installSettings.bootstrap, addPathToImages(instructs.images, options.device), installEvent); + global.mainEvent.emit("user:write:status", "Waiting for device to enter bootloader mode"); + global.mainEvent.emit("user:write:under", "Fastboot is scanning for devices"); + instructReboot("bootloader", instructs.buttons, () => { + global.mainEvent.once("download:done", () => { + global.mainEvent.emit("user:write:working", "particles"); + global.mainEvent.emit("user:write:status", "Flashing images"); + global.mainEvent.emit("user:write:under", "Flashing recovery and boot images"); + global.mainEvent.emit("user:write:progress", 0); + fastboot.erase("cache").then(() => { + fastboot.flashArray(addPathToImages(instructs.images, options.device)).then(() => { + if (instructs.bootstrap) { // Device should support the fastboot boot command + var recoveryImg; + instructs.images.forEach((image) => { + if (image.type == "recovery") recoveryImg = image.file; + }); + fastboot.boot(recoveryImg).then(() => { + global.mainEvent.emit("bootstrap:done", true); + }).catch(() => { + global.mainEvent.emit("bootstrap:done", false); + }); + } else { + global.mainEvent.emit("bootstrap:done", false); + } + }).catch((error) => { utils.errorToUser(error, "bootstrap"); }); + }).catch(((e) => { utils.errorToUser(e, "Fastboot: Erase cache"); })); }); - installEvent.emit("images:startDownload"); + downloadImages(instructs.images, options.device); }); } else { // If no images are specified, go straight to system-image // We need to be in recovery - instructReboot("recovery", instructs.buttons, installEvent, () => { - installEvent.emit("system-image:start"); - }); - } - }); - return installEvent; -} - -var getChannelSelects = (device, callback) => { - if (!device) { - callback (false); - return; - } - var channelsAppend = []; - systemImage.getDeviceChannels(device).then((channels) => { - if (!global.installProperties.channel) { - devicesApi.getInstallInstructs(device).then((ret) => { - if (ret) { - channels.forEach((channel) => { - var _channel = channel.replace("ubports-touch/", ""); - // Ignore blacklisted channels - if (ret["systemServer"]["blacklist"].indexOf(channel) == -1 && - channel.indexOf("15.04") == -1) { - if (channel === ret["systemServer"]["selected"]) - channelsAppend.push(""); - else - channelsAppend.push(""); - } - }); - channelsAppend.push("") - callback(channelsAppend.join('')); - return; - } else { - callback(false); - return; - } + instructReboot("recovery", instructs.buttons, () => { + systemImage.installLatestVersion({ + device: options.device, + channel: options.channel, + wipe: options.wipe + }); }); - } else { - if (channels.indexOf(global.installProperties.channel) != -1) { - setTimeout(callback([ - "" - ]), 50); - return; - } else { - callback(false); - return; - } } - }); - // If the respose takes longer than half a second, get help - setTimeout(() => { - utils.log.debug("getChannelSelects timed out"); - callback(false); - return; - }, 500); + }).catch((e) => { utils.errorToUser(e, "Install"); }); } module.exports = { getDevice: devicesApi.getDevice, - waitForDevice: (callback) => { - var waitEvent; - if (!global.installProperties.device) { - waitEvent = adb.waitForDevice((deviceDetected) => { - if (deviceDetected) { - adb.getDeviceName((device) => { - adb.isBaseUbuntuCom((ubuntuCom) => { - waitEvent.emit("device:select:event", device, ubuntuCom, true); - return; - }); - }); - } else { - waitEvent.emit("device:select:event", false); + waitForDevice: () => { + adb.waitForDevice().then(() => { + adb.getDeviceName().then((device) => { + adb.getOs().then((operatingSystem) => { + global.mainEvent.emit("device:select:event", device, (operatingSystem=="ubuntutouch"), true); return; - } + }).catch((error) => { + utils.errorToUser(error, "Wait for device") + }); + }).catch((error) => { + utils.errorToUser(error, "get device name"); }); - } else { - waitEvent = new event(); - } - waitEvent.on("device:select", (device) => { - waitEvent.emit("stop"); + }).catch(e => utils.log.debug("no device detected: " + e)); + global.mainEvent.once("device:select", (device) => { + global.mainEvent.emit("stop"); utils.log.info(device + " selected"); - waitEvent.emit("device:select:event", device, false, false); + global.mainEvent.emit("device:select:event", device, false, false); }); - waitEvent.once("device:select:event", (device, ubuntuCom, autoDetected) => { + global.mainEvent.once("device:select:event", (device, ubuntuCom, autoDetected) => { devicesApi.getDevice(device).then((apiData) => { - if (apiData) { - setTimeout(getChannelSelects(device, (channels) => { - if (channels) - callback(apiData, device, channels, ubuntuCom, autoDetected, isLegacyAndroid(device)); - ipcRenderer.send("setInstallProperties", { device: device }); + if (apiData) { + systemImage.getDeviceChannels(device).then((channels) => { + var channelsAppend = []; + devicesApi.getInstallInstructs(device).then((ret) => { + channels.forEach((channel) => { + var _channel = channel.replace("ubports-touch/", ""); + // Ignore blacklisted channels + if (ret["systemServer"]["blacklist"].indexOf(channel) == -1 && + channel.indexOf("15.04") == -1) { + if (channel === ret["systemServer"]["selected"]) + channelsAppend.push(""); + else + channelsAppend.push(""); + } + }); + channelsAppend.push("") + global.mainEvent.emit("device:select:data-ready", apiData, device, channelsAppend.join(''), ubuntuCom, autoDetected); + }).catch(((e) => { utils.log.error(e); global.mainEvent.emit("user:no-network"); })); + }).catch((e) => { utils.log.error(e); global.mainEvent.emit("user:no-network"); }); + } else { + mainEvent.emit("user:device-unsupported", device); // If there is no response, the device is not supported return; - }), 50); - } else { - callback(false, device); // If there is no response, the device is not supported - ipcRenderer.send("setInstallProperties", { device: device }); - return; - } - }); + } + }).catch(((e) => { utils.errorToUser(e, "Device Select"); })); }); - return waitEvent; }, - getNotWorking: getNotWorking, - formatNotWorking: formatNotWorking, install: install, getDeviceSelects: (callback) => { devicesApi.getDevices().then((devices) => { @@ -475,7 +280,6 @@ module.exports = { } else { callback(false); } - }); - }, - instructOemUnlock: instructOemUnlock + }).catch(((e) => { utils.errorToUser(e, "getDeviceSelects"); })); + } } diff --git a/src/fastboot.js b/src/fastboot.js deleted file mode 100644 index 58617d6d..00000000 --- a/src/fastboot.js +++ /dev/null @@ -1,237 +0,0 @@ -/* - -Fastboot wrapper, part of ubports-installer - -Author: Marius Gripsgard - -*/ - -const path = require("path"); - -const lockedErrors = ["unlocked", "locked", "oem-lock", "lock"] - -var isLocked = (message) => { - var locked = false; - lockedErrors.forEach((l) => { - if (message.includes(l)){ - locked = true; - return true; - } - }) - return locked; -} - -var handleError = (c, r, e, password, callback) => { - if (c) { - if (c.message.includes("incorrect password")) { - callback({ password: true }); - } else if (isLocked(c.message)) { - callback({ locked: true }); - } else if (e.includes("booting...") && e.includes("FAILED (remote failure)")) { - callback({ bootFailed: true }); - } else if ( - e.includes("FAILED (status read failed (No such device))") || - e.includes("FAILED (command write failed (No such device))") || - e.includes("FAILED (data transfer failure (Broken pipe))") || - e.includes("FAILED (data transfer failure (Protocol error))") - ) { - callback({ connectionLost: true }); - } else if (e.includes("FAILED (remote: low power, need battery charging.)")) { - callback({ lowPower: true }); - } else { - callback(true, "Fastboot: Unknown error: " + utils.hidePassword(r,password) + " " + utils.hidePassword(e,password)); - } - } else { - callback(c, r, e); - } -} - -/* - -args; string, function - -*/ -var waitForDevice = (password, callback) => { - utils.log.info("fastboot: wait for device"); - if (global.installProperties.simulate) { - callback(false); - return; - } - var cmd = ""; - if (utils.needRoot()) - cmd += utils.sudoCommand(password); - cmd += "fastboot" + " devices"; - var stop; - utils.log.debug("Executing: " + utils.hidePassword(cmd, password)); - utils.platformToolsExecAsar("fastboot", (asarExec) => { - var repeat = () => { - asarExec.exec(cmd, (err, r, e) => { - if (r) { - if (r.includes("incorrect password")) - callback(true, { - password: true - }); - else if (r.includes("fastboot")) { - callback(false); - asarExec.done(); - } else { - // Unknown error; - utils.log.error("Fastboot: Unknown error: " + utils.hidePassword(r,password) + " " + utils.hidePassword(e,password)); - callback(true, "Fastboot: Unknown error: " + utils.hidePassword(r,password) + " " + utils.hidePassword(e,password)); - } - return; - } else { - if (e) { - utils.log.error("Fastboot: Unknown error: " + utils.hidePassword(r,password) + " " + utils.hidePassword(e,password)); - callback(true, "Fastboot: Unknown error: " + utils.hidePassword(r,password) + " " + utils.hidePassword(e,password)); - } - setTimeout(() => { - if (!stop) repeat(); - else asarExec.done(); - }, 5000) - } - }) - } - repeat(); - }); - return { - stop: () => { - stop = true; - } - }; -} - -// Due to limitations with sudo we combind the sudo.exec to one call to prevent -// seperate password prompts -/* - -args; array(object), string, function - -image object format -[ - { - path: string, | path of file - url: string, | url to extract filename - type: string | partition to flash - } -] - -*/ -var flash = (images, callback, password) => { - if (global.installProperties.simulate) { - callback(false); - return; - } - utils.log.debug("fastboot: flash; " + JSON.stringify(images)); - var cmd = ""; - images.forEach((image, l) => { - if (utils.needRoot()) - cmd += utils.sudoCommand(password); - cmd += "fastboot" + " flash " + image.type + " \"" + path.join(image.path, path.basename(image.url)) + "\""; - if (l !== images.length - 1) - cmd += " && " - }); - utils.platformToolsExecAsar("fastboot", (asarExec) => { - asarExec.exec(cmd, (c, r, e) => { - handleError(c, r, e, password, callback); - asarExec.done(); - }) - }); -} - -/* - -args; array(object), string, function - -image object format -[ - { - path: string, | path of file - url: string | url to extract filename - } -] - -*/ -var boot = (image, password, callback) => { - if (global.installProperties.simulate) { - callback(false); - return; - } - var cmd=""; - if (utils.needRoot()) - cmd += utils.sudoCommand(password); - cmd += "fastboot" + " boot \"" + path.join(image.path, path.basename(image.url)) + "\""; - utils.platformToolsExecAsar("fastboot", (asarExec) => { - asarExec.exec(cmd, (c, r, e) => { - handleError(c, r, e, password, callback); - asarExec.done(); - }) - }); -} -/* - -args; array, string, function - -*/ -var format = (partitions, password, callback) => { - if (global.installProperties.simulate) { - callback(false); - return; - } - var cmd=""; - partitions.forEach((partition, l) => { - if (utils.needRoot()) - cmd += utils.sudoCommand(password); - cmd += "fastboot" + " format " + partition; - if (l !== partitions.length - 1) - cmd += " && " - }); - utils.platformToolsExecAsar("fastboot", (asarExec) => { - asarExec.exec(cmd, (c, r, e) => { - handleError(c, r, e, password, callback); - asarExec.done(); - }) - }); -} - -/* - -args; array, string, function - -*/ -var oem = (command, password, callback) => { - if (global.installProperties.simulate) { - callback(false); - return; - } - var cmd=""; - if (utils.needRoot()) - cmd += utils.sudoCommand(password); - cmd += "fastboot" + " oem " + command; - utils.platformToolsExecAsar("fastboot", (asarExec) => { - asarExec.exec(cmd, (c, r, e) => { - setTimeout(() => { - handleError(c, r, e, password, callback); - asarExec.done(); - }, 100); - }) - }); -} - -/* - -args; string, function - -*/ -var oemUnlock = (password, callback) => { - oem("unlock", password, callback); -} - -module.exports = { - flash: flash, - waitForDevice: waitForDevice, - boot: boot, - format: format, - oem: oem, - oemUnlock: oemUnlock -} diff --git a/src/html/index.pug b/src/html/index.pug index 6c1a32f1..652ccf70 100644 --- a/src/html/index.pug +++ b/src/html/index.pug @@ -6,7 +6,7 @@ html body include scripts/root .header.is-over - h3#header-text.text-muted.installer UBports Installer + h3#header-text.text-muted.installer UBports Installer (#{global.packageInfo.version}) button#help.help-button.btn.btn-primary.is-over Report a bug button#donate.donate-button.btn.btn-primary.is-over Donate #particles-background.vertical-centered-box @@ -24,20 +24,17 @@ html include views/working #progress.progress(hidden='hidden') footer.footer.is-over - #waitForDevice.container(hidden='hidden') - h3.text-muted.footer-top - | Waiting for a device + .container + h3(style="margin-top: 0").text-muted.footer-top + span#footer-top UBports Installer is starting up span#wait-dot - p.text-muted Connect the device to the computer with a USB cable. - #device.container - h3#device-name.text-muted.footer-top - | UBports Installer is starting up - p#device-under-text.text-muted Starting adb service... + p + span#footer-bottom.text-muted Starting adb service + span#footer-speed.text-muted // --- Modals --- include modals/install include modals/connection-lost include modals/error - include modals/password include modals/oem-lock include modals/legacy-android include modals/low-power diff --git a/src/html/modals/developer-mode.pug b/src/html/modals/developer-mode.pug index 1b333914..910c5f0f 100644 --- a/src/html/modals/developer-mode.pug +++ b/src/html/modals/developer-mode.pug @@ -47,7 +47,7 @@ li | Now go back to the Settings menu and find "developer settings" (sometimes called "developer options"), Tap that. li - | Enable the "OEM unlock" and "USB debugging" options. + | Enable "USB debugging", "ADB" or "Android Debug Bridge" option. If you see it, also enable the "allow OEM unlock" option, but that is not available on every device. .col-xs-6 img(src='../screens/android-dev-mode.gif', style='width: 100%') .modal-footer diff --git a/src/html/modals/error.pug b/src/html/modals/error.pug index 7b06756a..352651f5 100644 --- a/src/html/modals/error.pug +++ b/src/html/modals/error.pug @@ -8,7 +8,7 @@ .modal-body p The Installation stopped due to a problem. You can choose to ignore this, or re-start the installation process. p If this continues to happen, please check if you are affected by #[a(onclick="shell.openExternal('https://github.com/ubports/ubports-installer/issues')") a known bug]. - p If your problem is not yet known, klick the button below to report a new bug. + p If your problem is not yet known, click the button below to report a new bug. pre#error-body. \n p#not-latest-stable(hidden='hidden') You are not using the latest stable version of the UBports Installer. @@ -17,6 +17,6 @@ p If you need help, you can join UBports' support channels on #[a(onclick="shell.openExternal('https://t.me/WelcomePlus')") telegram] or #[a(onclick="shell.openExternal('https://matrix.to/#/!KwdniMNeTmClpgHkND:matrix.org?via=matrix.org&via=ubports.chat&via=disroot.org')") matrix] or ask a question #[a(onclick="shell.openExternal('https://forums.ubports.com')") in the forum] or on #[a(onclick="shell.openExternal('https://askubuntu.com')") askubuntu]. As a last resort, we also have #[a(onclick="shell.openExternal('https://devices.ubuntu-touch.io')") manual installation instructions for every device], that you can follow if you want to install without using the UBports Installer. .modal-footer - button.btn.btn-default(type='button', hidden='hidden', data-dismiss='modal', onclick="location.reload(); utils.log.info('STARTING OVER')") Try again - button.btn.btn-default(type='button', hidden='hidden', data-dismiss='modal', onclick="utils.log.info('ERROR IGNORED')") Ignore + button.btn.btn-default(type='button', hidden='hidden', data-dismiss='modal', onclick="restartInstaller()") Try again + button.btn.btn-default(type='button', hidden='hidden', data-dismiss='modal', onclick="ignoreError()") Ignore button#btn-bugreport.btn.btn-primary(type='button') Report a bug diff --git a/src/html/modals/install.pug b/src/html/modals/install.pug index 16dd89fe..8759a5ee 100644 --- a/src/html/modals/install.pug +++ b/src/html/modals/install.pug @@ -10,7 +10,7 @@ .modal-install-body-no-wipe p b NOTE - | : Installing may in rare cases lead to data loss + | : Installing may in rare cases lead to data loss. p b NOTE ANDROID | : Please note you won't be able to access your Android data and/or apps in Ubuntu Touch. diff --git a/src/html/modals/low-power.pug b/src/html/modals/low-power.pug index 3d247245..32fce5df 100644 --- a/src/html/modals/low-power.pug +++ b/src/html/modals/low-power.pug @@ -11,4 +11,4 @@ b | Please let your device charge for a while and try again. .modal-footer - button.btn.btn-default(type='button', data-dismiss='modal', onclick="location.reload()") Try again + button.btn.btn-default(type='button', data-dismiss='modal', onclick="ipcRenderer.send('restart');") Try again diff --git a/src/html/modals/no-network.pug b/src/html/modals/no-network.pug index e70ba2be..8baacf6b 100644 --- a/src/html/modals/no-network.pug +++ b/src/html/modals/no-network.pug @@ -9,4 +9,4 @@ p | The installer could not connect to UBports' servers to download the devices list. Are you connected to the internet? .modal-footer - button.btn.btn-default(type='button', data-dismiss='modal', onclick="location.reload()") Try again + button.btn.btn-default(type='button', data-dismiss='modal', onclick="ipcRenderer.send('restart');") Try again diff --git a/src/html/modals/oem-lock.pug b/src/html/modals/oem-lock.pug index 310b3a97..fa8765ea 100644 --- a/src/html/modals/oem-lock.pug +++ b/src/html/modals/oem-lock.pug @@ -9,9 +9,11 @@ p | Your device is oem locked, that means installation of third party operating systems like Ubuntu Touch is disabled. b - | Removing the OEM-lock might void your devices warranty. If you want to be sure, please ask your manufacturer or vendor if they allow this. UBports is not responsible and won't replace devices in case of warranty loss. You are responsible for your own actions. + | Removing the OEM-lock might void your device's warranty. If you want to be sure, please ask your manufacturer or vendor if they allow this. UBports is not responsible and won't replace devices in case of warranty loss. You are responsible for your own actions. p | Do you want to unlock your device now? + p + | You might see a confirmation dialog on your device next. .modal-footer button#btn-exit.btn.btn-default(type='button', data-dismiss='modal') Abort button#btn-unlock.btn.btn-primary(type='button') Unlock diff --git a/src/html/modals/options.pug b/src/html/modals/options.pug index 226d5e2c..26bb9b81 100644 --- a/src/html/modals/options.pug +++ b/src/html/modals/options.pug @@ -18,11 +18,11 @@ label input#options-wipe(type='checkbox') | Wipe storage - .col-xs-3 + //- .col-xs-3 label input#options-custom-tools(type='checkbox') | Custom tools - .col-xs-12 + //- .col-xs-12 p#options-custom-tools-snap-note(hidden='hidden') b NOTE: | Custom tools can not be specified for confined snaps. @@ -31,7 +31,7 @@ b NOTE: | If the wipe option is enabled all data stored on the device will be erased. b Please create an external backup of the data you want to keep! - .div#options-custom-tools-area(hidden='hidden') + //- .div#options-custom-tools-area(hidden='hidden') .form-group label.col-xs-3.control-label adb .col-xs-9 diff --git a/src/html/modals/password.pug b/src/html/modals/password.pug deleted file mode 100644 index 2d7e48ee..00000000 --- a/src/html/modals/password.pug +++ /dev/null @@ -1,20 +0,0 @@ -#password-modal.modal.fade(tabindex='-1', data-backdrop='static', data-keyboard='false', role='dialog') - .modal-dialog(role='document') - .modal-content - .modal-header - button.close(type='button', data-dismiss='modal', aria-label='Close') - span(aria-hidden='true') × - h4#myModalLabel.modal-title Administrator password needed to continue - .modal-body - p - | In order to flash the bootimages on your device, your administrator password is needed. This is the same one you use to install software on this computer. - #password-wrong.alert.alert-danger(role='alert', hidden='hidden') - | Access denied, please try again. Are you sure you have entered the correct password? - hr - form.form-horizontal - .form-group - label.col-xs-3.control-label Password - .col-xs-9 - input#password-input.form-control(type='password') - .modal-footer - button#btn-password.btn.btn-primary(type='button', data-dismiss='modal') OK diff --git a/src/html/modals/windows-drivers.pug b/src/html/modals/windows-drivers.pug index 771de5db..11596f60 100644 --- a/src/html/modals/windows-drivers.pug +++ b/src/html/modals/windows-drivers.pug @@ -10,7 +10,7 @@ | You need to install the #[a(onclick="shell.openExternal('https://adb.clockworkmod.com/')") Universal ADB driver] and re-start the program to continue with the installation. | If you have already installed adb drivers, you can dismiss this message and simply continue with the installation. br - | If installer still does not detect you device, you might want to try installing #[a(onclick="shell.openExternal('https://developer.android.com/studio/releases/')") Android Studio] from Google. After that, you can specify custom adb and fastboot tools in the options in the next step. + | If installer still does not detect your device, you might want to try installing #[a(onclick="shell.openExternal('https://developer.android.com/studio/releases/')") Android Studio] from Google. After that, you can specify custom adb and fastboot tools in the options in the next step. br | Please note that the UBports Installer is still somewhat unstable on Windows. If the installation does not work on this machine and you have access to a Linux computer, you might want to try your luck there. br diff --git a/src/html/scripts/main.pug b/src/html/scripts/main.pug index 0f6fd9cd..13ba5f05 100644 --- a/src/html/scripts/main.pug +++ b/src/html/scripts/main.pug @@ -1,10 +1,9 @@ script. // CATCH ANY ERRORS! var onErr = (err) => { - if (global.installProperties.cli) utils.die(err) - if(utils.getUpdateAvailable()) { + if(global.packageInfo.updateAvailable) { $("#not-latest-stable").show(); - if (utils.isSnap()) { + if (global.packageInfo.isSnap) { $("#snap-update-instructions-error").show(); } else { $("#generic-update-instructions-error").show(); @@ -12,224 +11,149 @@ script. } $("#error-body").text(err); $("#error-modal").modal("show"); - $("#password-modal").modal("hide"); } window.onerror = (err, url, line) => { onErr(err+" (MainRenderer:"+line+")"); } + ipcRenderer.on("user:error", (event, err) => { onErr(err); }); - const setInstallEvents = (installEvent) => { - installEvent.on("user:error", onErr); - installEvent.on("bootstrap:flashing", () => { - views.show("working", "particles"); - $("#device-under-text").text("Flashing recovery and boot images") - }); - installEvent.on("system-image:start", () => { - views.show("working", "particles"); - }); - installEvent.on("download:start", () => { - views.show("working", "download"); - }); - installEvent.on("adbpush:start", () => { - views.show("working", "push"); - }); - installEvent.on("adbpush:done", () => { - views.show("working", "particles"); - }); - installEvent.on("user:password", () => { - modals.show("password"); - $("#password-input").val(""); - $("#password-input").keypress((event) => { - if (event.which == '13') { - event.preventDefault(); - installEvent.emit("password", $("#password-input").val()); - modals.hide("password") - $('#password-wrong').hide(); - } - }); - $("#btn-password").click(() => { - installEvent.emit("password", $("#password-input").val()); - $('#password-wrong').hide(); - }); - }); - installEvent.on("user:connection-lost", (callback) => { - modals.show("connection-lost"); - $("#btn-reconnect").click(callback); - }); - installEvent.on("user:low-power", (callback) => { - modals.show("low-power"); - }); - installEvent.on("user:oem-lock", (callback) => { - modals.show('oem-lock'); - $("#btn-unlock").click(() => { - $("#btn-unlock").attr("disabled", true); - $("#btn-exit").attr("disabled", true); - $("#unlock-prog").removeClass("hidden"); - devices.instructOemUnlock(installEvent, (err) => { - $("#btn-unlock").attr("disabled", false); - $("#btn-exit").attr("disabled", false); - $("#unlock-prog").addClass("hidden"); - if (err) { - modals.hide('oem-lock'); - } else { - callback(callback); - modals.hide('oem-lock'); - } - }); - }); - }); - installEvent.on("user:password:wrong", () => { - installEvent.emit("user:password"); - $('#password-wrong').show(); - }); - installEvent.on("user:reboot", (i) => { - views.show("reboot-" + i.button); - $("[id=reboot-to-state]").text(i.state); - $("#complex-reboot-instruction").text(i.instruction); - $("#device-name").text("Please reboot to "+i.state); - $("#device-under-text").text(i.instruction.split(".")[0]); - }); - installEvent.on("adb:rebooted", () => { - $('#views-reboot-up').hide(); - $('#views-reboot-down').hide(); - }); - installEvent.on("reboot:done", () => { - views.show("working", "particles"); - $('#views-reboot-up').hide(); - $('#views-reboot-down').hide(); - }); - installEvent.on("user:write:next", (text, current, total) => { - $("#device-under-text").text(text + " file " + current + " of " + total); - }); - installEvent.on("user:write:start", (text, length) => { - $("#device-under-text").text(text+" file 1 of "+length); - }); - installEvent.on("user:write:progress", (length) => { - if(length >= 100) { - length=100; - } - $("#progress").width(length.toString()+"%"); - }); - installEvent.on("user:write:done", () => { - if (global.installProperties.cli) { - remote.getCurrentWindow().close(); - } else { - views.show("done"); - $("#device-name").text("Done"); - $("#device-under-text").text("It is now safe to unplug the device."); - $("#progress").width("0%"); - } - }); - installEvent.on("user:write:status", (status) => { - $("#device-name").text(status).append("."); - }); + ipcRenderer.on("user:write:working", (e, animation) => { + views.show("working", animation); + }); + + ipcRenderer.on("user:connection-lost", (e, callback) => { + modals.show("connection-lost"); + $("#btn-reconnect").click(callback); + }); + + ipcRenderer.on("user:low-power", (callback) => { + modals.show("low-power"); + }); + + var ignoreError = () => { + ipcRenderer.send('error_ignored'); } - const mainEvent = (output, device, channels, ubuntuCom, autoDetected, isLegacyAndroid) => { - utils.log.debug("mainEvent called") - var installEvent; - if(!output) { - $("#device-name").text("Device not supported"); - $("#device-under-text").text("The device " + device + " is not supported"); - $("[id=your-device]").text(device) - views.show("not-supported"); - utils.log.warn("This device is not supported!") - $("#btn-inst").hide(); - } else { - if (global.installProperties.cli) { - utils.log.debug(output); - installEvent = devices.install({ - device: global.installProperties.device, - channel: global.installProperties.channel, - wipe: false // TODO --wipe option - }); - setInstallEvents(installEvent); - views.show("working", "particles"); - $("#progress").show(); - } else { - views.show("install"); - $("#options-channel").append(channels); - options.optionsValToUser(); - modals.hide('select-device'); - $("#btn-inst").show(); - $("#device-name").text(output.name); - if (isLegacyAndroid && !ubuntuCom) - $("#legacy-android-note").show(); - if (isLegacyAndroid) - modals.show("legacy-android"); - if (autoDetected) - footer.underText.set("Are you ready for Ubuntu Touch on your " + output.name + "?"); - else - footer.underText.set("Please connect your " + output.name + " with a USB cable."); - $("#your-ubp-device").text(output.name+" ("+output.device+")") - $("#your-ubp-device").click(() => { - shell.openExternal("https://devices.ubuntu-touch.io/device/"+output.device); - }); - - views.show(ubuntuCom ? "switch" : "install"); - - $("#btn-inst").click(() => { - modals.show('install'); - if(options.get("custom-tools", true)) { - utils.setCustomPlatformTool("adb", options.get("custom-tools-adb")); - utils.setCustomPlatformTool("fastboot", options.get("custom-tools-fastboot")); - } - }); - - $("#btn-installModal").click(() => { - views.show("working", "particles"); - $("#progress").show(); - ipcRenderer.send("setInstallProperties", {device: output.device, channel: options.get("channel", true)}); - installEvent = devices.install({ - device: output.device, - channel: options.get("channel", true), - wipe: options.get("wipe", true) - }); - setInstallEvents(installEvent); - }); - } - } - }; + var restartInstaller = () => { + ipcRenderer.send('restart'); + } - // START - utils.log.info("Welcome to the UBports Installer version " + global.packageInfo.version + "!"); - header.version_info.set(global.packageInfo.version); - views.show("working", "particles"); - footer.topText.set("UBports Installer is starting up").append("."); - footer.underText.set("Starting adb service..."); + ipcRenderer.on("user:oem-lock", (event) => { + modals.show('oem-lock'); + $("#btn-unlock").click(() => { + event.sender.send("user:oem-lock:ok"); + modals.hide('oem-lock'); + $("#btn-unlock").attr("disabled", true); + $("#btn-exit").attr("disabled", true); + $("#unlock-prog").removeClass("hidden"); + }); + }); + + ipcRenderer.on("user:reboot", (e, i) => { + views.show("reboot-" + i.button); + $("[id=reboot-to-state]").text(i.state); + $("#complex-reboot-instruction").text(i.instruction); + }); + + ipcRenderer.on("reboot:done", () => { + $('#views-reboot-up').hide(); + $('#views-reboot-down').hide(); + }); - devices.getDeviceSelects((out) => { - if (out) { - $("#device-select").append(out); + ipcRenderer.on("user:no-network", () => { + modals.show('no-network'); + }); + + ipcRenderer.on("user:write:speed", (e, speed) => { + footer.speedText.set(speed); + }); + + ipcRenderer.on("user:write:progress", (e, length) => { + if(length >= 100) { + length=100; + } + $("#progress").width(length.toString()+"%"); + }); + + ipcRenderer.on("user:write:done", () => { + if (global.installProperties.cli) { + remote.getCurrentWindow().close(); } else { - modals.show('no-network'); + views.show("done"); + footer.topText.set("Installation complete!"); + footer.underText.set("It is now safe to unplug the device."); + $("#progress").width("0%"); } }); - adb.start(false, false, (err) => { - var waitEvent = devices.waitForDevice(mainEvent); - if (!global.installProperties.device) { - footer.topText.set("Waiting for device").append("."); - footer.underText.set("Please connect your device with a USB cable"); - views.show("wait-for-device"); - // Button to open device selector - $("#btn-modal-select-device").click(() => { - waitEvent.emit("stop"); - modals.show('select-device'); - }); - // Button to confirm device selection - $("#btn-select-device").click(() => { - var device = $("#device-select").find(":selected").attr("name"); - waitEvent.emit("device:select", device); - }); + ipcRenderer.on("user:write:status", (e, status) => { + footer.topText.set(status, true) + }); + + ipcRenderer.on("user:write:under", (e, status) => { + footer.underText.set(status, true) + }); + + ipcRenderer.on("user:device-unsupported", (event, device) => { + footer.topText.set("Device not supported"); + footer.underText.set("The device " + device + " is not supported"); + $("[id=your-device]").text(device); + views.show("not-supported"); + $("#btn-inst").hide(); + }); + + ipcRenderer.on("device:select:data-ready", (event, output, device, channels, ubuntuCom, autoDetected, isLegacyAndroid) => { + views.show("install"); + $("#options-channel").append(channels); + options.optionsValToUser(); + modals.hide('select-device'); + $("#btn-inst").show(); + footer.topText.set(output.name); + if (isLegacyAndroid && !ubuntuCom) { + $("#legacy-android-note").show(); + modals.show("legacy-android"); + } + if (autoDetected) { + footer.underText.set("Are you ready for Ubuntu Touch on your " + output.name + "?"); } else { - setTimeout(waitEvent.emit('device:select', (global.installProperties.device)), 50); + footer.underText.set("Please connect your " + output.name + " with a USB cable."); } - waitEvent.on("user:error", onErr); - waitEvent.on("device:select", (device) => { - modals.hide('select-device'); + $("#your-ubp-device").text(output.name+" ("+output.device+")"); + $("#your-ubp-device").click(() => { + shell.openExternal("https://devices.ubuntu-touch.io/device/"+output.device); + }); + + $("#btn-installModal").click(() => { + views.show("working", "particles"); + $("#progress").show(); + ipcRenderer.send("user:device:select", { + device: output.device, + channel: options.get("channel", true), + wipe: options.get("wipe", true) + }); + }); + }); + + views.show("working", "particles"); + + ipcRenderer.on("device:wait:device-selects-ready", (event, deviceSelects) => { + $("#device-select").append(deviceSelects); + }); + + ipcRenderer.on("user:adb:ready", () => { + footer.topText.set("Waiting for device", true); + footer.underText.set("Please connect your device with a USB cable"); + views.show("wait-for-device"); + // Button to open device selector + $("#btn-modal-select-device").click(() => { + modals.show('select-device'); + }); + // Button to confirm device selection + $("#btn-select-device").click(() => { + var device = $("#device-select").find(":selected").attr("name"); + ipcRenderer.send("device:select", device); }); }); diff --git a/src/html/scripts/root.pug b/src/html/scripts/root.pug index 8c21469d..7b98db1a 100644 --- a/src/html/scripts/root.pug +++ b/src/html/scripts/root.pug @@ -2,10 +2,6 @@ script. require('jquery'); window.$ = window.jQuery = require('../../node_modules/jquery/dist/jquery.js'); const { shell } = require('electron'); - const devices = require('../devices.js'); - const systemImage = require("../system-image.js"); - const adb = require("../adb.js"); - const utils = require("../utils.js"); const remote = require('electron').remote; var ipcRenderer = require('electron').ipcRenderer; require('bootstrap'); diff --git a/src/html/scripts/ui.pug b/src/html/scripts/ui.pug index fd754a26..5c3ffb24 100644 --- a/src/html/scripts/ui.pug +++ b/src/html/scripts/ui.pug @@ -101,23 +101,23 @@ script. remove: id => setText("user", id, "") } - const header = { - version_info: { - set: (text) => { - return $('#header-text').text('UBports Installer ('+text+')'); - } - } - } - const footer = { topText: { - set: (text) => { - return $("#device-name").text(text) + set: (text, dots) => { + if (dots) $("#wait-dot").show() + else $("#wait-dot").hide() + return $("#footer-top").text(text) } }, underText: { set: (text) => { - return $("#device-under-text").text(text) + return $("#footer-bottom").text(text) + } + }, + speedText: { + set: (text) => { + if (text) return $("#footer-speed").text(" at " + text + " MB/s"); + else return $("#footer-speed").text(""); } } } @@ -179,22 +179,20 @@ script. switchHide("modal-install-body-wipe", "modal-install-body-no-wipe"); } }); - $("#options-custom-tools").change(() => { - if (getOptionVal("custom-tools", true)) { - $("#options-custom-tools-area").show(); - } else { - $("#options-custom-tools-area").hide(); - } - }); + // $("#options-custom-tools").change(() => { + // if (getOptionVal("custom-tools", true)) { + // $("#options-custom-tools-area").show(); + // } else { + // $("#options-custom-tools-area").hide(); + // } + // }); }, optionsValToUser: optionsValToUser } $("#btn-bugreport").click(() => { var title = $("#error-body").text(); - utils.createBugReport(title, (body) => { - shell.openExternal("https://github.com/ubports/ubports-installer/issues/new?title="+title+"&body="+body); - }); + ipcRenderer.send("createBugReport", title); }); $("#btn-exit").click(() => { @@ -203,9 +201,7 @@ script. }); $("#help").click(() => { - utils.createBugReport("user-requested error report", (body) => { - shell.openExternal("https://github.com/ubports/ubports-installer/issues/new?title=please describe the problem you are experiencing&body="+body); - }); + ipcRenderer.send("createBugReport", "user-requested bug-report"); }); $("#donate").click(() => { @@ -220,26 +216,29 @@ script. modals.show('developer-mode-info'); }); - if(utils.isSnap()) { - $("#options-custom-tools").prop("disabled", true); - $("#options-custom-tools-snap-note").show(); - } + $("#btn-inst").click(() => { + modals.show('install'); + // if(options.get("custom-tools", true)) { + // utils.setCustomPlatformTool("adb", options.get("custom-tools-adb")); + // utils.setCustomPlatformTool("fastboot", options.get("custom-tools-fastboot")); + // } + }); + + // if(global.packageInfo.isSnap) { + // $("#options-custom-tools").prop("disabled", true); + // $("#options-custom-tools-snap-note").show(); + // } if (process.platform === "win32" && !localStorage.getItem('neverAskForWindowsDrivers')) { modals.show('windows-drivers'); } - utils.getUpdateAvailable().then((updateAvailable) => { - if(updateAvailable) { - utils.log.warn("This is not the latest stable release!") - if (utils.isSnap()) { - $("#snap-update-instructions").show(); - $("#btn-update-installer").hide(); - } else { - $("#generic-update-instructions").show(); - } - modals.show('new-update'); + ipcRenderer.on("user:update-available", () => { + if (global.packageInfo.isSnap) { + $("#snap-update-instructions").show(); + $("#btn-update-installer").hide(); } else { - utils.log.debug("Running latest stable version."); + $("#generic-update-instructions").show(); } + modals.show('new-update'); }); diff --git a/src/html/views/done.pug b/src/html/views/done.pug index f80e7929..813bbeaf 100644 --- a/src/html/views/done.pug +++ b/src/html/views/done.pug @@ -7,11 +7,11 @@ p | The installation process from the computer is done. The device will now perform the remaining steps which should take less than five minutes. After the installation, the device will reboot and you can begin to explore Ubuntu Touch. p - | Found something you don't like? #[a(onclick="shell.openExternal('https://github.com/ubports/ubports-touch')") tell us], or help us change it! + | Found something you don't like? #[a(onclick="shell.openExternal('https://github.com/ubports/ubports-touch')") Tell us], or help us change it! p | Development of Ubuntu Touch is driven by the #[a(onclick="shell.openExternal('https://ubports.com')") UBports Community]. Donate now to allow us to continue our mission! button.btn.btn-default(type='button', style='width: 49%; margin-bottom: 10px; margin-right: 5px', onclick="shell.openExternal('https://ubports.com/get-involved')") Get involved button.btn.btn-primary(type='button', style='width: 49%; margin-bottom: 10px;', onclick="shell.openExternal('https://ubports.com/donate')") Donate p | Got more devices you want to flash? - button.btn.btn-info(type='button', style='width: 100%;', onclick="location.reload(); ipcRenderer.send('resetDeviceAndChannel')") Flash another device! + button.btn.btn-info(type='button', style='width: 100%;', onclick="ipcRenderer.send('restart');") Flash another device! diff --git a/src/html/views/not-supported.pug b/src/html/views/not-supported.pug index 85cde80f..7ca068da 100644 --- a/src/html/views/not-supported.pug +++ b/src/html/views/not-supported.pug @@ -17,5 +17,5 @@ hr h4(style='font-weight: bold;') You want to try to install anyway? p - | You can try selecting your device manualy, but please only do so if you're sure that your exact model is actually supported! You might also want to #[a(onclick="shell.openExternal('http://devices.ubuntu-touch.io')") file a bug]. + | You can try selecting your device manually, but please only do so if you're sure that your exact model is actually supported! You might also want to #[a(onclick="shell.openExternal('http://devices.ubuntu-touch.io')") file a bug]. button#btn-modal-select-device-unsupported.btn.btn-default(type='button', style='width: 100%;') Select device manually diff --git a/src/main.js b/src/main.js index 44d7643f..c6f3aca6 100755 --- a/src/main.js +++ b/src/main.js @@ -1,26 +1,65 @@ "use strict"; /* - -This file is a part of ubports-installer - -Author: Marius Gripsgard - -*/ + * Copyright (C) 2017-2019 UBports Foundation + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ const cli = require("commander"); const electron = require('electron'); const electronPug = require('electron-pug'); + const app = electron.app; const BrowserWindow = electron.BrowserWindow; -var ipcMain = require('electron').ipcMain; +global.packageInfo = require('../package.json'); +const Adb = require('promise-android-tools').Adb; +const Fastboot = require('promise-android-tools').Fastboot; + +const exec = require('child_process').exec; const path = require('path'); const url = require('url'); +const events = require("events"); +class event extends events {}; + const pug = new electronPug(); +const ipcMain = electron.ipcMain; let mainWindow; -global.packageInfo = require('../package.json'); +const mainEvent = new event(); +global.mainEvent = mainEvent; + +const utils = require('./utils.js'); +global.utils = utils; +const devices = require('./devices.js'); +var adb = new Adb({ + exec: (args, callback) => { exec( + [(path.join(utils.getUbuntuTouchDir(), 'platform-tools', 'adb'))].concat(args).join(" "), + {options: {maxBuffer: 1024*1024*2}}, + callback + ); } +}); +global.adb = adb; +var fastboot = new Fastboot({ + exec: (args, callback) => { exec( + [(path.join(utils.getUbuntuTouchDir(), 'platform-tools', 'fastboot'))].concat(args).join(" "), + {options: {maxBuffer: 1024*1024*2}}, + callback + ); } +}); +global.fastboot = fastboot; cli .name(global.packageInfo.name) @@ -29,38 +68,172 @@ cli .option('-d, --device ', '[experimental] Override detected device-id (codename)') .option('-c, --channel ', '[experimental] Override the recommended release-channel for the device') .option('-C, --cli', "[experimental] Run without GUI", undefined, 'false') - .option('-F, --force-fallback', "Use the android-tools packaged with the UBports Installer", undefined, 'false') - .option('-n, --no-root', "Do not ask for the password and run fastboot without elevated privilleges", undefined, 'false') .option('-v, --verbose', "Enable verbose logging", undefined, 'false') .option('-D, --debug', "Enable debugging tools and verbose logging", undefined, 'false') - .option('-s, --simulate', "[experimental] Run through every step except actually installing", undefined, 'false') .parse(process.argv); global.installProperties = { device: cli.device, channel: cli.channel, cli: cli.cli, - forceFallback: cli.forceFallback, - noRoot: !cli.root, verbose: (cli.verbose || cli.debug), - debug: cli.debug, - simulate: cli.simulate + debug: cli.debug }; -ipcMain.on( "setInstallProperties", ( event, installProperties ) => { +global.packageInfo.isSnap = utils.isSnap(); + +utils.exportExecutablesFromPackage(); + +//============================================================================== +// RENDERER SIGNAL HANDLING +//============================================================================== + +// Device selected +ipcMain.on("user:device:select", (event, installProperties) => { global.installProperties = Object.assign(global.installProperties, installProperties); + devices.install(installProperties); }); -ipcMain.on( "die", (exitCode) => { +// Exit process with optional non-zero exit code +ipcMain.on("die", (exitCode) => { process.exit(exitCode); }); -ipcMain.on("resetDeviceAndChannel", () => { +// Restart the installer +ipcMain.on("restart", () => { + mainEvent.emit("restart"); +}); + +// The user ignored an error +ipcMain.on("error_ignored", () => { + utils.log.debug("ERROR IGNORED"); +}); + +// Submit a bug-report +ipcMain.on("createBugReport", (event, title) => { + utils.createBugReport(title, global.installProperties, (body) => { + electron.shell.openExternal("https://github.com/ubports/ubports-installer/issues/new?title="+title+"&body="+body); + }); +}); + +// The user selected a device +ipcMain.on("device:select", (event, device) => { + global.installProperties.device = device; + mainEvent.emit("device:select", device); +}); + +//============================================================================== +// RENDERER COMMUNICATION +//============================================================================== + +// Open the bugreporting tool +mainEvent.on("user:error", (err) => { + try { + if (mainWindow) mainWindow.webContents.send("user:error", err); + else utils.die(err); + } catch (e) { + utils.log.error(e); + process.exit(1); + } +}); + +// Connection to the device was lost +mainEvent.on("user:connection-lost", (callback) => { + if (mainWindow) mainWindow.webContents.send("user:connection-lost", callback); +}); + +// The device battery is too low to install +mainEvent.on("user:low-power", () => { + if (mainWindow) mainWindow.webContents.send("user:low-power"); +}); + +// Restart the installer +mainEvent.on("restart", () => { global.installProperties.device = undefined; global.installProperties.channel = undefined; + utils.log.debug("WINDOW RELOADED"); + mainWindow.reload(); +}); + +// The device's bootloader is locked, prompt the user to unlock it +mainEvent.on("user:oem-lock", (callback) => { + mainWindow.webContents.send("user:oem-lock"); + ipcMain.once("user:oem-lock:ok", () => { + fastboot.oemUnlock().then(() => { + callback(true); + }).catch((err) => { + mainEvent.emit("user:error", err); + }); + }); +}); + +// Prompt the user to reboot +mainEvent.on("user:reboot", (i) => { + if (mainWindow) mainWindow.webContents.send("user:reboot", i); +}); + +// Reboot complete, hide the reboot prompt +mainEvent.on("reboot:done", () => { + if (mainWindow) mainWindow.webContents.send("reboot:done"); +}); + +// Control the progress bar +mainEvent.on("user:write:progress", (length) => { + if (mainWindow) mainWindow.webContents.send("user:write:progress", length); +}); + +// Installation successfull +mainEvent.on("user:write:done", () => { + if (mainWindow) mainWindow.webContents.send("user:write:done"); + if (mainWindow) mainWindow.webContents.send("user:write:speed"); + utils.log.info("All done! Your device will now reboot and complete the installation. Enjoy exploring Ubuntu Touch!"); +}); + +// Show working animation +mainEvent.on("user:write:working", (animation) => { + if (mainWindow) mainWindow.webContents.send("user:write:working", animation); }); +// Set the top text in the footer +mainEvent.on("user:write:status", (status) => { + if (mainWindow) mainWindow.webContents.send("user:write:status", status); +}); + +// Set the speed part of the footer +mainEvent.on("user:write:speed", (speed) => { + if (mainWindow) mainWindow.webContents.send("user:write:speed", speed); +}); + +// Set the lower text in the footer +mainEvent.on("user:write:under", (status) => { + if (mainWindow) mainWindow.webContents.send("user:write:under", status); +}); + +// Device is unsupported +mainEvent.on("user:device-unsupported", (device) => { + utils.log.warn("The device " + device + " is not supported!"); + if (mainWindow) mainWindow.webContents.send("user:device-unsupported", device); +}); + +// Set the install configuration data +mainEvent.on("device:select:data-ready", (output, device, channels, ubuntuCom, autoDetected, isLegacyAndroid) => { + global.installProperties.device = device; + if (mainWindow) mainWindow.webContents.send("device:select:data-ready", output, device, channels, ubuntuCom, autoDetected, isLegacyAndroid); +}); + +// No internet connection +mainEvent.on("user:no-network", () => { + if (mainWindow) mainWindow.webContents.send("user:no-network"); +}); + +//============================================================================== +// CREATE WINDOW +//============================================================================== + function createWindow () { + utils.setLogLevel(global.installProperties.verbose ? "debug" : "info"); + utils.log.info("Welcome to the UBports Installer version " + global.packageInfo.version + "!"); + utils.log.info("This is " + (global.packageInfo.updateAvailable ? "not " : "") + "the latest stable version!"); mainWindow = new BrowserWindow({ width: cli.cli ? 0 : (cli.debug ? 1600 : 800), height: cli.cli ? 0 : 600, @@ -69,33 +242,55 @@ function createWindow () { title: "UBports Installer ("+global.packageInfo.version+")" }); + // Tasks we need for every start + mainWindow.webContents.on("did-finish-load", () => { + adb.startServer().then(() => { + mainWindow.webContents.send("user:adb:ready"); + devices.waitForDevice(); + }); + devices.getDeviceSelects((out) => { + mainWindow.webContents.send("device:wait:device-selects-ready", out) + }); + }); + + // Task we need only on the first start + mainWindow.webContents.once("did-finish-load", () => { + utils.getUpdateAvailable().then(() => { + utils.log.info("This is not the latest version of the UBports Installer! Please update: https://devices.ubuntu-touch.io/installer/" + (global.packageInfo.package ? global.packageInfo.package : "")); + mainWindow.webContents.send("user:update-available"); + }).catch(() => { + utils.log.debug("This is the latest version.") + }); + }); + mainWindow.loadURL(url.format({ pathname: path.join(__dirname, 'html/index.pug'), protocol: 'file:', slashes: true })); - mainWindow.setMenu(null); - if (cli.debug) { - mainWindow.webContents.openDevTools(); - } + mainWindow.setMenu(null); // TODO set menu + + if (cli.debug) mainWindow.webContents.openDevTools(); mainWindow.on('closed', function () { mainWindow = null; }); } -app.on('ready', createWindow); +//============================================================================== +// FUNCTIONAL EVENT HANDLING +//============================================================================== -app.on('uncaughtException', function (error) { - console.log("CRAP!"); -}); +app.on('ready', createWindow); app.on('window-all-closed', function () { - console.log("Good bye!"); - if (process.platform !== 'darwin') { - app.quit(); - } + utils.log.info("Good bye!"); + adb.killServer().then(() => { + if (process.platform !== 'darwin') { + app.quit(); + } + }); }); app.on('activate', function () { @@ -103,3 +298,9 @@ app.on('activate', function () { createWindow(); } }); + +process.on('unhandledRejection', (r) => { + utils.log.error(r); + if (mainWindow) utils.errorToUser(r); + else utils.die(r); +}); diff --git a/src/system-image.js b/src/system-image.js index 85c80487..b51fc791 100644 --- a/src/system-image.js +++ b/src/system-image.js @@ -1,86 +1,58 @@ "use strict"; /* + * Copyright (C) 2017-2019 UBports Foundation + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ -This file is a part of ubports-installer - -Author: Marius Gripsgard - -*/ - -const fs = require("fs"); const utils = require("./utils"); -const adb = require("./adb"); -const path = require("path"); -const events = require("events") -const mkdirp = require('mkdirp'); const systemImageClient = require("system-image-node-module").Client; const systemImage = new systemImageClient({path: utils.getUbuntuTouchDir()}); -class event extends events {} - -const ubuntuCommandFile = "ubuntu_command"; -const ubuntuPushDir = "/cache/recovery/" const getDeviceChannels = (device) => { return systemImage.getDeviceChannels(device); } -var downloadLatestVersion = (options) => { - utils.log.debug("downloadLatestVersion options: ", options); - var thisEvent; - if (!options.event) - thisEvent = new event(); - else - thisEvent = options.event; - systemImage.getLatestVersion(options.device, options.channel).then((latest) => { - var urls = systemImage.getFilesUrlsArray(latest) - urls.push.apply(urls, systemImage.getGgpUrlsArray()); - var files = systemImage.getFilePushArray(urls); - utils.downloadFiles(urls, thisEvent); - utils.log.debug(urls); - thisEvent.once("download:done", () => { - files.push({ - src: systemImage.createInstallCommandsFile( - systemImage.createInstallCommands( - latest.files, - options.installerCheck, - options.wipe, - options.enable - ), - options.device - ), - dest: ubuntuPushDir + ubuntuCommandFile - }); - thisEvent.emit("download:pushReady", files); - }); - }).catch(() => { - thisEvent.emit("error", "could not find latest version; " + "device: " + options.device + " channel: " + options.channel); - }); - return thisEvent; -} - -var pushLatestVersion = (files, thisEvent, dontWipeCache) => { - var doPush = () => { - adb.shell("mount -a", () => { - adb.shell("mkdir -p /cache/recovery", () => { - adb.pushMany(files, thisEvent); - }); - }); - } - if (dontWipeCache) - doPush(); - else - adb.wipeCache(doPush); - return thisEvent; -} - var installLatestVersion = (options) => { - var downloadEvent = downloadLatestVersion(options); - downloadEvent.once("download:pushReady", (files) => { - pushLatestVersion(files, downloadEvent) + mainEvent.emit("user:write:working", "download"); + mainEvent.emit("user:write:status", "Downloading Ubuntu Touch"); + mainEvent.emit("user:write:under", "Downloading"); + systemImage.downloadLatestVersion(options, (progress, speed) => { + mainEvent.emit("download:progress", progress); + mainEvent.emit("download:speed", speed); + }, (current, total) => { + if (current != total) utils.log.debug("Downloading system-image file " + (current+1) + " of " + total); + }).then((files) => { + mainEvent.emit("download:done"); + mainEvent.emit("user:write:progress", 0); + mainEvent.emit("user:write:working", "push"); + mainEvent.emit("user:write:status", "Sending"); + mainEvent.emit("user:write:under", "Sending files to the device"); + adb.wipeCache().then(() => { + adb.shell("mount -a").then(() => { + adb.shell("mkdir -p /cache/recovery").then(() => { + adb.pushArray(files, (progress) => { + global.mainEvent.emit("user:write:progress", progress*100); + }).then(() => { + global.mainEvent.emit("adbpush:done"); + }).catch(e => utils.errorToUser("Push failed: Failed push: " + e)); + }).catch(e => utils.errorToUser("Push failed: Failed to create target dir: " + e)); + }).catch(e => utils.errorToUser("Push failed: Failed to mount: " + e)); + }).catch(e => utils.errorToUser("Push failed: Failed wipe cache: " + e)); }); - return downloadEvent; } module.exports = { diff --git a/src/utils.js b/src/utils.js index 43f2c601..a7be29b3 100644 --- a/src/utils.js +++ b/src/utils.js @@ -1,34 +1,31 @@ /* - -This file is a part of ubports-installer - -Author: Marius Gripsgard - -*/ + * Copyright (C) 2017-2019 UBports Foundation + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ const http = require("request"); -const progress = require("request-progress"); +const download = require("download"); const os = require("os"); const fs = require("fs-extra"); const path = require("path"); const checksum = require('checksum'); const mkdirp = require('mkdirp'); -const tmp = require('tmp'); -const exec = require('child_process').exec; const cp = require('child_process'); -const sudo = require('electron-sudo'); const winston = require('winston'); const getos = require('getos'); -const commandExistsSync = require('command-exists').sync; -const remote = require('electron').remote; -var ipcRenderer = require('electron').ipcRenderer; -global.installProperties = remote ? remote.getGlobal('installProperties') : undefined; -global.packageInfo = remote ? remote.getGlobal('packageInfo') : require('../package.json'); - -var customTools = { - adb: undefined, - fastboot: undefined -} +global.packageInfo = require('../package.json'); const platforms = { "linux": "linux", @@ -36,13 +33,6 @@ const platforms = { "win32": "win" } -var platformNativeToolsLogged; -var platformFallbackToolsLogged; - -var getVersion = () => { - return global.packageInfo.version; -} - if (global.installProperties) winston.level = global.installProperties.verbose ? 'debug' : 'info'; @@ -53,7 +43,7 @@ var log = { debug: (l) => {winston.log("debug", l)} } -var createBugReport = (title, callback) => { +function createBugReport(title, installProperties, callback) { var options = { limit: 400, start: 0, @@ -84,9 +74,9 @@ var createBugReport = (title, callback) => { getos((e,gOs) => { callback("*Automatically generated error report* %0D%0A" + "UBports Installer Version: " + global.packageInfo.version + " %0D%0A" + - "Device: " + (global.installProperties.device ? global.installProperties.device : "Not detected") + "%0D%0A" + - "Channel: " + (global.installProperties.channel ? global.installProperties.channel : "Not yet set") + "%0D%0A" + - "Package: " + (isSnap() ? "snap" : (global.packageInfo.package || "source")) + "%0D%0A" + + "Device: " + (installProperties.device ? installProperties.device : "Not detected") + "%0D%0A" + + "Channel: " + (installProperties.channel ? installProperties.channel : "Not yet set") + "%0D%0A" + + "Package: " + (isSnap() ? "snap" : (packageInfo.package || "source")) + "%0D%0A" + "Operating System: " + getCleanOs() + " " + os.arch() + " %0D%0A" + "NodeJS version: " + process.version + " %0D%0A%0D%0A" + "Error log: https://paste.ubuntu.com/" + res.headers.location + " %0D%0A"); @@ -96,7 +86,7 @@ var createBugReport = (title, callback) => { }); } -var getCleanOs = () => { +function getCleanOs() { try { return getos((e,gOs) => { if(gOs.os == "linux") @@ -133,294 +123,110 @@ function getLatestInstallerVersion() { } function getUpdateAvailable() { - return getLatestInstallerVersion().then((latestVersion) => { - return latestVersion != global.packageInfo.version; + return new Promise((resolve, reject) => { + getLatestInstallerVersion().then((latestVersion) => { + if(latestVersion != global.packageInfo.version) resolve(); + else reject(); + }); }); } -var getUbuntuTouchDir = () => { - var osCacheDir; - switch (process.platform) { - case "linux": - osCacheDir = path.join(process.env.HOME, '.cache'); - break; - case "darwin": - osCacheDir = path.join(process.env.HOME, 'Library/Caches'); - break; - case "win32": - osCacheDir = process.env.APPDATA; - break; - default: - throw Error("Unknown platform " + process.platform); - } - return path.join(osCacheDir, "ubports") +function getUbuntuTouchDir() { + var osCacheDir; + switch (process.platform) { + case "linux": + osCacheDir = path.join(process.env.HOME, '.cache'); + break; + case "darwin": + osCacheDir = path.join(process.env.HOME, 'Library/Caches'); + break; + case "win32": + osCacheDir = process.env.APPDATA; + break; + default: + throw Error("Unknown platform " + process.platform); + } + return path.join(osCacheDir, "ubports"); } if (!fs.existsSync(getUbuntuTouchDir())) { - mkdirp.sync(getUbuntuTouchDir()); + mkdirp.sync(getUbuntuTouchDir()); } + winston.add(winston.transports.File, { filename: path.join(getUbuntuTouchDir(), 'ubports-installer.log'), level: 'debug', // Print debug logs to the file options: { flags: 'w' } // Clear log before writing to it }); -var die = (e) => { - log.error(e); - ipcRenderer.send("die", 1); -} - -var sudoCommand = (password) => { - return isSnap() ? "" : "echo '" + password.replace(/\'/g, "'\\''") + "' | sudo -S "; -} - -var checkPassword = (password, callback) => { - if (!needRoot()) { - log.debug("no root needed") - callback(true); - return; - } - log.debug("checking password") - exec(sudoCommand(password) + "echo correct", (err, output) => { - if(err){ - if (err.message.includes("incorrect password")) { - log.debug("incorrect password") - callback(false, { - password: true - }); - } else{ - // Replace password with "" to make sure it wont get logged - // with password - log.debug("unknown sudo error") - callback(false, { - message: err.message.replace(password, "***") - }); - } - }else { - log.debug("correct password") - if (output.includes("correct")) - callback(true); - else - callback(false); - } - }); -} - -// WORKAROUND: since we are using asar packages to compress into one package we cannot use -// child_process.exec since it spans a shell and shell wont be able to access the files -// inside the asar package. -var asarExec = (file, callback) => { - tmp.dir((err, tmpDir, cleanup) => { - if (err) callback(true); - fs.copy(file, path.join(tmpDir, path.basename(file)), (err) => { - fs.chmodSync(path.join(tmpDir, path.basename(file)), 0o755); - if(err) die(err); - callback({ - exec: (cmd, cb) => { - let name = file.split('/').pop(); - cmd = cmd.replace(new RegExp(name, 'g'), path.join(tmpDir, path.basename(file))); - exec(cmd, (err, e,r) => { - // log.debug(cmd) // CAREFUL! THIS MIGHT LOG PASSWORDS! - cb(err,e,r); - }) - }, - done: () => { - fs.removeSync(tmpDir); - } - }); - }); - }); -} - -const logPlatformNativeToolsOnce = () => { - if (!platformNativeToolsLogged) { - log.debug("Using native platform tools!"); - platformNativeToolsLogged=true; - } -} - -const logPlatformFallbackToolsOnce = () => { - if (!platformFallbackToolsLogged) { - log.debug("Using fallback platform tools!"); - platformFallbackToolsLogged=true; - } -} - -const callbackHook = (callback) => { - return (a,b,c) => { - // log.debug(a,b,c); - callback(a,b,c) - } -} - -const platformToolsExec = (tool, arg, callback) => { - var tools = getPlatformTools(); - - // First check for native tools - if (tools[tool] && !global.installProperties.forceFallback) { - logPlatformNativeToolsOnce(); - var cmd = tools[tool] + " " + arg.join(" "); - // log.debug(cmd) // CAREFUL! THIS MIGHT LOG PASSWORDS! - cp.exec(cmd, {maxBuffer: 2000*1024}, callbackHook(callback)); - return true; - } - - // Try using fallback tools - if (tools.fallback[tool]) { - logPlatformFallbackToolsOnce(); - // log.debug(tools.fallback[tool] + " " + arg.join(" ")) // CAREFUL! THIS MIGHT LOG PASSWORDS! - cp.execFile(tools.fallback[tool], arg, {maxBuffer: 2000*1024}, callbackHook(callback)); - return true; - } - log.error("NO PLATFORM TOOL USED!"); - callback(true, false); - return false; +function die(e) { + log.error(e); + process.exit(-1); } -const platformToolsExecAsar = (tool, callback) => { - var tools = getPlatformTools(); - - // First check for native - if (tools[tool] && !global.installProperties.forceFallback) { - logPlatformNativeToolsOnce(); - callback({ - exec: (cmd, cb) => { - var _cmd = cmd.replace(tool, tools[tool]); - exec(_cmd, (err, e,r) => { - // log.debug(_cmd) // CAREFUL! THIS MIGHT LOG PASSWORDS! - cb(err,e,r); - }) - }, - done: () => { console.log("done platform tools") } +// WORKAROUND: the chile spawned by child_process.exec can not access files inside the asar package +function exportExecutablesFromPackage() { + getFallbackPlatformTools().forEach((tool) => { + fs.copy(tool.package, tool.cache, () => { + fs.chmodSync(tool.cache, 0o755); }); - return true; - } - - // Use fallback tools if there are no native tools installed - if (tools.fallback[tool]) { - logPlatformFallbackToolsOnce(); - asarExec(tools.fallback[tool], callback); - return true; - } - log.error("NO PLATFORM TOOL USED!"); - callback(true, false); - return false; + }); } -var maybeEXE = (platform, tool) => { - if(platform === "win32") tool+=".exe"; - return tool; +function maybeEXE(platform, tool) { + if(platform === "win32") tool+=".exe"; + return tool; } -var getPlatform = () => { +function getPlatform() { var thisPlatform = os.platform(); if(!platforms[thisPlatform]) die("Unsuported platform"); return platforms[thisPlatform]; } -// Check if we have native platform tools -const setCustomPlatformTool = (tool, executable) => { - log.info(tool + " has been set to " + executable) - customTools[tool] = executable; -} - -// Check if we have native platform tools -const getPlatformTools = () => { - var p = getNativePlatformTools(); - p["fallback"] = getFallbackPlatformTools(); - return p; -} - -const getNativePlatformTools = () => { - var ret = {}; - if (customTools["adb"]) - ret["adb"] = customTools["adb"]; - else if (commandExistsSync("adb")) - ret["adb"] = "adb"; - if (customTools["fastboot"]) - ret["fastboot"] = customTools["fastboot"]; - else if (commandExistsSync("fastboot")) - ret["fastboot"] = "fastboot"; - return ret; -} - -const getFallbackPlatformTools = () => { - var thisPlatform = os.platform(); - if(!platforms[thisPlatform]) die("Unsupported platform"); - var platformToolsPath = path.join(__dirname, "/../platform-tools/", platforms[thisPlatform]); - return { - fastboot: path.join(platformToolsPath, maybeEXE(thisPlatform, "fastboot")), - adb: path.join(platformToolsPath, maybeEXE(thisPlatform, "adb")) +function getFallbackPlatformTools() { + var thisPlatform = os.platform(); + if(!platforms[thisPlatform]) die("Unsupported platform"); + var toolInPackage = path.join(__dirname, "/../platform-tools/", platforms[thisPlatform]); + var toolInCache = path.join(utils.getUbuntuTouchDir(), 'platform-tools'); + return [ + { + package: path.join(toolInPackage, maybeEXE(thisPlatform, "fastboot")), + cache: path.join(toolInCache, maybeEXE(thisPlatform, "fastboot")) + }, + { + package: path.join(toolInPackage, maybeEXE(thisPlatform, "adb")), + cache: path.join(toolInCache, maybeEXE(thisPlatform, "adb")) } + ] } -var isSnap = () => { +function isSnap() { return process.env.SNAP_NAME } -var needRoot = () => { - if ( - (os.platform() === "win32") || - isSnap() || - !commandExistsSync("sudo") || - global.installProperties.noRoot || - global.installProperties.simulate - ) return false; - else return !process.env.SUDO_UID -} - -var ensureRoot = (m) => { - if(process.env.SUDO_UID) - return; - log.error(m) - process.exit(1); -} - -var checkFiles = (urls, callback) => { - var urls_ = []; - var next = () => { - if (urls.length <= 1) { - callback(urls_) +function checksumFile(file) { + return new Promise(function(resolve, reject) { + fs.access(path.join(file.path, path.basename(file.url)), (err) => { + if (err) { + reject(); + } else { + if (!file.checksum) { + // No checksum so return true; + resolve(); + return; } else { - urls.shift(); - check() + checksum.file(path.join(file.path, path.basename(file.url)), { + algorithm: "sha256" + }, function(err, sum) { + utils.log.debug("checked: " +path.basename(file.url), sum === file.checksum); + if (sum === file.checksum) resolve(); + else reject(); + }); } - } - var check = () => { - fs.access(path.join(urls[0].path, path.basename(urls[0].url)), (err) => { - if (err) { - log.debug("Not existing " + path.join(urls[0].path, path.basename(urls[0].url))); - urls_.push(urls[0]); - next(); - } else { - checksumFile(urls[0], (check) => { - if (check) { - log.debug(path.join(urls[0].path, path.basename(urls[0].url)) + " exists with the expected checksum, so the download will be skipped."); - next(); - } else { - log.debug("Checksum mismatch on " + path.join(urls[0].path, path.basename(urls[0].url)) + ". This file will be downloaded again."); - urls_.push(urls[0]); - next(); - } - }) - } - }) - } - check(); -} - -var checksumFile = (file, callback) => { - if (!file.checksum) { - // No checksum so return true; - callback(true); - return; - } - checksum.file(path.join(file.path, path.basename(file.url)), { - algorithm: "sha256" - }, function(err, sum) { - log.debug("checked: " +path.basename(file.url), sum === file.checksum); - callback(sum === file.checksum, sum); + } }); + }); } /* @@ -433,90 +239,76 @@ urls format: } ] */ -var downloadFiles = (urls_, downloadEvent) => { - var urls; - var totalFiles; - downloadEvent.emit("download:startCheck"); - var dl = () => { - if (!fs.existsSync(urls[0].path)) { - mkdirp.sync(urls[0].path); - } - progress(http(urls[0].url)) - .on('progress', (state) => { - downloadEvent.emit("download:progress", state.percent*100); - }) - .on('error', (err) => { - if (err) downloadEvent.emit("download:error", err); - }) - .on('end', () => { - fs.rename(path.join(urls[0].path, path.basename(urls[0].url + ".tmp")), - path.join(urls[0].path, path.basename(urls[0].url)), () => { - downloadEvent.emit("download:checking"); - checksumFile(urls[0], (check) => { - if (check) { - if (urls.length <= 1) { - downloadEvent.emit("download:done"); - } else { - urls.shift(); - downloadEvent.emit("download:next", totalFiles-urls.length+1, totalFiles); - dl() - } - } else { - downloadEvent.emit("download:error", "Checksum mismatch on file " + path.basename(urls[0].url)); - } +function downloadFiles(urls, progress, next) { + return new Promise(function(resolve, reject) { + var filesDownloaded = 0; + var overallSize = 0; + var overallDownloaded = 0; + var previousOverallDownloaded = 0; + var downloadProgress = 0; + var progressInterval = setInterval(() => { + downloadProgress = overallDownloaded/overallSize; + if (overallSize != 0) { + if (downloadProgress < 0.999) { + progress(downloadProgress, (overallDownloaded-previousOverallDownloaded)/1000000); + previousOverallDownloaded = overallDownloaded; + } else { + clearInterval(progressInterval); + progress(1, 0); + } + } + }, 1000); + Promise.all(urls.map((file) => { + return new Promise(function(resolve, reject) { + checksumFile(file).then(() => { + next(++filesDownloaded, urls.length); + resolve(); + return; + }).catch(() => { + download(file.url, file.path).on("response", (res) => { + var totalSize = eval(res.headers['content-length']); + overallSize += totalSize; + var downloaded = 0; + res.on('data', data => { + overallDownloaded += data.length; + }); + }).then(() => { + checksumFile(file).then(() => { + next(++filesDownloaded, urls.length); + resolve(); + return; + }).catch((err) => { + reject(err); + return; + }); + }); }); }); - }) - .pipe(fs.createWriteStream(path.join(urls[0].path, path.basename(urls[0].url + ".tmp")))); - } - checkFiles(urls_, (ret) => { - if (ret.length <= 0) { - downloadEvent.emit("download:done"); - } else { - urls = ret; - totalFiles = urls.length; - downloadEvent.emit("download:start", totalFiles); - dl(); - } - }) - return downloadEvent; -} - -const getRandomInt = (min, max) => { - min = Math.ceil(min); - max = Math.floor(max); - return Math.floor(Math.random() * (max - min)) + min; + })).then(() => { + resolve(); + return; + }).catch((err) => { + reject(err); + return; + }); + }); } -const hidePassword = (output, pw) => { - if (needRoot()) { - return output.replace(pw.replace(/\'/g, "'\\''"), "***"); - } else { - return output; - } +function errorToUser(error, errorLocation) { + var errorString = "Error: " + (errorLocation ? errorLocation : "Unknown") + ": " + error; + utils.log.error(errorString); + global.mainEvent.emit("user:error", errorString); } module.exports = { - setCustomPlatformTool: setCustomPlatformTool, - downloadFiles: downloadFiles, - checksumFile: checksumFile, - checkFiles: checkFiles, - log: log, - platformToolsExec: platformToolsExec, - platformToolsExecAsar: platformToolsExecAsar, - ensureRoot: ensureRoot, - isSnap: isSnap, - getPlatformTools: getPlatformTools, - getUbuntuTouchDir: getUbuntuTouchDir, - needRoot: needRoot, - sudoCommand: sudoCommand, - checkPassword: checkPassword, - createBugReport: createBugReport, - getUpdateAvailable: getUpdateAvailable, - getPlatform: getPlatform, - asarExec: asarExec, - getRandomInt: getRandomInt, - getVersion: getVersion, - hidePassword: hidePassword, - die: die + errorToUser: errorToUser, + exportExecutablesFromPackage: exportExecutablesFromPackage, + downloadFiles: downloadFiles, + log: log, + isSnap: isSnap, + getUbuntuTouchDir: getUbuntuTouchDir, + createBugReport: createBugReport, + getUpdateAvailable: getUpdateAvailable, + die: die, + setLogLevel: (level) => { winston.level = level; } }