Browse Source

Merge test into master

jojo 5 years ago
parent
commit
66aa282e06

+ 4 - 1
.babelrc

@@ -1,3 +1,6 @@
 {
-  "presets": ["@babel/preset-env"]
+  "presets": ["@babel/preset-env"],
+  "plugins": [
+    "@babel/plugin-proposal-object-rest-spread"
+  ]
 }

+ 18 - 0
.env

@@ -0,0 +1,18 @@
+//    1. Game server
+
+  // a. If you want to test app with local server (npm run server-dev) :
+SERVER_HOST="localhost"
+  // b. If you want to test app directly with running server online :
+//SERVER_HOST="149.91.81.94"
+
+
+//    2. Game DB (if "localhost" selected above)
+
+  // a. If MariaDB installed on local computer use for dev :
+//DB="localhost"
+//DB_NAME="twelve_heroes"
+
+  // b. If not, for DEV use test database : (can be managed at http://149.91.81.94:1990/phpmyadmin/)
+DB="149.91.81.94"
+DB_PORT=1986
+DB_NAME="test_twelve_heroes"

+ 1 - 1
.eslintrc.json

@@ -6,7 +6,7 @@
     "plugin:import/warnings"
   ],
   "parserOptions": {
-    "ecmaVersion": 7,
+    "ecmaVersion": 2017,
     "sourceType": "module"
   },
   "env": {

+ 1 - 3
.gitignore

@@ -54,9 +54,6 @@ typings/
 # Yarn Integrity file
 .yarn-integrity
 
-# dotenv environment variables file
-.env
-
 # next.js build output
 .next
 
@@ -66,6 +63,7 @@ db.json
 #webpack dev build
 assets
 webpack
+www
 
 #cordova build
 platforms/

+ 6 - 0
.vscode/settings.json

@@ -0,0 +1,6 @@
+{
+    "git.ignoreLimitWarning": true,
+    "typescript.validate.enable": false,
+    "tslint.enable": false,
+    "javascript.validate.enable": false
+}

+ 6 - 0
app-server/app-server.js

@@ -0,0 +1,6 @@
+const express = require('express');
+const app = express();
+const port = 2612;
+
+app.use(express.static('www_web'));
+app.listen(port, () => console.log(`Serving 12 Heroes App at http://localhost:${port}`));

+ 8 - 1
config.xml

@@ -1,5 +1,5 @@
 <?xml version='1.0' encoding='utf-8'?>
-<widget id="com.jojo.twelve-heroes" version="1.0.0" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
+<widget id="com.jojo.twelveheroes" version="1.0.0" windows-packageVersion="0.1.3" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
     <name>twelve-heroes</name>
     <description>
         A sample Apache Cordova application that responds to the deviceready event.
@@ -18,7 +18,14 @@
     <allow-intent href="geo:*" />
     <platform name="android">
         <allow-intent href="market:*" />
+        <preference name="android-minSdkVersion" value="26"/>
+        <preference name="android-targetSdkVersion" value="27"/>
     </platform>
+
+    <platform name="windows">
+        <preference name="windows-target-version" value="10.0" />
+    </platform>
+
     <platform name="ios">
         <allow-intent href="itms:*" />
         <allow-intent href="itms-apps:*" />

+ 44 - 0
index.html

@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<!--
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+     KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+-->
+<html>
+
+<head>
+  <!--
+        Customize this policy to fit your own app's needs. For more guidance, see:
+            https://github.com/apache/cordova-plugin-whitelist/blob/master/README.md#content-security-policy
+        Some notes:
+            * gap: is required only on iOS (when using UIWebView) and is needed for JS->native communication
+            * https://ssl.gstatic.com is required only on Android and is needed for TalkBack to function properly
+            * Disables use of inline scripts in order to mitigate risk of XSS vulnerabilities. To change this:
+                * Enable inline JS: add 'unsafe-inline' to default-src
+        -->
+  <!-- <meta http-equiv="Content-Security-Policy" content="default-src 'self' data: gap: https://ssl.gstatic.com 'unsafe-eval'; style-src 'self' 'unsafe-inline'; media-src *; img-src 'self' data: content: blob:;"> -->
+  <meta name="format-detection" content="telephone=no">
+  <meta name="msapplication-tap-highlight" content="no">
+  <meta name="viewport" content="initial-scale=1, width=device-width, viewport-fit=cover">
+  <!-- <link rel="stylesheet" type="text/css" href="css/index.css"> -->
+  <title>Hello World</title>
+</head>
+
+<body>
+  
+<script type="text/javascript" src="webpack/app.bundle.js"></script></body>
+
+</html>

File diff suppressed because it is too large
+ 387 - 389
package-lock.json


+ 46 - 29
package.json

@@ -6,70 +6,87 @@
     "ecosystem:cordova"
   ],
   "scripts": {
-    "server": "babel-node server/main.js",
-    "dev": "webpack --watch",
-    "precor-build": "cordova prepare",
-    "cor-build": "CORDOVA=true cordova build -- --webpackConfig webpack.config.js",
-    "cordova": "CORDOVA=true cordova run -- -w webpack.config.js",
-    "start": "npm-run-all --parallel server dev lint:watch",
+    "dev": "DEV=true webpack --watch",
+    "start": "npm-run-all --parallel dev lint:watch",
+    "server-dev": "cd server && npm run server-dev",
+    "dev-all": "npm-run-all --parallel server dev lint:watch",
+    "build-web-app": "WEB=true webpack --mode=production",
+    "appserver": "node app-server/app-server.js",
+    "server": "cd server && npm start",
+    "dev-cordova": "DEV=true CORDOVA=true webpack",
+    "postdev-cordova": "cordova prepare",
+    "build-cordova": "CORDOVA=true webpack --mode=production",
+    "postbuild-cordova": "cordova prepare",
+    "cordova-browser": "cordova run browser",
+    "win-build": "cordova build windows --win",
+    "preandroid-build": "set ORG_GRADLE_PROJECT_cdvMinSdkVersion=20 ",
+    "android-build": "cordova build android",
+    "win": "cordova run windows --win",
+    "android": "cordova run android --emulator",
     "lint": "esw webpack.config.* src --color",
     "lint:watch": "npm run lint -- --watch",
-    "ngrok": "ngrok http 3000",
-    "share": "npm-run-all --parallel server dev ngrok",
+    "lint-server": "esw server* --color",
+    "lint-server:watch": "npm run lint-server -- --watch",
+    "localtunnel": "lt --port 3000",
+    "share": "npm-run-all --parallel open:src localtunnel",
     "test": "mocha --reporter progress \"src/**/*.test.js\"",
     "test:watch": "npm run test -- --watch",
-    "clean": "git clean -fdx -e node_modules"
+    "clean": "rm -rf platforms plugins webpack www/dist www/index.html www/assets",
+    "export": "export PATH=$(npm bin):$PATH"
   },
   "author": "JOJO",
   "license": "MIT",
   "dependencies": {
-    "@babel/node": "7.6.2",
-    "@babel/polyfill": "7.6.0",
-    "express": "^4.17.1",
-    "phaser": "3.19.0"
+    "phaser": "^3.21.0",
+    "socket.io-client": "^2.3.0",
+    "cordova-android": "^8.1.0",
+    "cordova-browser": "^6.0.0",
+    "cordova-windows": "^7.0.1"
   },
   "devDependencies": {
     "@babel/cli": "7.6.2",
-    "@babel/core": "^7.6.2",
-    "@babel/plugin-proposal-object-rest-spread": "^7.6.2",
+    "@babel/core": "^7.9.0",
+    "@babel/plugin-proposal-object-rest-spread": "^7.9.0",
+    "@babel/polyfill": "7.6.0",
     "@babel/preset-env": "7.6.2",
-    "@babel/register": "^7.6.2",
+    "@babel/register": "^7.9.0",
+    "are-you-es5": "^1.3.3",
     "babel-loader": "8.0.6",
     "browser-sync": "2.26.7",
     "browser-sync-webpack-plugin": "2.2.2",
     "chai": "4.2.0",
     "chalk": "2.4.2",
     "clean-webpack-plugin": "3.0.0",
-    "copy-webpack-plugin": "^5.1.0",
-    "cordova-browser": "^6.0.0",
-    "cordova-plugin-webpack": "^0.4.7",
+    "copy-webpack-plugin": "^5.1.1",
+    "cordova": "^9.0.0",
     "cordova-plugin-whitelist": "^1.3.4",
+    "dotenv": "^8.2.0",
     "eslint": "6.4.0",
     "eslint-plugin-import": "2.18.2",
     "eslint-watch": "6.0.1",
-    "file-loader": "4.2.0",
+    "express": "^4.17.1",
+    "file-loader": "6.0.0",
+    "html-loader": "^1.0.0",
     "html-webpack-plugin": "3.2.0",
-    "mocha": "6.2.0",
-    "ngrok": "3.2.7",
+    "mocha": "^7.1.1",
     "npm-run-all": "4.1.5",
     "open": "6.4.0",
     "path": "0.12.7",
     "raw-loader": "3.1.0",
     "readline-sync": "1.4.10",
-    "socket.io": "^2.3.0",
-    "socket.io-client": "^2.3.0",
-    "webpack": "4.41.0",
-    "webpack-cli": "3.3.9",
+    "webpack": "^4.42.0",
+    "webpack-cli": "^3.3.11",
     "webpack-dev-middleware": "3.7.2",
     "webpack-md5-hash": "0.0.6"
   },
   "cordova": {
     "plugins": {
-      "cordova-plugin-whitelist": {},
-      "cordova-plugin-webpack": {}
+      "cordova-plugin-whitelist": {}
     },
     "platforms": [
-      "browser"
+      "browser",
+      "windows",
+      "android"
     ]
   }
 }

+ 3 - 0
server/.babelrc

@@ -0,0 +1,3 @@
+{
+  "extends": "../.babelrc"
+}

+ 72 - 0
server/.gitignore

@@ -0,0 +1,72 @@
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+
+# Runtime data
+pids
+*.pid
+*.seed
+*.pid.lock
+
+# Directory for instrumented libs generated by jscoverage/JSCover
+lib-cov
+
+# Coverage directory used by tools like istanbul
+coverage
+
+# nyc test coverage
+.nyc_output
+
+# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
+.grunt
+
+# Bower dependency directory (https://bower.io/)
+bower_components
+
+# node-waf configuration
+.lock-wscript
+
+# Compiled binary addons (https://nodejs.org/api/addons.html)
+build/Release
+
+# Dependency directories
+node_modules/
+jspm_packages/
+
+# TypeScript v1 declaration files
+typings/
+
+# Optional npm cache directory
+.npm
+
+# Optional eslint cache
+.eslintcache
+
+# Optional REPL history
+.node_repl_history
+
+# Output of 'npm pack'
+*.tgz
+
+# Yarn Integrity file
+.yarn-integrity
+
+# dotenv environment variables file
+.env
+
+# next.js build output
+.next
+
+#mock db
+db.json
+
+#webpack dev build
+assets
+webpack
+
+#cordova build
+platforms/
+plugins/

+ 183 - 0
server/db/mariadb-connector.js

@@ -0,0 +1,183 @@
+'use strict';
+import mariadb from 'mariadb';
+
+const JOJOAPPS_SERVER_DB='localhost';
+// const JOJOAPPS_SERVER_DB_PORT= 1986;
+const JOJOAPPS_SERVER_DB_SOCKET= '/run/mysqld/mysqld.sock';
+const DATABASE_NAME='twelve_heroes';
+
+export default class MariadbConnector {
+  constructor() {
+    let host = process.env.DB || JOJOAPPS_SERVER_DB;
+    let port = process.env.DB_PORT || 0;
+    let database = process.env.DB_NAME || DATABASE_NAME;
+    console.log('DB server : ' + host);
+    console.log('DB database : ' + database);
+
+    let mariaDbConfig={
+      host,
+      user: 'node',
+      password: 'nodejs1234',
+      database,
+      connectionLimit: 5
+    };
+
+    if (port === 0) {
+      mariaDbConfig.socketPath = JOJOAPPS_SERVER_DB_SOCKET;
+      console.log('Will use DB UNIX socket : ' + mariaDbConfig.socketPath);
+    } else {
+      mariaDbConfig.port=port;
+      console.log('Will use DB port : ' + port);
+    }
+
+    this.pool = mariadb.createPool(mariaDbConfig);
+  }
+
+  async getUsernames() {
+
+    let conn;
+    let players = [];
+    try {
+      conn = await this.pool.getConnection();
+
+      const rows_players = await conn.query("SELECT username FROM players");
+      for (const { username: u } of rows_players) {
+        players.push(u);
+      }
+    } finally {
+      if (conn && conn !== null) {
+        conn.end();
+      }
+    }
+    return players;
+  }
+
+  async addPlayer(username) {
+    console.log('mariadb add player : ', username);
+    let conn;
+    try {
+      conn = await this.pool.getConnection();
+      const val = await conn.query("INSERT INTO players value (?, NOW(),NULL)", [username]);
+      console.log('OK removing player : ', val);
+      return val;
+    } catch (err) {
+      console.log('error adding player : ', err);
+      throw err;
+    } finally {
+      if (conn && conn !== null) {
+        conn.end();
+      }
+    }
+  }
+  async removePlayer(username) {
+    console.log('mariadb remove player : ', username);
+    let conn;
+    try {
+      conn = await this.pool.getConnection();
+      const val = await conn.query("DELETE FROM players WHERE username=?", [username]);
+      console.log('OK removing player : ', val);
+      return val;
+    } catch (err) {
+      console.log('error removing player : ', err);
+      throw err;
+    } finally {
+      if (conn && conn !== null) {
+        conn.end();
+      }
+    }
+  }
+
+  async addNewGame(game) {
+    console.log('mariadb add game : ', game);
+    let conn;
+    try {
+      conn = await this.pool.getConnection();
+      const val = await conn.query("INSERT INTO games values (NULL,?,?,?,?,?,?,NOW())",
+        [game.player1,
+        game.player2,
+        game.deck,
+        convertAdvRulesToString(game.advRules),
+        game.status,
+        game.data]);
+      console.log('OK adding game : ', val);
+      return val.insertId;
+    } catch (err) {
+      console.log('error adding game : ', err);
+      throw err;
+    } finally {
+      if (conn && conn !== null) {
+        conn.end();
+      }
+    }
+  }
+
+  removeGameById(gameId) {
+    return this.removeGame("DELETE FROM games WHERE id=?", [gameId]);
+  }
+  removeGamesByPlayer1(player1Name) {
+    return this.removeGame("DELETE FROM games WHERE player1=?", [player1Name]);
+  }
+  removeGamesByPlayerAny(playerName) {
+    return this.removeGame("DELETE FROM games WHERE player1=? OR player2=?", [playerName, playerName]);
+  }
+  removeGamesByStatus(status) {
+    return this.removeGame("DELETE FROM games WHERE status=?", [status]);
+  }
+  removeGamesByDays(days) {
+    return this.removeGame("DELETE FROM games WHERE  datediff(NOW(),last_played) > ?", [days]);
+  }
+  removeFinishedGamesByDays(days) {
+    return this.removeGame("DELETE FROM games WHERE status='FINISHED' AND datediff(NOW(),last_played) > ?", [days]);
+  }
+
+  async removeGame(queryStr, queryArgs) {
+    console.log('mariadb remove game  : ', queryStr);
+    let conn;
+    try {
+      conn = await this.pool.getConnection();
+      const val = await conn.query(queryStr, queryArgs);
+      console.log('OK removing game : ', val);
+      return val;
+    } catch (err) {
+      console.log('error removing game : ', err);
+      throw err;
+    } finally {
+      if (conn && conn !== null) {
+        conn.end();
+      }
+    }
+  }
+
+  async getNonFinishedGamesForPlayer(username) {
+
+    let conn;
+    let games = [];
+    try {
+      conn = await this.pool.getConnection();
+      const res = await conn.query(
+        "SELECT * FROM`games` WHERE status != 'FINISHED' AND(player1 = ? OR player2 = '' OR player2 = ?)",
+        [username,username]);
+      for (const { player1,player2,deck,adv_rules } of res) {
+        games.push({player1,player2,deck,adv_rules});
+      }
+      console.log(`returning for ${username} : `, games);
+    } finally {
+      if (conn && conn !== null) {
+        conn.end();
+      }
+    }
+    return games;
+
+  }
+}
+let convertAdvRulesToString = function (advRulesArray) {
+  let advRulestStr = '';
+  let last = advRulesArray.length - 1;
+  advRulesArray.forEach((rule, index) => {
+    advRulestStr += rule;
+    if (index < last) {
+      advRulestStr += ',';
+    }
+  });
+  return advRulestStr;
+};

+ 0 - 33
server/main.js

@@ -1,33 +0,0 @@
-'use strict';
-import PlayerId from './players/player-id';
-import DuelController from './game-server/duel-controller';
-
-const io = require('socket.io'); //(http)
-const server = io.listen(4000);
-
-let players = [];
-
-let addNewPlayer = function (playerSocket, playerName) {
-  console.log('players length : ' + players.length + ' : ' + players);
-  if (players.length < 2) {
-    let newPlayer = new PlayerId(playerSocket,playerName);
-    console.log('push player : ' + newPlayer);
-    players.push(newPlayer);
-  }
-  if (players.length === 2) {
-    let duelController = new DuelController(players[0], players[1]);
-  }
-}
-
-server.on('connection', function (socket) {
-  console.log("A player connected with id : " + socket.id);
-  socket.on ('disconnect', () => {
-    console.log("A player disconnected with id : " + socket.id);
-  });
-
-  socket.on('auth', (playerName) => {
-    console.log(' Received auth message, player name : ' + playerName);
-    addNewPlayer(socket, playerName);
-  });
-
-})

+ 5251 - 0
server/package-lock.json

@@ -0,0 +1,5251 @@
+{
+  "name": "twelve-heroes-server",
+  "version": "1.0.0",
+  "lockfileVersion": 1,
+  "requires": true,
+  "dependencies": {
+    "@babel/node": {
+      "version": "7.6.2",
+      "resolved": "https://registry.npmjs.org/@babel/node/-/node-7.6.2.tgz",
+      "integrity": "sha512-59UxvVtRpVpL5i0KTcw41FqLNPT/Jc9k/48Rq00wfN49lAIQeRKGwZ6xX1FWlCfcIGP+5l4rfZajORvmYkhfGg==",
+      "dev": true,
+      "requires": {
+        "@babel/register": "^7.6.2",
+        "commander": "^2.8.1",
+        "core-js": "^3.2.1",
+        "lodash": "^4.17.13",
+        "node-environment-flags": "^1.0.5",
+        "regenerator-runtime": "^0.13.3",
+        "v8flags": "^3.1.1"
+      }
+    },
+    "@babel/register": {
+      "version": "7.9.0",
+      "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.9.0.tgz",
+      "integrity": "sha512-Tv8Zyi2J2VRR8g7pC5gTeIN8Ihultbmk0ocyNz8H2nEZbmhp1N6q0A1UGsQbDvGP/sNinQKUHf3SqXwqjtFv4Q==",
+      "dev": true,
+      "requires": {
+        "find-cache-dir": "^2.0.0",
+        "lodash": "^4.17.13",
+        "make-dir": "^2.1.0",
+        "pirates": "^4.0.0",
+        "source-map-support": "^0.5.16"
+      }
+    },
+    "@heroku-cli/color": {
+      "version": "1.1.14",
+      "resolved": "https://registry.npmjs.org/@heroku-cli/color/-/color-1.1.14.tgz",
+      "integrity": "sha512-2JYy//YE2YINTe21hpdVMBNc7aYFkgDeY9JUz/BCjFZmYLn0UjGaCc4BpTcMGXNJwuqoUenw2WGOFGHsJqlIDw==",
+      "dev": true,
+      "requires": {
+        "ansi-styles": "^3.2.1",
+        "chalk": "^2.4.1",
+        "strip-ansi": "^5.0.0",
+        "supports-color": "^5.5.0",
+        "tslib": "^1.9.3"
+      }
+    },
+    "@heroku-cli/command": {
+      "version": "8.3.0",
+      "resolved": "https://registry.npmjs.org/@heroku-cli/command/-/command-8.3.0.tgz",
+      "integrity": "sha512-gQoe6KnIr8q+JCYvO/6STRBsJXHw+UwwtNs5me5Zx/020u2S1I4oqi3KamcTeRTC7ZVORH3DfE30aA3HNgYXsA==",
+      "dev": true,
+      "requires": {
+        "@heroku-cli/color": "^1.1.14",
+        "@oclif/errors": "^1.2.2",
+        "cli-ux": "^4.9.3",
+        "debug": "^4.1.1",
+        "fs-extra": "^7.0.1",
+        "heroku-client": "^3.1.0",
+        "http-call": "^5.2.4",
+        "netrc-parser": "^3.1.6",
+        "open": "^6.2.0"
+      },
+      "dependencies": {
+        "http-call": {
+          "version": "5.3.0",
+          "resolved": "https://registry.npmjs.org/http-call/-/http-call-5.3.0.tgz",
+          "integrity": "sha512-ahwimsC23ICE4kPl9xTBjKB4inbRaeLyZeRunC/1Jy/Z6X8tv22MEAjK+KBOMSVLaqXPTTmd8638waVIKLGx2w==",
+          "dev": true,
+          "requires": {
+            "content-type": "^1.0.4",
+            "debug": "^4.1.1",
+            "is-retry-allowed": "^1.1.0",
+            "is-stream": "^2.0.0",
+            "parse-json": "^4.0.0",
+            "tunnel-agent": "^0.6.0"
+          }
+        }
+      }
+    },
+    "@heroku-cli/notifications": {
+      "version": "1.2.2",
+      "resolved": "https://registry.npmjs.org/@heroku-cli/notifications/-/notifications-1.2.2.tgz",
+      "integrity": "sha512-bW2R/I2TpxECPMU8bqiY9rTDHZHjRmKNPWCmXZGCg1ko3NehYfF26i2KBZ8OW3pSwcUi/cWSGhytpLPonHfQ+g==",
+      "dev": true,
+      "requires": {
+        "node-notifier": "^5.2.1"
+      }
+    },
+    "@heroku-cli/plugin-addons": {
+      "version": "1.2.31",
+      "resolved": "https://registry.npmjs.org/@heroku-cli/plugin-addons/-/plugin-addons-1.2.31.tgz",
+      "integrity": "sha1-Ytl57s/3LyYWd+x4nzfgTWFQNac=",
+      "dev": true,
+      "requires": {
+        "co": "4.6.0",
+        "co-wait": "0.0.0",
+        "heroku-cli-util": "^8.0.9",
+        "lodash": "^4.17.10",
+        "printf": "0.3.0"
+      },
+      "dependencies": {
+        "printf": {
+          "version": "0.3.0",
+          "resolved": "https://registry.npmjs.org/printf/-/printf-0.3.0.tgz",
+          "integrity": "sha512-DlJSroT2n9nkh47D4T6BHFQvsMR0L41889ECLmdbzk2BlhN0t31/vl5mHvlWiNBCNQrqG9XfpXwqmJQ2utoYwg==",
+          "dev": true
+        }
+      }
+    },
+    "@heroku-cli/plugin-addons-v5": {
+      "version": "7.24.0",
+      "resolved": "https://registry.npmjs.org/@heroku-cli/plugin-addons-v5/-/plugin-addons-v5-7.24.0.tgz",
+      "integrity": "sha512-FaPWRTiGKfBgKyIZKwOfmeDSp494rpTlmYaIpOmhWlfN8Gfy7G8pPCEnXue9Cr1B9uPeKofsEfE+yfymJ1gBhA==",
+      "dev": true,
+      "requires": {
+        "co": "4.6.0",
+        "co-wait": "0.0.0",
+        "heroku-cli-util": "^8.0.11",
+        "lodash": "^4.17.11",
+        "printf": "0.5.1"
+      }
+    },
+    "@heroku-cli/plugin-apps": {
+      "version": "7.38.2",
+      "resolved": "https://registry.npmjs.org/@heroku-cli/plugin-apps/-/plugin-apps-7.38.2.tgz",
+      "integrity": "sha512-JABAFamKlRjEZTfhdultAVkjJsYTec7Sb5TNVvpSl/fayaocJCSudGIsqcCRedwvRrIvkDN6gQ5XBneXPBD5+Q==",
+      "dev": true,
+      "requires": {
+        "@heroku-cli/color": "^1.1.14",
+        "@heroku-cli/command": "^8.3.0",
+        "@heroku-cli/schema": "^1.0.25",
+        "@oclif/command": "^1",
+        "@oclif/config": "^1",
+        "cli-ux": "^5.3.2",
+        "inquirer": "^7.0.1",
+        "shell-escape": "^0.2.0",
+        "tslib": "^1",
+        "urijs": "^1.19.1"
+      },
+      "dependencies": {
+        "clean-stack": {
+          "version": "2.2.0",
+          "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz",
+          "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==",
+          "dev": true
+        },
+        "cli-ux": {
+          "version": "5.4.5",
+          "resolved": "https://registry.npmjs.org/cli-ux/-/cli-ux-5.4.5.tgz",
+          "integrity": "sha512-5A6FuU0wPUlfCWUjtizUvNIbXElp6jN9QUJsDibs6F9cVX1kTgaMR3m6KT0R3iriEXpMrmPKV6yYS8XICNuQ6Q==",
+          "dev": true,
+          "requires": {
+            "@oclif/command": "^1.5.1",
+            "@oclif/errors": "^1.2.1",
+            "@oclif/linewrap": "^1.0.0",
+            "@oclif/screen": "^1.0.3",
+            "ansi-escapes": "^3.1.0",
+            "ansi-styles": "^3.2.1",
+            "cardinal": "^2.1.1",
+            "chalk": "^2.4.1",
+            "clean-stack": "^2.0.0",
+            "cli-progress": "^3.4.0",
+            "extract-stack": "^1.0.0",
+            "fs-extra": "^7.0.1",
+            "hyperlinker": "^1.0.0",
+            "indent-string": "^4.0.0",
+            "is-wsl": "^1.1.0",
+            "js-yaml": "^3.13.1",
+            "lodash": "^4.17.11",
+            "natural-orderby": "^2.0.1",
+            "password-prompt": "^1.1.2",
+            "semver": "^5.6.0",
+            "string-width": "^3.1.0",
+            "strip-ansi": "^5.1.0",
+            "supports-color": "^5.5.0",
+            "supports-hyperlinks": "^1.0.1",
+            "treeify": "^1.1.0",
+            "tslib": "^1.9.3"
+          }
+        },
+        "indent-string": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz",
+          "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==",
+          "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"
+          }
+        }
+      }
+    },
+    "@heroku-cli/plugin-apps-v5": {
+      "version": "7.39.1",
+      "resolved": "https://registry.npmjs.org/@heroku-cli/plugin-apps-v5/-/plugin-apps-v5-7.39.1.tgz",
+      "integrity": "sha512-EexasW63WvIcmKM7x8LDfZP5LQFYC/2i3pP5erYf7t4otm4HTFDLWsQG7vJ9DCJTKtmpImyIpgNszQuyKyFJ5w==",
+      "dev": true,
+      "requires": {
+        "@heroku-cli/command": "^8.3.0",
+        "co": "^4.6.0",
+        "filesize": "^4.0.0",
+        "fs-extra": "^7.0.1",
+        "heroku-cli-util": "^8.0.11",
+        "inquirer": "^6.2.2",
+        "js-yaml": "^3.12.1",
+        "lodash": "^4.17.11",
+        "shell-escape": "^0.2.0",
+        "sparkline": "^0.2.0",
+        "strftime": "^0.10.0",
+        "term-img": "^2.1.0",
+        "urijs": "1.19.1"
+      },
+      "dependencies": {
+        "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"
+          }
+        },
+        "figures": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz",
+          "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=",
+          "dev": true,
+          "requires": {
+            "escape-string-regexp": "^1.0.5"
+          }
+        },
+        "inquirer": {
+          "version": "6.5.2",
+          "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.5.2.tgz",
+          "integrity": "sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ==",
+          "dev": true,
+          "requires": {
+            "ansi-escapes": "^3.2.0",
+            "chalk": "^2.4.2",
+            "cli-cursor": "^2.1.0",
+            "cli-width": "^2.0.0",
+            "external-editor": "^3.0.3",
+            "figures": "^2.0.0",
+            "lodash": "^4.17.12",
+            "mute-stream": "0.0.7",
+            "run-async": "^2.2.0",
+            "rxjs": "^6.4.0",
+            "string-width": "^2.1.0",
+            "strip-ansi": "^5.1.0",
+            "through": "^2.3.6"
+          }
+        },
+        "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
+        },
+        "mute-stream": {
+          "version": "0.0.7",
+          "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz",
+          "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=",
+          "dev": true
+        },
+        "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"
+          }
+        },
+        "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"
+          }
+        },
+        "urijs": {
+          "version": "1.19.1",
+          "resolved": "https://registry.npmjs.org/urijs/-/urijs-1.19.1.tgz",
+          "integrity": "sha512-xVrGVi94ueCJNrBSTjWqjvtgvl3cyOTThp2zaMaFNGp3F542TR6sM3f2o8RqZl+AwteClSVmoCyt0ka4RjQOQg==",
+          "dev": true
+        }
+      }
+    },
+    "@heroku-cli/plugin-auth": {
+      "version": "7.39.1",
+      "resolved": "https://registry.npmjs.org/@heroku-cli/plugin-auth/-/plugin-auth-7.39.1.tgz",
+      "integrity": "sha512-FF+AoNzk4aoLiHwQ7qqwkSXHQDrBzf0RRmq0xkKzleSlg7GgVnW8wOjSwpy165nCZpkAZMrqAfzURYmOllFiHg==",
+      "dev": true,
+      "requires": {
+        "@heroku-cli/color": "^1.1.14",
+        "@heroku-cli/command": "^8.3.0",
+        "@oclif/command": "^1.5.11",
+        "@oclif/config": "^1.12.10",
+        "cli-ux": "^4.9.3",
+        "date-fns": "^2.0.0-alpha.8"
+      }
+    },
+    "@heroku-cli/plugin-autocomplete": {
+      "version": "7.39.1",
+      "resolved": "https://registry.npmjs.org/@heroku-cli/plugin-autocomplete/-/plugin-autocomplete-7.39.1.tgz",
+      "integrity": "sha512-LB88xK/YUPDulPQPtFG4g3SjDLI8USSPDpnYDyIO8H9mYtxG/51xdPlHHdG7sa3H9Ek4GsUuumIqBUBXlEM8Pg==",
+      "dev": true,
+      "requires": {
+        "@heroku-cli/command": "^8.3.0",
+        "@oclif/command": "^1.5.11",
+        "@oclif/config": "^1.12.10",
+        "chalk": "^2.4.2",
+        "cli-ux": "^4.9.3",
+        "debug": "^4.1.1",
+        "fs-extra": "^7.0.1",
+        "lodash.flatten": "^4.4.0",
+        "tslib": "1.9.3"
+      }
+    },
+    "@heroku-cli/plugin-buildpacks": {
+      "version": "7.39.1",
+      "resolved": "https://registry.npmjs.org/@heroku-cli/plugin-buildpacks/-/plugin-buildpacks-7.39.1.tgz",
+      "integrity": "sha512-o209DxvGX+rH/p/VI+RILx6n8XoreB8cNoSjd/5HiCX3t+t8rmjenMJCVKxR0wE0IHhj4/DnseknA56UovZKTQ==",
+      "dev": true,
+      "requires": {
+        "@heroku-cli/color": "^1.1.14",
+        "@heroku-cli/command": "^8.3.0",
+        "@heroku/buildpack-registry": "^1.0.1",
+        "@oclif/config": "^1.12.10",
+        "@oclif/plugin-legacy": "^1.1.4",
+        "cli-ux": "^4.9.3",
+        "heroku-cli-util": "^8.0.11",
+        "http-call": "^5.2.3",
+        "lodash": "^4.17.11",
+        "true-myth": "2.2.3",
+        "valid-url": "^1.0.9"
+      },
+      "dependencies": {
+        "@types/node": {
+          "version": "10.14.13",
+          "resolved": "https://registry.npmjs.org/@types/node/-/node-10.14.13.tgz",
+          "integrity": "sha512-yN/FNNW1UYsRR1wwAoyOwqvDuLDtVXnaJTZ898XIw/Q5cCaeVAlVwvsmXLX5PuiScBYwZsZU4JYSHB3TvfdwvQ=="
+        },
+        "ajv": {
+          "version": "6.10.2",
+          "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz",
+          "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw=="
+        },
+        "ansi-escapes": {
+          "version": "4.2.1",
+          "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.2.1.tgz",
+          "integrity": "sha512-Cg3ymMAdN10wOk/VYfLV7KCQyv7EDirJ64500sU7n9UlmioEtDuU5Gd+hj73hXSU/ex7tHJSssmyftDdkMLO8Q==",
+          "requires": {
+            "type-fest": "^0.5.2"
+          },
+          "dependencies": {
+            "type-fest": {
+              "version": "0.5.2",
+              "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.5.2.tgz",
+              "integrity": "sha512-DWkS49EQKVX//Tbupb9TFa19c7+MK1XmzkrZUR8TAktmE/DizXoaoJV6TZ/tSIPXipqNiRI6CyAe7x69Jb6RSw=="
+            }
+          }
+        },
+        "chalk": {
+          "version": "2.4.1",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz",
+          "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==",
+          "requires": {
+            "ansi-styles": "^3.2.1",
+            "escape-string-regexp": "^1.0.5",
+            "supports-color": "^5.3.0"
+          }
+        },
+        "cli-cursor": {
+          "version": "3.1.0",
+          "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz",
+          "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==",
+          "requires": {
+            "restore-cursor": "^3.1.0"
+          }
+        },
+        "debug": {
+          "version": "4.1.0",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.0.tgz",
+          "integrity": "sha512-heNPJUJIqC+xB6ayLAMHaIrmN9HKa7aQO8MGqKpvCA+uJYVcvR6l5kgdrhRuwPFHU7P5/A1w0BjByPHwpfTDKg==",
+          "requires": {
+            "ms": "^2.1.1"
+          }
+        },
+        "doctrine": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
+          "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w=="
+        },
+        "emoji-regex": {
+          "version": "8.0.0",
+          "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+          "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
+        },
+        "eslint": {
+          "version": "6.7.2",
+          "resolved": "https://registry.npmjs.org/eslint/-/eslint-6.7.2.tgz",
+          "integrity": "sha512-qMlSWJaCSxDFr8fBPvJM9kJwbazrhNcBU3+DszDW1OlEwKBBRWsJc7NJFelvwQpanHCR14cOLD41x8Eqvo3Nng==",
+          "requires": {
+            "ajv": "^6.10.0",
+            "chalk": "^2.1.0",
+            "cross-spawn": "^6.0.5",
+            "debug": "^4.0.1",
+            "doctrine": "^3.0.0",
+            "eslint-utils": "^1.4.3",
+            "file-entry-cache": "^5.0.1",
+            "globals": "^12.1.0",
+            "inquirer": "^7.0.0",
+            "js-yaml": "^3.13.1",
+            "lodash": "^4.17.14",
+            "minimatch": "^3.0.4",
+            "mkdirp": "^0.5.1",
+            "optionator": "^0.8.3",
+            "semver": "^6.1.2",
+            "strip-ansi": "^5.2.0",
+            "strip-json-comments": "^3.0.1"
+          }
+        },
+        "eslint-utils": {
+          "version": "1.4.3",
+          "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz",
+          "integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q=="
+        },
+        "figures": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/figures/-/figures-3.0.0.tgz",
+          "integrity": "sha512-HKri+WoWoUgr83pehn/SIgLOMZ9nAWC6dcGj26RY2R4F50u4+RTUz0RCrUlOV3nKRAICW1UGzyb+kcX2qK1S/g==",
+          "requires": {
+            "escape-string-regexp": "^1.0.5"
+          }
+        },
+        "file-entry-cache": {
+          "version": "5.0.1",
+          "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz",
+          "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==",
+          "requires": {
+            "flat-cache": "^2.0.1"
+          }
+        },
+        "flat-cache": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz",
+          "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==",
+          "requires": {
+            "write": "1.0.3"
+          }
+        },
+        "globals": {
+          "version": "12.3.0",
+          "resolved": "https://registry.npmjs.org/globals/-/globals-12.3.0.tgz",
+          "integrity": "sha512-wAfjdLgFsPZsklLJvOBUBmzYE8/CwhEqSBEMRXA3qxIiNtyqvjYurAtIfDh6chlEPUfmTY3MnZh5Hfh4q0UlIw==",
+          "requires": {
+            "type-fest": "^0.8.1"
+          }
+        },
+        "inquirer": {
+          "version": "7.0.0",
+          "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.0.0.tgz",
+          "integrity": "sha512-rSdC7zelHdRQFkWnhsMu2+2SO41mpv2oF2zy4tMhmiLWkcKbOAs87fWAJhVXttKVwhdZvymvnuM95EyEXg2/tQ==",
+          "requires": {
+            "ansi-escapes": "^4.2.1",
+            "chalk": "^2.4.2",
+            "cli-cursor": "^3.1.0",
+            "cli-width": "^2.0.0",
+            "external-editor": "^3.0.3",
+            "figures": "^3.0.0",
+            "lodash": "^4.17.15",
+            "mute-stream": "0.0.8",
+            "run-async": "^2.2.0",
+            "rxjs": "^6.4.0",
+            "string-width": "^4.1.0",
+            "strip-ansi": "^5.1.0",
+            "through": "^2.3.6"
+          },
+          "dependencies": {
+            "chalk": {
+              "version": "2.4.2",
+              "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+              "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+              "requires": {
+                "ansi-styles": "^3.2.1",
+                "escape-string-regexp": "^1.0.5",
+                "supports-color": "^5.3.0"
+              }
+            }
+          }
+        },
+        "is-fullwidth-code-point": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+          "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="
+        },
+        "mute-stream": {
+          "version": "0.0.8",
+          "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz",
+          "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA=="
+        },
+        "onetime": {
+          "version": "5.1.0",
+          "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.0.tgz",
+          "integrity": "sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q==",
+          "requires": {
+            "mimic-fn": "^2.1.0"
+          }
+        },
+        "optionator": {
+          "version": "0.8.3",
+          "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz",
+          "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==",
+          "requires": {
+            "fast-levenshtein": "~2.0.6"
+          }
+        },
+        "restore-cursor": {
+          "version": "3.1.0",
+          "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz",
+          "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==",
+          "requires": {
+            "onetime": "^5.1.0",
+            "signal-exit": "^3.0.2"
+          }
+        },
+        "semver": {
+          "version": "6.3.0",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+          "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
+        },
+        "string-width": {
+          "version": "4.1.0",
+          "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.1.0.tgz",
+          "integrity": "sha512-NrX+1dVVh+6Y9dnQ19pR0pP4FiEIlUvdTGn8pw6CKTNq5sgib2nIhmUNT5TAmhWmvKr3WcxBcP3E8nWezuipuQ==",
+          "requires": {
+            "emoji-regex": "^8.0.0",
+            "is-fullwidth-code-point": "^3.0.0",
+            "strip-ansi": "^5.2.0"
+          }
+        },
+        "strip-json-comments": {
+          "version": "3.0.1",
+          "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.0.1.tgz",
+          "integrity": "sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw=="
+        },
+        "tslib": {
+          "version": "1.9.3",
+          "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz",
+          "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ=="
+        },
+        "type-fest": {
+          "version": "0.8.1",
+          "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz",
+          "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA=="
+        },
+        "write": {
+          "version": "1.0.3",
+          "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz",
+          "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==",
+          "requires": {
+            "mkdirp": "^0.5.1"
+          }
+        }
+      }
+    },
+    "@heroku-cli/plugin-certs": {
+      "version": "7.39.1",
+      "resolved": "https://registry.npmjs.org/@heroku-cli/plugin-certs/-/plugin-certs-7.39.1.tgz",
+      "integrity": "sha512-Iu5UV1dly4Hz1yKD22jBhubxYtN9SCOI+0JUpQlK/QY7zmSgTP3EhF8kI811KmbsNfG3f4PLOaBhNCjjiqXnKA==",
+      "dev": true,
+      "requires": {
+        "@heroku-cli/command": "^8.3.0",
+        "@oclif/command": "^1.5.11",
+        "@oclif/config": "^1.12.10",
+        "tslib": "^1.9.3"
+      }
+    },
+    "@heroku-cli/plugin-certs-v5": {
+      "version": "7.39.0",
+      "resolved": "https://registry.npmjs.org/@heroku-cli/plugin-certs-v5/-/plugin-certs-v5-7.39.0.tgz",
+      "integrity": "sha512-hqeQEUrN1gFvkOKyUtOkphZIB3EZ4dy/Rl8a3AQQ5NYrigEFX9qpIv6NEDCAy3MJeioAC3+nmqwSUMLh7s2GVw==",
+      "dev": true,
+      "requires": {
+        "co": "4.6.0",
+        "co-wait": "0.0.0",
+        "date-fns": "^1.29.0",
+        "heroku-cli-util": "^8.0.11",
+        "inquirer": "^6.2.2",
+        "lodash": "^4.17.13",
+        "psl": "^1.1.29"
+      },
+      "dependencies": {
+        "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"
+          }
+        },
+        "date-fns": {
+          "version": "1.30.1",
+          "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.30.1.tgz",
+          "integrity": "sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw==",
+          "dev": true
+        },
+        "figures": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz",
+          "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=",
+          "dev": true,
+          "requires": {
+            "escape-string-regexp": "^1.0.5"
+          }
+        },
+        "inquirer": {
+          "version": "6.5.2",
+          "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.5.2.tgz",
+          "integrity": "sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ==",
+          "dev": true,
+          "requires": {
+            "ansi-escapes": "^3.2.0",
+            "chalk": "^2.4.2",
+            "cli-cursor": "^2.1.0",
+            "cli-width": "^2.0.0",
+            "external-editor": "^3.0.3",
+            "figures": "^2.0.0",
+            "lodash": "^4.17.12",
+            "mute-stream": "0.0.7",
+            "run-async": "^2.2.0",
+            "rxjs": "^6.4.0",
+            "string-width": "^2.1.0",
+            "strip-ansi": "^5.1.0",
+            "through": "^2.3.6"
+          }
+        },
+        "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
+        },
+        "mute-stream": {
+          "version": "0.0.7",
+          "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz",
+          "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=",
+          "dev": true
+        },
+        "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"
+          }
+        },
+        "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"
+          }
+        }
+      }
+    },
+    "@heroku-cli/plugin-ci": {
+      "version": "7.39.1",
+      "resolved": "https://registry.npmjs.org/@heroku-cli/plugin-ci/-/plugin-ci-7.39.1.tgz",
+      "integrity": "sha512-6SWtejUTpejLpDBTl2EURXKOCkeKyuXragSxVvYbe7jGK9AiOK8Kaaxk6p4I2ukCMsL/iPoT1HDxv46HV6pBuw==",
+      "dev": true,
+      "requires": {
+        "@heroku-cli/color": "^1.1.14",
+        "@heroku-cli/command": "^8.3.0",
+        "@oclif/command": "^1.5.11",
+        "@oclif/config": "^1.12.10",
+        "ansi-escapes": "3.2.0",
+        "async-file": "^2.0.2",
+        "cli-ux": "^4.9.3",
+        "debug": "^4.1.1",
+        "fs-extra": "^7.0.1",
+        "github-url-to-object": "^4.0.4",
+        "got": "^9.6.0",
+        "inquirer": "^6.2.2",
+        "phoenix": "^1.4.3",
+        "tmp": "^0.0.33",
+        "tslib": "^1.9.3",
+        "validator": "^10.11.0",
+        "ws": "^6.2.1"
+      },
+      "dependencies": {
+        "@sindresorhus/is": {
+          "version": "0.14.0",
+          "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz",
+          "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==",
+          "dev": true
+        },
+        "@types/node": {
+          "version": "10.14.13",
+          "resolved": "https://registry.npmjs.org/@types/node/-/node-10.14.13.tgz",
+          "integrity": "sha512-yN/FNNW1UYsRR1wwAoyOwqvDuLDtVXnaJTZ898XIw/Q5cCaeVAlVwvsmXLX5PuiScBYwZsZU4JYSHB3TvfdwvQ=="
+        },
+        "ajv": {
+          "version": "6.10.2",
+          "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz",
+          "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw=="
+        },
+        "ansi-regex": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
+          "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
+          "dev": true
+        },
+        "cacheable-request": {
+          "version": "6.0.0",
+          "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.0.0.tgz",
+          "integrity": "sha512-2N7AmszH/WPPpl5Z3XMw1HAP+8d+xugnKQAeKvxFZ/04dbT/CAznqwbl+7eSr3HkwdepNwtb2yx3CAMQWvG01Q==",
+          "dev": true,
+          "requires": {
+            "clone-response": "^1.0.2",
+            "get-stream": "^4.0.0",
+            "http-cache-semantics": "^4.0.0",
+            "keyv": "^3.0.0",
+            "lowercase-keys": "^1.0.1",
+            "normalize-url": "^3.1.0",
+            "responselike": "^1.0.2"
+          }
+        },
+        "chalk": {
+          "version": "2.4.1",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz",
+          "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==",
+          "requires": {
+            "ansi-styles": "^3.2.1",
+            "escape-string-regexp": "^1.0.5",
+            "supports-color": "^5.3.0"
+          }
+        },
+        "cli-cursor": {
+          "version": "3.1.0",
+          "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz",
+          "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==",
+          "requires": {
+            "restore-cursor": "^3.1.0"
+          }
+        },
+        "doctrine": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
+          "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w=="
+        },
+        "emoji-regex": {
+          "version": "8.0.0",
+          "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+          "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
+        },
+        "eslint": {
+          "version": "6.7.2",
+          "resolved": "https://registry.npmjs.org/eslint/-/eslint-6.7.2.tgz",
+          "integrity": "sha512-qMlSWJaCSxDFr8fBPvJM9kJwbazrhNcBU3+DszDW1OlEwKBBRWsJc7NJFelvwQpanHCR14cOLD41x8Eqvo3Nng==",
+          "requires": {
+            "ajv": "^6.10.0",
+            "chalk": "^2.1.0",
+            "cross-spawn": "^6.0.5",
+            "debug": "^4.0.1",
+            "doctrine": "^3.0.0",
+            "eslint-utils": "^1.4.3",
+            "file-entry-cache": "^5.0.1",
+            "globals": "^12.1.0",
+            "inquirer": "^7.0.0",
+            "js-yaml": "^3.13.1",
+            "lodash": "^4.17.14",
+            "minimatch": "^3.0.4",
+            "mkdirp": "^0.5.1",
+            "optionator": "^0.8.3",
+            "semver": "^6.1.2",
+            "strip-ansi": "^5.2.0",
+            "strip-json-comments": "^3.0.1"
+          },
+          "dependencies": {
+            "ansi-escapes": {
+              "version": "4.2.1",
+              "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.2.1.tgz",
+              "integrity": "sha512-Cg3ymMAdN10wOk/VYfLV7KCQyv7EDirJ64500sU7n9UlmioEtDuU5Gd+hj73hXSU/ex7tHJSssmyftDdkMLO8Q==",
+              "requires": {
+                "type-fest": "^0.5.2"
+              }
+            },
+            "debug": {
+              "version": "4.1.0",
+              "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.0.tgz",
+              "integrity": "sha512-heNPJUJIqC+xB6ayLAMHaIrmN9HKa7aQO8MGqKpvCA+uJYVcvR6l5kgdrhRuwPFHU7P5/A1w0BjByPHwpfTDKg==",
+              "requires": {
+                "ms": "^2.1.1"
+              }
+            },
+            "inquirer": {
+              "version": "7.0.0",
+              "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.0.0.tgz",
+              "integrity": "sha512-rSdC7zelHdRQFkWnhsMu2+2SO41mpv2oF2zy4tMhmiLWkcKbOAs87fWAJhVXttKVwhdZvymvnuM95EyEXg2/tQ==",
+              "requires": {
+                "ansi-escapes": "^4.2.1",
+                "chalk": "^2.4.2",
+                "cli-cursor": "^3.1.0",
+                "cli-width": "^2.0.0",
+                "external-editor": "^3.0.3",
+                "figures": "^3.0.0",
+                "lodash": "^4.17.15",
+                "mute-stream": "0.0.8",
+                "run-async": "^2.2.0",
+                "rxjs": "^6.4.0",
+                "string-width": "^4.1.0",
+                "strip-ansi": "^5.1.0",
+                "through": "^2.3.6"
+              },
+              "dependencies": {
+                "chalk": {
+                  "version": "2.4.2",
+                  "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+                  "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+                  "requires": {
+                    "ansi-styles": "^3.2.1",
+                    "escape-string-regexp": "^1.0.5",
+                    "supports-color": "^5.3.0"
+                  }
+                }
+              }
+            },
+            "semver": {
+              "version": "6.3.0",
+              "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+              "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
+            },
+            "type-fest": {
+              "version": "0.5.2",
+              "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.5.2.tgz",
+              "integrity": "sha512-DWkS49EQKVX//Tbupb9TFa19c7+MK1XmzkrZUR8TAktmE/DizXoaoJV6TZ/tSIPXipqNiRI6CyAe7x69Jb6RSw=="
+            }
+          }
+        },
+        "eslint-utils": {
+          "version": "1.4.3",
+          "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz",
+          "integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q=="
+        },
+        "figures": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/figures/-/figures-3.0.0.tgz",
+          "integrity": "sha512-HKri+WoWoUgr83pehn/SIgLOMZ9nAWC6dcGj26RY2R4F50u4+RTUz0RCrUlOV3nKRAICW1UGzyb+kcX2qK1S/g==",
+          "requires": {
+            "escape-string-regexp": "^1.0.5"
+          }
+        },
+        "file-entry-cache": {
+          "version": "5.0.1",
+          "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz",
+          "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==",
+          "requires": {
+            "flat-cache": "^2.0.1"
+          }
+        },
+        "flat-cache": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz",
+          "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==",
+          "requires": {
+            "write": "1.0.3"
+          }
+        },
+        "get-stream": {
+          "version": "4.1.0",
+          "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz",
+          "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==",
+          "dev": true,
+          "requires": {
+            "pump": "^3.0.0"
+          }
+        },
+        "globals": {
+          "version": "12.3.0",
+          "resolved": "https://registry.npmjs.org/globals/-/globals-12.3.0.tgz",
+          "integrity": "sha512-wAfjdLgFsPZsklLJvOBUBmzYE8/CwhEqSBEMRXA3qxIiNtyqvjYurAtIfDh6chlEPUfmTY3MnZh5Hfh4q0UlIw==",
+          "requires": {
+            "type-fest": "^0.8.1"
+          }
+        },
+        "got": {
+          "version": "9.6.0",
+          "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz",
+          "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==",
+          "dev": true,
+          "requires": {
+            "@sindresorhus/is": "^0.14.0",
+            "@szmarczak/http-timer": "^1.1.2",
+            "cacheable-request": "^6.0.0",
+            "decompress-response": "^3.3.0",
+            "duplexer3": "^0.1.4",
+            "get-stream": "^4.1.0",
+            "lowercase-keys": "^1.0.1",
+            "mimic-response": "^1.0.1",
+            "p-cancelable": "^1.0.0",
+            "to-readable-stream": "^1.0.0",
+            "url-parse-lax": "^3.0.0"
+          }
+        },
+        "http-cache-semantics": {
+          "version": "4.0.1",
+          "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz",
+          "integrity": "sha512-OO/9K7uFN30qwAKvslzmCTbimZ/uRjtdN5S50vvWLwUKqFuZj0n96XyCzF5tHRHEO/Q4JYC01hv41gkX06gmHA==",
+          "dev": true
+        },
+        "inquirer": {
+          "version": "6.5.2",
+          "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.5.2.tgz",
+          "integrity": "sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ==",
+          "dev": true,
+          "requires": {
+            "ansi-escapes": "^3.2.0",
+            "chalk": "^2.4.2",
+            "cli-cursor": "^2.1.0",
+            "cli-width": "^2.0.0",
+            "external-editor": "^3.0.3",
+            "figures": "^2.0.0",
+            "lodash": "^4.17.12",
+            "mute-stream": "0.0.7",
+            "run-async": "^2.2.0",
+            "rxjs": "^6.4.0",
+            "string-width": "^2.1.0",
+            "strip-ansi": "^5.1.0",
+            "through": "^2.3.6"
+          },
+          "dependencies": {
+            "chalk": {
+              "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",
+                "supports-color": "^5.3.0"
+              }
+            },
+            "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"
+              }
+            },
+            "figures": {
+              "version": "2.0.0",
+              "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz",
+              "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=",
+              "dev": true,
+              "requires": {
+                "escape-string-regexp": "^1.0.5"
+              }
+            },
+            "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
+            },
+            "mute-stream": {
+              "version": "0.0.7",
+              "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz",
+              "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=",
+              "dev": true
+            },
+            "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"
+              }
+            },
+            "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"
+              }
+            },
+            "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"
+              },
+              "dependencies": {
+                "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"
+                  }
+                }
+              }
+            }
+          }
+        },
+        "is-fullwidth-code-point": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+          "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="
+        },
+        "keyv": {
+          "version": "3.1.0",
+          "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz",
+          "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==",
+          "dev": true,
+          "requires": {
+            "json-buffer": "3.0.0"
+          }
+        },
+        "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
+        },
+        "mute-stream": {
+          "version": "0.0.8",
+          "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz",
+          "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA=="
+        },
+        "nock": {
+          "version": "9.6.1",
+          "resolved": "https://registry.npmjs.org/nock/-/nock-9.6.1.tgz",
+          "integrity": "sha512-EDgl/WgNQ0C1BZZlASOQkQdE6tAWXJi8QQlugqzN64JJkvZ7ILijZuG24r4vCC7yOfnm6HKpne5AGExLGCeBWg==",
+          "requires": {
+            "debug": "^3.1.0",
+            "lodash": "^4.17.5",
+            "mkdirp": "^0.5.0",
+            "semver": "^5.5.0"
+          },
+          "dependencies": {
+            "debug": {
+              "version": "3.2.6",
+              "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
+              "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
+              "requires": {
+                "ms": "^2.1.1"
+              }
+            }
+          }
+        },
+        "normalize-url": {
+          "version": "3.3.0",
+          "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-3.3.0.tgz",
+          "integrity": "sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg==",
+          "dev": true
+        },
+        "onetime": {
+          "version": "5.1.0",
+          "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.0.tgz",
+          "integrity": "sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q=="
+        },
+        "optionator": {
+          "version": "0.8.3",
+          "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz",
+          "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==",
+          "requires": {
+            "fast-levenshtein": "~2.0.6"
+          }
+        },
+        "p-cancelable": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.0.0.tgz",
+          "integrity": "sha512-USgPoaC6tkTGlS831CxsVdmZmyb8tR1D+hStI84MyckLOzfJlYQUweomrwE3D8T7u5u5GVuW064LT501wHTYYA==",
+          "dev": true
+        },
+        "restore-cursor": {
+          "version": "3.1.0",
+          "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz",
+          "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==",
+          "requires": {
+            "onetime": "^5.1.0",
+            "signal-exit": "^3.0.2"
+          }
+        },
+        "string-width": {
+          "version": "4.1.0",
+          "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.1.0.tgz",
+          "integrity": "sha512-NrX+1dVVh+6Y9dnQ19pR0pP4FiEIlUvdTGn8pw6CKTNq5sgib2nIhmUNT5TAmhWmvKr3WcxBcP3E8nWezuipuQ==",
+          "requires": {
+            "emoji-regex": "^8.0.0",
+            "is-fullwidth-code-point": "^3.0.0",
+            "strip-ansi": "^5.2.0"
+          }
+        },
+        "strip-json-comments": {
+          "version": "3.0.1",
+          "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.0.1.tgz",
+          "integrity": "sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw=="
+        },
+        "type-fest": {
+          "version": "0.8.1",
+          "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz",
+          "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA=="
+        },
+        "write": {
+          "version": "1.0.3",
+          "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz",
+          "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==",
+          "requires": {
+            "mkdirp": "^0.5.1"
+          }
+        },
+        "ws": {
+          "version": "6.2.1",
+          "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz",
+          "integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==",
+          "dev": true,
+          "requires": {
+            "async-limiter": "~1.0.0"
+          }
+        }
+      }
+    },
+    "@heroku-cli/plugin-ci-v5": {
+      "version": "7.39.1",
+      "resolved": "https://registry.npmjs.org/@heroku-cli/plugin-ci-v5/-/plugin-ci-v5-7.39.1.tgz",
+      "integrity": "sha512-AylNg5sl1Fi7qsgaVOF6P8bKWBM/YP5/7KN6FkJpFbGGzaiMZBl3vOVI7qHHbysbjcY/+H/b4waJ63nr3TlHWg==",
+      "dev": true,
+      "requires": {
+        "@heroku-cli/command": "^8.3.0",
+        "@heroku-cli/plugin-run-v5": "^7.39.1",
+        "ansi-escapes": "3.2.0",
+        "bluebird": "^3.5.3",
+        "co": "^4.6.0",
+        "co-wait": "0.0.0",
+        "github-url-to-object": "^4.0.4",
+        "got": "^8.3.2",
+        "heroku-cli-util": "^8.0.11",
+        "inquirer": "^7.0.0",
+        "lodash.flatten": "^4.4.0",
+        "shell-escape": "^0.2.0",
+        "temp": "^0.8.3",
+        "validator": "^12.0.0"
+      },
+      "dependencies": {
+        "validator": {
+          "version": "12.2.0",
+          "resolved": "https://registry.npmjs.org/validator/-/validator-12.2.0.tgz",
+          "integrity": "sha512-jJfE/DW6tIK1Ek8nCfNFqt8Wb3nzMoAbocBF6/Icgg1ZFSBpObdnwVY2jQj6qUqzhx5jc71fpvBWyLGO7Xl+nQ==",
+          "dev": true
+        }
+      }
+    },
+    "@heroku-cli/plugin-config": {
+      "version": "7.39.1",
+      "resolved": "https://registry.npmjs.org/@heroku-cli/plugin-config/-/plugin-config-7.39.1.tgz",
+      "integrity": "sha512-NybGXDM0csvvZiQByvSD2T0VZzXSEgp4ogHq9H8bd3s+0/De1aoBokEyl78HbqmuRkBRKJfS2MlbB7neD1z75g==",
+      "dev": true,
+      "requires": {
+        "@heroku-cli/color": "^1.1.14",
+        "@heroku-cli/command": "^8.3.0",
+        "@oclif/command": "^1.5.11",
+        "@oclif/config": "^1.12.10",
+        "cli-ux": "^4.9.3",
+        "edit-string": "^1.1.6",
+        "lodash": "^4.17.11",
+        "shell-quote": "^1.6.1"
+      }
+    },
+    "@heroku-cli/plugin-container-registry-v5": {
+      "version": "7.28.0",
+      "resolved": "https://registry.npmjs.org/@heroku-cli/plugin-container-registry-v5/-/plugin-container-registry-v5-7.28.0.tgz",
+      "integrity": "sha512-by/BAZcltQZItEtQomgZsbo+6XRF7yBkvvechaRSsyjLHOY1JO9BOvwpefpSXTI2hvzVPeD064+qhzKvnY1XVQ==",
+      "dev": true,
+      "requires": {
+        "glob": "^7.1.3",
+        "heroku-cli-util": "^8.0.11",
+        "http-call": "^5.2.3",
+        "inquirer": "^6.2.2"
+      },
+      "dependencies": {
+        "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"
+          }
+        },
+        "figures": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz",
+          "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=",
+          "dev": true,
+          "requires": {
+            "escape-string-regexp": "^1.0.5"
+          }
+        },
+        "inquirer": {
+          "version": "6.5.2",
+          "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.5.2.tgz",
+          "integrity": "sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ==",
+          "dev": true,
+          "requires": {
+            "ansi-escapes": "^3.2.0",
+            "chalk": "^2.4.2",
+            "cli-cursor": "^2.1.0",
+            "cli-width": "^2.0.0",
+            "external-editor": "^3.0.3",
+            "figures": "^2.0.0",
+            "lodash": "^4.17.12",
+            "mute-stream": "0.0.7",
+            "run-async": "^2.2.0",
+            "rxjs": "^6.4.0",
+            "string-width": "^2.1.0",
+            "strip-ansi": "^5.1.0",
+            "through": "^2.3.6"
+          }
+        },
+        "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
+        },
+        "mute-stream": {
+          "version": "0.0.7",
+          "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz",
+          "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=",
+          "dev": true
+        },
+        "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"
+          }
+        },
+        "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"
+          }
+        }
+      }
+    },
+    "@heroku-cli/plugin-git": {
+      "version": "7.39.1",
+      "resolved": "https://registry.npmjs.org/@heroku-cli/plugin-git/-/plugin-git-7.39.1.tgz",
+      "integrity": "sha512-sEaSL2eiOLF/gZlYs3oINn6o2R2RH8zLwye+FmwlUr9QMU5MNcn2u51ZsF+XXSxKKRGAac1f+42ruMDhCNn8VA==",
+      "dev": true,
+      "requires": {
+        "@heroku-cli/color": "^1.1.14",
+        "@heroku-cli/command": "^8.3.0",
+        "@oclif/command": "^1.5.11",
+        "@oclif/config": "^1.12.10",
+        "cli-ux": "^4.9.3",
+        "debug": "4.1.1"
+      }
+    },
+    "@heroku-cli/plugin-local": {
+      "version": "7.38.1",
+      "resolved": "https://registry.npmjs.org/@heroku-cli/plugin-local/-/plugin-local-7.38.1.tgz",
+      "integrity": "sha512-AA+FO5aI+O96Txyss2mht2Z9JOpmcc5W02L9yNwZznGy5mb257+bvCpUL3xeNYVxSeKykuM4ksSnLRJnHcV+HQ==",
+      "dev": true,
+      "requires": {
+        "@heroku-cli/command": "^8.3.0",
+        "@oclif/command": "^1",
+        "@oclif/config": "^1",
+        "foreman": "^3.0.1",
+        "tslib": "^1"
+      }
+    },
+    "@heroku-cli/plugin-oauth-v5": {
+      "version": "7.39.1",
+      "resolved": "https://registry.npmjs.org/@heroku-cli/plugin-oauth-v5/-/plugin-oauth-v5-7.39.1.tgz",
+      "integrity": "sha512-7/JTGp/buoFZ4ffyepsgQ/HixZ2/no5IfPaCSkGRh/68egiUVNgJkxgzK8SQ30xrVZNoCUvqAlYX5xhmBLnwyg==",
+      "dev": true,
+      "requires": {
+        "co": "^4.6.0",
+        "date-fns": "^1.29.0",
+        "heroku-cli-util": "^8.0.11",
+        "lodash": "^4.17.11"
+      },
+      "dependencies": {
+        "date-fns": {
+          "version": "1.30.1",
+          "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.30.1.tgz",
+          "integrity": "sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw==",
+          "dev": true
+        }
+      }
+    },
+    "@heroku-cli/plugin-orgs-v5": {
+      "version": "7.38.1",
+      "resolved": "https://registry.npmjs.org/@heroku-cli/plugin-orgs-v5/-/plugin-orgs-v5-7.38.1.tgz",
+      "integrity": "sha512-+CXvwuuaNJShO0alZk7J066BRwk9j3RVD5SI8xLMHDz+Mcob2cda6tAX1J0nBVGCqaHNQedSRoYzA4Vq31SDkw==",
+      "dev": true,
+      "requires": {
+        "@heroku-cli/command": "^8.3.0",
+        "co": "^4.6.0",
+        "heroku-cli-util": "^8.0.11",
+        "inquirer": "^6.2.2",
+        "lodash": "^4.17.11",
+        "lodash.flatten": "^4.4.0"
+      },
+      "dependencies": {
+        "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"
+          }
+        },
+        "figures": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz",
+          "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=",
+          "dev": true,
+          "requires": {
+            "escape-string-regexp": "^1.0.5"
+          }
+        },
+        "inquirer": {
+          "version": "6.5.2",
+          "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.5.2.tgz",
+          "integrity": "sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ==",
+          "dev": true,
+          "requires": {
+            "ansi-escapes": "^3.2.0",
+            "chalk": "^2.4.2",
+            "cli-cursor": "^2.1.0",
+            "cli-width": "^2.0.0",
+            "external-editor": "^3.0.3",
+            "figures": "^2.0.0",
+            "lodash": "^4.17.12",
+            "mute-stream": "0.0.7",
+            "run-async": "^2.2.0",
+            "rxjs": "^6.4.0",
+            "string-width": "^2.1.0",
+            "strip-ansi": "^5.1.0",
+            "through": "^2.3.6"
+          }
+        },
+        "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
+        },
+        "mute-stream": {
+          "version": "0.0.7",
+          "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz",
+          "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=",
+          "dev": true
+        },
+        "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"
+          }
+        },
+        "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"
+          }
+        }
+      }
+    },
+    "@heroku-cli/plugin-pg-v5": {
+      "version": "7.37.0",
+      "resolved": "https://registry.npmjs.org/@heroku-cli/plugin-pg-v5/-/plugin-pg-v5-7.37.0.tgz",
+      "integrity": "sha512-2/ex9SOpfWnnmkVEK5c2VI2E9Gue4erc/UHmvp53gYkRZRdSZ60uCsXtGUQixLMQb8pXwR7eeXFp7zsTrdwNXA==",
+      "dev": true,
+      "requires": {
+        "@heroku-cli/plugin-addons": "^1.2.29",
+        "bytes": "^3.1.0",
+        "co": "^4.6.0",
+        "co-wait": "^0.0.0",
+        "debug": "^4.1.1",
+        "filesize": "^4.0.0",
+        "heroku-cli-util": "^8.0.11",
+        "lodash": "^4.17.11",
+        "mkdirp": "^0.5.1",
+        "node-notifier": "^5.4.0",
+        "smooth-progress": "^1.1.0",
+        "strip-eof": "^1.0.0",
+        "tunnel-ssh": "^4.1.4"
+      }
+    },
+    "@heroku-cli/plugin-pipelines": {
+      "version": "7.38.1",
+      "resolved": "https://registry.npmjs.org/@heroku-cli/plugin-pipelines/-/plugin-pipelines-7.38.1.tgz",
+      "integrity": "sha512-pkGycD+vK9ag2kToOTQKac+OGnVIwXwK9W1TSW2MAGYvOQCmsJ9dJ2MNPNYUqLJBoUwT+Gj2qz9tFNvjcng1sw==",
+      "dev": true,
+      "requires": {
+        "@heroku-cli/color": "^1.1.14",
+        "@heroku-cli/command": "^8.3.0",
+        "@heroku-cli/schema": "^1.0.25",
+        "@oclif/command": "^1",
+        "@oclif/config": "^1",
+        "cli-ux": "^5.2.1",
+        "got": "^9.6.0",
+        "heroku-cli-util": "^8.0.11",
+        "http-call": "^5.2.4",
+        "inquirer": "^7.0.0",
+        "lodash.keyby": "^4.6.0",
+        "lodash.sortby": "^4.7.0",
+        "validator": "^10.11.0"
+      },
+      "dependencies": {
+        "@sindresorhus/is": {
+          "version": "0.14.0",
+          "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz",
+          "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==",
+          "dev": true
+        },
+        "cacheable-request": {
+          "version": "6.1.0",
+          "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz",
+          "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==",
+          "dev": true,
+          "requires": {
+            "clone-response": "^1.0.2",
+            "get-stream": "^5.1.0",
+            "http-cache-semantics": "^4.0.0",
+            "keyv": "^3.0.0",
+            "lowercase-keys": "^2.0.0",
+            "normalize-url": "^4.1.0",
+            "responselike": "^1.0.2"
+          },
+          "dependencies": {
+            "get-stream": {
+              "version": "5.1.0",
+              "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.1.0.tgz",
+              "integrity": "sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw==",
+              "dev": true,
+              "requires": {
+                "pump": "^3.0.0"
+              }
+            },
+            "lowercase-keys": {
+              "version": "2.0.0",
+              "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz",
+              "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==",
+              "dev": true
+            }
+          }
+        },
+        "clean-stack": {
+          "version": "2.2.0",
+          "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz",
+          "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==",
+          "dev": true
+        },
+        "cli-ux": {
+          "version": "5.4.5",
+          "resolved": "https://registry.npmjs.org/cli-ux/-/cli-ux-5.4.5.tgz",
+          "integrity": "sha512-5A6FuU0wPUlfCWUjtizUvNIbXElp6jN9QUJsDibs6F9cVX1kTgaMR3m6KT0R3iriEXpMrmPKV6yYS8XICNuQ6Q==",
+          "dev": true,
+          "requires": {
+            "@oclif/command": "^1.5.1",
+            "@oclif/errors": "^1.2.1",
+            "@oclif/linewrap": "^1.0.0",
+            "@oclif/screen": "^1.0.3",
+            "ansi-escapes": "^3.1.0",
+            "ansi-styles": "^3.2.1",
+            "cardinal": "^2.1.1",
+            "chalk": "^2.4.1",
+            "clean-stack": "^2.0.0",
+            "cli-progress": "^3.4.0",
+            "extract-stack": "^1.0.0",
+            "fs-extra": "^7.0.1",
+            "hyperlinker": "^1.0.0",
+            "indent-string": "^4.0.0",
+            "is-wsl": "^1.1.0",
+            "js-yaml": "^3.13.1",
+            "lodash": "^4.17.11",
+            "natural-orderby": "^2.0.1",
+            "password-prompt": "^1.1.2",
+            "semver": "^5.6.0",
+            "string-width": "^3.1.0",
+            "strip-ansi": "^5.1.0",
+            "supports-color": "^5.5.0",
+            "supports-hyperlinks": "^1.0.1",
+            "treeify": "^1.1.0",
+            "tslib": "^1.9.3"
+          }
+        },
+        "get-stream": {
+          "version": "4.1.0",
+          "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz",
+          "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==",
+          "dev": true,
+          "requires": {
+            "pump": "^3.0.0"
+          }
+        },
+        "got": {
+          "version": "9.6.0",
+          "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz",
+          "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==",
+          "dev": true,
+          "requires": {
+            "@sindresorhus/is": "^0.14.0",
+            "@szmarczak/http-timer": "^1.1.2",
+            "cacheable-request": "^6.0.0",
+            "decompress-response": "^3.3.0",
+            "duplexer3": "^0.1.4",
+            "get-stream": "^4.1.0",
+            "lowercase-keys": "^1.0.1",
+            "mimic-response": "^1.0.1",
+            "p-cancelable": "^1.0.0",
+            "to-readable-stream": "^1.0.0",
+            "url-parse-lax": "^3.0.0"
+          }
+        },
+        "http-cache-semantics": {
+          "version": "4.1.0",
+          "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz",
+          "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==",
+          "dev": true
+        },
+        "http-call": {
+          "version": "5.3.0",
+          "resolved": "https://registry.npmjs.org/http-call/-/http-call-5.3.0.tgz",
+          "integrity": "sha512-ahwimsC23ICE4kPl9xTBjKB4inbRaeLyZeRunC/1Jy/Z6X8tv22MEAjK+KBOMSVLaqXPTTmd8638waVIKLGx2w==",
+          "dev": true,
+          "requires": {
+            "content-type": "^1.0.4",
+            "debug": "^4.1.1",
+            "is-retry-allowed": "^1.1.0",
+            "is-stream": "^2.0.0",
+            "parse-json": "^4.0.0",
+            "tunnel-agent": "^0.6.0"
+          }
+        },
+        "indent-string": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz",
+          "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==",
+          "dev": true
+        },
+        "normalize-url": {
+          "version": "4.5.0",
+          "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.0.tgz",
+          "integrity": "sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ==",
+          "dev": true
+        },
+        "p-cancelable": {
+          "version": "1.1.0",
+          "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz",
+          "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==",
+          "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"
+          }
+        }
+      }
+    },
+    "@heroku-cli/plugin-ps": {
+      "version": "7.39.1",
+      "resolved": "https://registry.npmjs.org/@heroku-cli/plugin-ps/-/plugin-ps-7.39.1.tgz",
+      "integrity": "sha512-/Du8r/MB8tbpi3z6+4RtUG0YqFiOZq5GuzjeU3dtkE+XyRYIeP2YAEI1BXSwd84buFLvkcR9vMctbvMMT8SOhw==",
+      "dev": true,
+      "requires": {
+        "@heroku-cli/color": "^1.1.14",
+        "@heroku-cli/command": "^8.3.0",
+        "@oclif/command": "^1.5.11",
+        "@oclif/config": "^1.12.10",
+        "cli-ux": "^4.9.3",
+        "lodash": "^4.17.11"
+      }
+    },
+    "@heroku-cli/plugin-ps-exec": {
+      "version": "2.3.8",
+      "resolved": "https://registry.npmjs.org/@heroku-cli/plugin-ps-exec/-/plugin-ps-exec-2.3.8.tgz",
+      "integrity": "sha512-r+wCiFtNEJ+hsztVvinzZYaLL00s3Ovn+IbTQIQkeKG+CpFXa3yrBQsyNvfIs3yUdEF5n2086czJ1iaAq/qyLQ==",
+      "dev": true,
+      "requires": {
+        "heroku-cli-util": "^8.0.8",
+        "heroku-exec-util": "0.7.5",
+        "lodash": "^4.17.13"
+      }
+    },
+    "@heroku-cli/plugin-redis-v5": {
+      "version": "7.25.0",
+      "resolved": "https://registry.npmjs.org/@heroku-cli/plugin-redis-v5/-/plugin-redis-v5-7.25.0.tgz",
+      "integrity": "sha512-+/1wHfBCTn5wSRvjcZpSu6STO3NdkHwitnvjSr01ik/fnszGwYGbKubXJMbdlW2Ejm1GIZP3okkak9LLlB8jlg==",
+      "dev": true,
+      "requires": {
+        "heroku-cli-util": "^8.0.11",
+        "redis-parser": "^3.0.0",
+        "ssh2": "^0.6.1"
+      },
+      "dependencies": {
+        "ssh2": {
+          "version": "0.6.2",
+          "resolved": "https://registry.npmjs.org/ssh2/-/ssh2-0.6.2.tgz",
+          "integrity": "sha512-DJ+dOhXEEsmNpcQTI0x69FS++JH6qqL/ltEHf01pI1SSLMAcmD+hL4jRwvHjPwynPsmSUbHJ/WIZYzROfqZWjA==",
+          "dev": true,
+          "requires": {
+            "ssh2-streams": "~0.2.0"
+          }
+        },
+        "ssh2-streams": {
+          "version": "0.2.1",
+          "resolved": "https://registry.npmjs.org/ssh2-streams/-/ssh2-streams-0.2.1.tgz",
+          "integrity": "sha512-3zCOsmunh1JWgPshfhKmBCL3lUtHPoh+a/cyQ49Ft0Q0aF7xgN06b76L+oKtFi0fgO57FLjFztb1GlJcEZ4a3Q==",
+          "dev": true,
+          "requires": {
+            "asn1": "~0.2.0",
+            "semver": "^5.1.0",
+            "streamsearch": "~0.1.2"
+          }
+        }
+      }
+    },
+    "@heroku-cli/plugin-run-v5": {
+      "version": "7.39.1",
+      "resolved": "https://registry.npmjs.org/@heroku-cli/plugin-run-v5/-/plugin-run-v5-7.39.1.tgz",
+      "integrity": "sha512-Lsio+HkPA9Xq8acZ9NMLtFd6YhhdnLBYYxjh00cAQcc2DKwpK6TdTMWx3ojV6uhHRWuInQ8kXIIQdOrpQnCFqQ==",
+      "dev": true,
+      "requires": {
+        "@heroku-cli/color": "^1.1.14",
+        "@heroku-cli/command": "^8.3.0",
+        "@heroku-cli/notifications": "^1.2.2",
+        "@heroku/eventsource": "^1.0.7",
+        "co": "4.6.0",
+        "fs-extra": "^7.0.1",
+        "heroku-cli-util": "^8.0.11",
+        "shellwords": "^0.1.1"
+      }
+    },
+    "@heroku-cli/plugin-spaces": {
+      "version": "7.38.1",
+      "resolved": "https://registry.npmjs.org/@heroku-cli/plugin-spaces/-/plugin-spaces-7.38.1.tgz",
+      "integrity": "sha512-qOyAzXJKSnjUEfP3MB7evjhXAExKTo2hpTNv9H1ypOxTPvZhWqG6EpgmTXfvlOUbVrO9N/GlSdfG4mKEacjM8Q==",
+      "dev": true,
+      "requires": {
+        "@heroku-cli/command": "^8.3.0",
+        "@heroku-cli/notifications": "^1.2.2",
+        "co": "4.6.0",
+        "heroku-cli-util": "^8.0.11",
+        "lodash": "^4.17.11",
+        "strftime": "^0.10.0"
+      }
+    },
+    "@heroku-cli/plugin-status": {
+      "version": "7.38.1",
+      "resolved": "https://registry.npmjs.org/@heroku-cli/plugin-status/-/plugin-status-7.38.1.tgz",
+      "integrity": "sha512-rv3Xmos7AXjVNGWoCoU4Z0OcjlRoyGkEDkhmzW4JLekRUtLlsDxm4O1oCGm1+vHfrSjBJpRVj8cL6HcFhYnqww==",
+      "dev": true,
+      "requires": {
+        "@heroku-cli/color": "^1.1.14",
+        "@heroku-cli/command": "^8.3.0",
+        "@oclif/command": "^1.5.11",
+        "@oclif/config": "^1.12.10",
+        "@oclif/errors": "^1.2.2",
+        "cli-ux": "^4.9.3",
+        "date-fns": "^1.29.0",
+        "http-call": "^5.2.3"
+      },
+      "dependencies": {
+        "date-fns": {
+          "version": "1.30.1",
+          "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.30.1.tgz",
+          "integrity": "sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw==",
+          "dev": true
+        }
+      }
+    },
+    "@heroku-cli/plugin-webhooks": {
+      "version": "7.38.1",
+      "resolved": "https://registry.npmjs.org/@heroku-cli/plugin-webhooks/-/plugin-webhooks-7.38.1.tgz",
+      "integrity": "sha512-qMdOikDNoh+xyGP6QfKS5/Pjt5NvY5W6bmAgkWaiu6OzxzDTF5ewvERcfTTOJNttp48VWPhgyt2Ie/6giryH9A==",
+      "dev": true,
+      "requires": {
+        "@heroku-cli/color": "^1.1.14",
+        "@heroku-cli/command": "^8.3.0",
+        "@oclif/command": "^1",
+        "@oclif/config": "^1",
+        "cli-ux": "^5.2.1",
+        "tslib": "^1"
+      },
+      "dependencies": {
+        "clean-stack": {
+          "version": "2.2.0",
+          "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz",
+          "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==",
+          "dev": true
+        },
+        "cli-ux": {
+          "version": "5.4.5",
+          "resolved": "https://registry.npmjs.org/cli-ux/-/cli-ux-5.4.5.tgz",
+          "integrity": "sha512-5A6FuU0wPUlfCWUjtizUvNIbXElp6jN9QUJsDibs6F9cVX1kTgaMR3m6KT0R3iriEXpMrmPKV6yYS8XICNuQ6Q==",
+          "dev": true,
+          "requires": {
+            "@oclif/command": "^1.5.1",
+            "@oclif/errors": "^1.2.1",
+            "@oclif/linewrap": "^1.0.0",
+            "@oclif/screen": "^1.0.3",
+            "ansi-escapes": "^3.1.0",
+            "ansi-styles": "^3.2.1",
+            "cardinal": "^2.1.1",
+            "chalk": "^2.4.1",
+            "clean-stack": "^2.0.0",
+            "cli-progress": "^3.4.0",
+            "extract-stack": "^1.0.0",
+            "fs-extra": "^7.0.1",
+            "hyperlinker": "^1.0.0",
+            "indent-string": "^4.0.0",
+            "is-wsl": "^1.1.0",
+            "js-yaml": "^3.13.1",
+            "lodash": "^4.17.11",
+            "natural-orderby": "^2.0.1",
+            "password-prompt": "^1.1.2",
+            "semver": "^5.6.0",
+            "string-width": "^3.1.0",
+            "strip-ansi": "^5.1.0",
+            "supports-color": "^5.5.0",
+            "supports-hyperlinks": "^1.0.1",
+            "treeify": "^1.1.0",
+            "tslib": "^1.9.3"
+          }
+        },
+        "indent-string": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz",
+          "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==",
+          "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"
+          }
+        }
+      }
+    },
+    "@heroku-cli/schema": {
+      "version": "1.0.25",
+      "resolved": "https://registry.npmjs.org/@heroku-cli/schema/-/schema-1.0.25.tgz",
+      "integrity": "sha512-7V6/WdTHrsvpqeqttm4zhzVJyt/Us/Cz9oS4yure4JdLtwlr2eF6PvlDLA5ZIvBybMtSDyxhHid0PeshKLtwxw==",
+      "dev": true
+    },
+    "@heroku/buildpack-registry": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/@heroku/buildpack-registry/-/buildpack-registry-1.0.1.tgz",
+      "integrity": "sha512-cbB6ND+unRk692jf1PctcoqnmuyifanTMtFStucXukkpyeI/QgXac5qJNb3g6yhHOObTghJBXi9Uzy1KBcnPgQ==",
+      "dev": true,
+      "requires": {
+        "node-fetch": "^2.2.0",
+        "true-myth": "^2.0.0"
+      }
+    },
+    "@heroku/eventsource": {
+      "version": "1.0.7",
+      "resolved": "https://registry.npmjs.org/@heroku/eventsource/-/eventsource-1.0.7.tgz",
+      "integrity": "sha512-zepmPMu8A6S2SyhhzUFVJLhLfqOAGXYR8brf+dRhP41yK9fFinoTT5DO4bo8/EGCJFptPAqfKDavLHsedvynzQ==",
+      "dev": true,
+      "requires": {
+        "original": "^1.0.0"
+      }
+    },
+    "@heroku/socksv5": {
+      "version": "0.0.9",
+      "resolved": "https://registry.npmjs.org/@heroku/socksv5/-/socksv5-0.0.9.tgz",
+      "integrity": "sha1-ejkFkhE2smZpeaD4a7TwYvZX95M=",
+      "dev": true,
+      "requires": {
+        "ip-address": "^5.8.8"
+      }
+    },
+    "@oclif/color": {
+      "version": "0.0.0",
+      "resolved": "https://registry.npmjs.org/@oclif/color/-/color-0.0.0.tgz",
+      "integrity": "sha512-KKd3W7eNwfNF061tr663oUNdt8EMnfuyf5Xv55SGWA1a0rjhWqS/32P7OeB7CbXcJUBdfVrPyR//1afaW12AWw==",
+      "dev": true,
+      "requires": {
+        "ansi-styles": "^3.2.1",
+        "supports-color": "^5.4.0",
+        "tslib": "^1"
+      }
+    },
+    "@oclif/command": {
+      "version": "1.5.18",
+      "resolved": "https://registry.npmjs.org/@oclif/command/-/command-1.5.18.tgz",
+      "integrity": "sha512-sfLb5UUCwyQ0w9LyQ1/3DUuD/RWnPZk6uvcK5P7pqD65WgRJaOPCqzuNZyb56kPsj6FftRp1UudApNKd7U0KBQ==",
+      "dev": true,
+      "requires": {
+        "@oclif/config": "^1",
+        "@oclif/errors": "^1.2.2",
+        "@oclif/parser": "^3.8.3",
+        "@oclif/plugin-help": "^2",
+        "debug": "^4.1.1",
+        "semver": "^5.6.0"
+      }
+    },
+    "@oclif/config": {
+      "version": "1.13.2",
+      "resolved": "https://registry.npmjs.org/@oclif/config/-/config-1.13.2.tgz",
+      "integrity": "sha512-RUOKeuAaopo3zrA5hcgE0PT2lbAUT72+eJdqTlWyI9sbPrGHZgUwV+vrL6Qal7ywWYDkL0vrKd1YS4yXtKIDKw==",
+      "dev": true,
+      "requires": {
+        "@oclif/parser": "^3.8.0",
+        "debug": "^4.1.1",
+        "tslib": "^1.9.3"
+      }
+    },
+    "@oclif/errors": {
+      "version": "1.2.2",
+      "resolved": "https://registry.npmjs.org/@oclif/errors/-/errors-1.2.2.tgz",
+      "integrity": "sha512-Eq8BFuJUQcbAPVofDxwdE0bL14inIiwt5EaKRVY9ZDIG11jwdXZqiQEECJx0VfnLyUZdYfRd/znDI/MytdJoKg==",
+      "dev": true,
+      "requires": {
+        "clean-stack": "^1.3.0",
+        "fs-extra": "^7.0.0",
+        "indent-string": "^3.2.0",
+        "strip-ansi": "^5.0.0",
+        "wrap-ansi": "^4.0.0"
+      }
+    },
+    "@oclif/linewrap": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/@oclif/linewrap/-/linewrap-1.0.0.tgz",
+      "integrity": "sha512-Ups2dShK52xXa8w6iBWLgcjPJWjais6KPJQq3gQ/88AY6BXoTX+MIGFPrWQO1KLMiQfoTpcLnUwloN4brrVUHw==",
+      "dev": true
+    },
+    "@oclif/parser": {
+      "version": "3.8.4",
+      "resolved": "https://registry.npmjs.org/@oclif/parser/-/parser-3.8.4.tgz",
+      "integrity": "sha512-cyP1at3l42kQHZtqDS3KfTeyMvxITGwXwH1qk9ktBYvqgMp5h4vHT+cOD74ld3RqJUOZY/+Zi9lb4Tbza3BtuA==",
+      "dev": true,
+      "requires": {
+        "@oclif/linewrap": "^1.0.0",
+        "chalk": "^2.4.2",
+        "tslib": "^1.9.3"
+      }
+    },
+    "@oclif/plugin-commands": {
+      "version": "1.2.3",
+      "resolved": "https://registry.npmjs.org/@oclif/plugin-commands/-/plugin-commands-1.2.3.tgz",
+      "integrity": "sha512-8ECrHOGJOAK/0q2xag6yfDBbPM7Qr+tzELvy9vsvNg05yKqRu8JSmgZ0Ir8RyjCsRNDdAmesQYhxzX3ZGuG+7g==",
+      "dev": true,
+      "requires": {
+        "@oclif/command": "^1.5.4",
+        "@oclif/config": "^1.8.7",
+        "cli-ux": "^4.9.0",
+        "lodash": "^4.17.11",
+        "tslib": "^1.9.3"
+      }
+    },
+    "@oclif/plugin-help": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/@oclif/plugin-help/-/plugin-help-2.2.0.tgz",
+      "integrity": "sha512-56iIgE7NQfwy/ZrWrvrEfJGb5rrMUt409yoQGw4feiU101UudA1btN1pbUbcKBr7vY9KFeqZZcftXEGxOp7zBg==",
+      "dev": true,
+      "requires": {
+        "@oclif/command": "^1.5.13",
+        "chalk": "^2.4.1",
+        "indent-string": "^3.2.0",
+        "lodash.template": "^4.4.0",
+        "string-width": "^3.0.0",
+        "strip-ansi": "^5.0.0",
+        "widest-line": "^2.0.1",
+        "wrap-ansi": "^4.0.0"
+      },
+      "dependencies": {
+        "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"
+          }
+        }
+      }
+    },
+    "@oclif/plugin-legacy": {
+      "version": "1.1.4",
+      "resolved": "https://registry.npmjs.org/@oclif/plugin-legacy/-/plugin-legacy-1.1.4.tgz",
+      "integrity": "sha512-/oJGRcM7VaSGJ9Eodi/kl0avAKDlJvdYA8jmh4bhBHrCsaPqM61P7LUH2w2PUIccnM82mPPCp3PoUEM85PAIdw==",
+      "dev": true,
+      "requires": {
+        "@heroku-cli/command": "^8.2.0",
+        "@oclif/color": "^0.0.0",
+        "@oclif/command": "^1.5.4",
+        "ansi-escapes": "^3.1.0",
+        "debug": "^4.1.0",
+        "semver": "^5.6.0",
+        "tslib": "^1.9.3"
+      }
+    },
+    "@oclif/plugin-not-found": {
+      "version": "1.2.2",
+      "resolved": "https://registry.npmjs.org/@oclif/plugin-not-found/-/plugin-not-found-1.2.2.tgz",
+      "integrity": "sha512-SPlmiJFmTFltQT/owdzQwKgq6eq5AEKVwVK31JqbzK48bRWvEL1Ye60cgztXyZ4bpPn2Fl+KeL3FWFQX41qJuA==",
+      "dev": true,
+      "requires": {
+        "@oclif/color": "^0.0.0",
+        "@oclif/command": "^1.5.3",
+        "cli-ux": "^4.9.0",
+        "fast-levenshtein": "^2.0.6",
+        "lodash": "^4.17.11"
+      }
+    },
+    "@oclif/plugin-plugins": {
+      "version": "1.7.9",
+      "resolved": "https://registry.npmjs.org/@oclif/plugin-plugins/-/plugin-plugins-1.7.9.tgz",
+      "integrity": "sha512-o7qfmiUGl+NUyA2lM18/Ch5sasGGYPIINR3cZ/AjwtdQ3ooINnF00pUDcUOtbjW97gRmk6/j79tcyTo8i7rHZg==",
+      "dev": true,
+      "requires": {
+        "@oclif/color": "^0.0.0",
+        "@oclif/command": "^1.5.12",
+        "chalk": "^2.4.2",
+        "cli-ux": "^5.2.1",
+        "debug": "^4.1.0",
+        "fs-extra": "^7.0.1",
+        "http-call": "^5.2.2",
+        "load-json-file": "^5.2.0",
+        "npm-run-path": "^3.0.0",
+        "semver": "^5.6.0",
+        "tslib": "^1.9.3",
+        "yarn": "^1.21.1"
+      },
+      "dependencies": {
+        "clean-stack": {
+          "version": "2.2.0",
+          "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz",
+          "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==",
+          "dev": true
+        },
+        "cli-ux": {
+          "version": "5.4.5",
+          "resolved": "https://registry.npmjs.org/cli-ux/-/cli-ux-5.4.5.tgz",
+          "integrity": "sha512-5A6FuU0wPUlfCWUjtizUvNIbXElp6jN9QUJsDibs6F9cVX1kTgaMR3m6KT0R3iriEXpMrmPKV6yYS8XICNuQ6Q==",
+          "dev": true,
+          "requires": {
+            "@oclif/command": "^1.5.1",
+            "@oclif/errors": "^1.2.1",
+            "@oclif/linewrap": "^1.0.0",
+            "@oclif/screen": "^1.0.3",
+            "ansi-escapes": "^3.1.0",
+            "ansi-styles": "^3.2.1",
+            "cardinal": "^2.1.1",
+            "chalk": "^2.4.1",
+            "clean-stack": "^2.0.0",
+            "cli-progress": "^3.4.0",
+            "extract-stack": "^1.0.0",
+            "fs-extra": "^7.0.1",
+            "hyperlinker": "^1.0.0",
+            "indent-string": "^4.0.0",
+            "is-wsl": "^1.1.0",
+            "js-yaml": "^3.13.1",
+            "lodash": "^4.17.11",
+            "natural-orderby": "^2.0.1",
+            "password-prompt": "^1.1.2",
+            "semver": "^5.6.0",
+            "string-width": "^3.1.0",
+            "strip-ansi": "^5.1.0",
+            "supports-color": "^5.5.0",
+            "supports-hyperlinks": "^1.0.1",
+            "treeify": "^1.1.0",
+            "tslib": "^1.9.3"
+          }
+        },
+        "indent-string": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz",
+          "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==",
+          "dev": true
+        },
+        "npm-run-path": {
+          "version": "3.1.0",
+          "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-3.1.0.tgz",
+          "integrity": "sha512-Dbl4A/VfiVGLgQv29URL9xshU8XDY1GeLy+fsaZ1AA8JDSfjvr5P5+pzRbWqRSBxk6/DW7MIh8lTM/PaGnP2kg==",
+          "dev": true,
+          "requires": {
+            "path-key": "^3.0.0"
+          }
+        },
+        "path-key": {
+          "version": "3.1.1",
+          "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+          "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+          "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"
+          }
+        }
+      }
+    },
+    "@oclif/plugin-update": {
+      "version": "1.3.9",
+      "resolved": "https://registry.npmjs.org/@oclif/plugin-update/-/plugin-update-1.3.9.tgz",
+      "integrity": "sha512-rEMsKT7VlCNnfAF7gxHcY9FtQw+w3ZMvxzoRqafMRCz6+Lt94r3PRulBI4M7IkIQwE+dqW/GPUlkDj86Os9Njg==",
+      "dev": true,
+      "requires": {
+        "@oclif/color": "^0.0.0",
+        "@oclif/command": "^1.5.4",
+        "@oclif/config": "^1.9.0",
+        "@oclif/errors": "^1.2.2",
+        "@types/semver": "^5.5.0",
+        "cli-ux": "^4.9.3",
+        "cross-spawn": "^6.0.5",
+        "debug": "^4.1.0",
+        "filesize": "^3.6.1",
+        "fs-extra": "^7.0.1",
+        "http-call": "^5.2.2",
+        "lodash": "^4.17.11",
+        "log-chopper": "^1.0.2",
+        "semver": "^5.6.0",
+        "tar-fs": "^1.16.3"
+      },
+      "dependencies": {
+        "filesize": {
+          "version": "3.6.1",
+          "resolved": "https://registry.npmjs.org/filesize/-/filesize-3.6.1.tgz",
+          "integrity": "sha512-7KjR1vv6qnicaPMi1iiTcI85CyYwRO/PSFCu6SvqL8jN2Wjt/NIYQTFtFs7fSDCYOstUkEWIQGFUg5YZQfjlcg==",
+          "dev": true
+        }
+      }
+    },
+    "@oclif/plugin-warn-if-update-available": {
+      "version": "1.7.0",
+      "resolved": "https://registry.npmjs.org/@oclif/plugin-warn-if-update-available/-/plugin-warn-if-update-available-1.7.0.tgz",
+      "integrity": "sha512-Nwyz3BJ8RhsfQ+OmFSsJSPIfn5YJqMrCzPh72Zgo2jqIjKIBWD8N9vTTe4kZlpeUUn77SyXFfwlBQbNCL5OEuQ==",
+      "dev": true,
+      "requires": {
+        "@oclif/command": "^1.5.10",
+        "@oclif/config": "^1.12.8",
+        "@oclif/errors": "^1.2.2",
+        "chalk": "^2.4.1",
+        "debug": "^4.1.0",
+        "fs-extra": "^7.0.0",
+        "http-call": "^5.2.2",
+        "lodash.template": "^4.4.0",
+        "semver": "^5.6.0"
+      }
+    },
+    "@oclif/plugin-which": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/@oclif/plugin-which/-/plugin-which-1.0.3.tgz",
+      "integrity": "sha512-abYZ9hgtifrDDIXtDEO3eQu5zbrAwxjdXvtnD0kIgADvTNXui4XP8qZs1+bL8BsNW/G6WiSghz0CV7WH8vkmVg==",
+      "dev": true,
+      "requires": {
+        "@oclif/command": "^1.5.4",
+        "@oclif/config": "^1.8.7",
+        "cli-ux": "^4.9.1",
+        "tslib": "^1.9.3"
+      }
+    },
+    "@oclif/screen": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/@oclif/screen/-/screen-1.0.4.tgz",
+      "integrity": "sha512-60CHpq+eqnTxLZQ4PGHYNwUX572hgpMHGPtTWMjdTMsAvlm69lZV/4ly6O3sAYkomo4NggGcomrDpBe34rxUqw==",
+      "dev": true
+    },
+    "@sindresorhus/is": {
+      "version": "0.7.0",
+      "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.7.0.tgz",
+      "integrity": "sha512-ONhaKPIufzzrlNbqtWFFd+jlnemX6lJAgq9ZeiZtS7I1PIf/la7CW4m83rTXRnVnsMbW2k56pGYu7AUFJD9Pow==",
+      "dev": true
+    },
+    "@szmarczak/http-timer": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz",
+      "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==",
+      "dev": true,
+      "requires": {
+        "defer-to-connect": "^1.0.1"
+      }
+    },
+    "@types/color-name": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz",
+      "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==",
+      "dev": true
+    },
+    "@types/geojson": {
+      "version": "7946.0.7",
+      "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.7.tgz",
+      "integrity": "sha512-wE2v81i4C4Ol09RtsWFAqg3BUitWbHSpSlIo+bNdsCJijO9sjme+zm+73ZMCa/qMC8UEERxzGbvmr1cffo2SiQ=="
+    },
+    "@types/node": {
+      "version": "12.12.31",
+      "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.31.tgz",
+      "integrity": "sha512-T+wnJno8uh27G9c+1T+a1/WYCHzLeDqtsGJkoEdSp2X8RTh3oOCZQcUnjAx90CS8cmmADX51O0FI/tu9s0yssg=="
+    },
+    "@types/semver": {
+      "version": "5.5.0",
+      "resolved": "https://registry.npmjs.org/@types/semver/-/semver-5.5.0.tgz",
+      "integrity": "sha512-41qEJgBH/TWgo5NFSvBCJ1qkoi3Q6ONSF2avrHq1LVEZfYpdHmj0y9SuTK+u9ZhG1sYQKBL1AWXKyLWP4RaUoQ==",
+      "dev": true
+    },
+    "abbrev": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
+      "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==",
+      "dev": true
+    },
+    "accepts": {
+      "version": "1.3.7",
+      "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz",
+      "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==",
+      "requires": {
+        "mime-types": "~2.1.24",
+        "negotiator": "0.6.2"
+      }
+    },
+    "after": {
+      "version": "0.8.2",
+      "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz",
+      "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8="
+    },
+    "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": "4.1.0",
+      "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
+      "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg=="
+    },
+    "ansi-styles": {
+      "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==",
+      "requires": {
+        "color-convert": "^1.9.0"
+      }
+    },
+    "ansicolors": {
+      "version": "0.3.2",
+      "resolved": "https://registry.npmjs.org/ansicolors/-/ansicolors-0.3.2.tgz",
+      "integrity": "sha1-ZlWX3oap/+Oqm/vmyuXG6kJrSXk=",
+      "dev": true
+    },
+    "app-path": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/app-path/-/app-path-2.2.0.tgz",
+      "integrity": "sha1-KvXCtUSkDhX8GsVVSDFDl0YIRdA=",
+      "dev": true,
+      "requires": {
+        "execa": "^0.4.0"
+      },
+      "dependencies": {
+        "execa": {
+          "version": "0.4.0",
+          "resolved": "https://registry.npmjs.org/execa/-/execa-0.4.0.tgz",
+          "integrity": "sha1-TrZGejaglfq7KXD/nV4/t7zm68M=",
+          "dev": true,
+          "requires": {
+            "cross-spawn-async": "^2.1.1",
+            "is-stream": "^1.1.0",
+            "npm-run-path": "^1.0.0",
+            "object-assign": "^4.0.1",
+            "path-key": "^1.0.0",
+            "strip-eof": "^1.0.0"
+          }
+        },
+        "is-stream": {
+          "version": "1.1.0",
+          "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
+          "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=",
+          "dev": true
+        },
+        "npm-run-path": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-1.0.0.tgz",
+          "integrity": "sha1-9cMr9ZX+ga6Sfa7FLoL4sACsPI8=",
+          "dev": true,
+          "requires": {
+            "path-key": "^1.0.0"
+          }
+        },
+        "path-key": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/path-key/-/path-key-1.0.0.tgz",
+          "integrity": "sha1-XVPVeAGWRsDWiADbThRua9wqx68=",
+          "dev": true
+        }
+      }
+    },
+    "argparse": {
+      "version": "1.0.10",
+      "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
+      "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
+      "requires": {
+        "sprintf-js": "~1.0.2"
+      }
+    },
+    "arraybuffer.slice": {
+      "version": "0.0.7",
+      "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz",
+      "integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog=="
+    },
+    "asn1": {
+      "version": "0.2.4",
+      "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz",
+      "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==",
+      "dev": true,
+      "requires": {
+        "safer-buffer": "~2.1.0"
+      }
+    },
+    "async-file": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/async-file/-/async-file-2.0.2.tgz",
+      "integrity": "sha1-Aq0HhWrDcX6DayCuxaTP4AxG3yM=",
+      "dev": true,
+      "requires": {
+        "rimraf": "^2.5.2"
+      }
+    },
+    "async-limiter": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz",
+      "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ=="
+    },
+    "backo2": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz",
+      "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc="
+    },
+    "balanced-match": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
+      "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
+    },
+    "base64-arraybuffer": {
+      "version": "0.1.5",
+      "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz",
+      "integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg="
+    },
+    "base64-js": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.2.0.tgz",
+      "integrity": "sha1-o5mS1yNYSBGYK+XikLtqU9hnAPE=",
+      "dev": true
+    },
+    "base64id": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz",
+      "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog=="
+    },
+    "better-assert": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz",
+      "integrity": "sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=",
+      "requires": {
+        "callsite": "1.0.0"
+      }
+    },
+    "bl": {
+      "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"
+      }
+    },
+    "blob": {
+      "version": "0.0.5",
+      "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz",
+      "integrity": "sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig=="
+    },
+    "bluebird": {
+      "version": "3.7.2",
+      "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
+      "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==",
+      "dev": true
+    },
+    "brace-expansion": {
+      "version": "1.1.11",
+      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+      "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+      "requires": {
+        "balanced-match": "^1.0.0",
+        "concat-map": "0.0.1"
+      }
+    },
+    "buffer-alloc": {
+      "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"
+      }
+    },
+    "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
+    },
+    "buffer-fill": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz",
+      "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=",
+      "dev": true
+    },
+    "buffer-from": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
+      "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==",
+      "dev": true
+    },
+    "byline": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/byline/-/byline-5.0.0.tgz",
+      "integrity": "sha1-dBxSFkaOrcRXsDQQEYrXfejB3bE=",
+      "dev": true
+    },
+    "bytes": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
+      "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==",
+      "dev": true
+    },
+    "cacheable-request": {
+      "version": "2.1.4",
+      "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-2.1.4.tgz",
+      "integrity": "sha1-DYCIAbY0KtM8kd+dC0TcCbkeXD0=",
+      "dev": true,
+      "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=",
+          "dev": true
+        }
+      }
+    },
+    "callsite": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz",
+      "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA="
+    },
+    "cardinal": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/cardinal/-/cardinal-2.1.1.tgz",
+      "integrity": "sha1-fMEFXYItISlU0HsIXeolHMe8VQU=",
+      "dev": true,
+      "requires": {
+        "ansicolors": "~0.3.2",
+        "redeyed": "~2.1.0"
+      }
+    },
+    "chalk": {
+      "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",
+        "supports-color": "^5.3.0"
+      }
+    },
+    "chardet": {
+      "version": "0.7.0",
+      "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz",
+      "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA=="
+    },
+    "chownr": {
+      "version": "1.1.4",
+      "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
+      "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==",
+      "dev": true
+    },
+    "clean-stack": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-1.3.0.tgz",
+      "integrity": "sha1-noIVAa6XmYbEax1m0tQy2y/UrjE=",
+      "dev": true
+    },
+    "cli-cursor": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz",
+      "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==",
+      "dev": true,
+      "requires": {
+        "restore-cursor": "^3.1.0"
+      }
+    },
+    "cli-progress": {
+      "version": "3.6.0",
+      "resolved": "https://registry.npmjs.org/cli-progress/-/cli-progress-3.6.0.tgz",
+      "integrity": "sha512-elg6jkiDedYrvwqWSae2FGvtbMo37Lo04oI9jJ5cI43Ge3jrDPWzeL3axv7MgBLYHDY/kGio/CXa49m4MWMrNw==",
+      "dev": true,
+      "requires": {
+        "colors": "^1.1.2",
+        "string-width": "^2.1.1"
+      }
+    },
+    "cli-ux": {
+      "version": "4.9.3",
+      "resolved": "https://registry.npmjs.org/cli-ux/-/cli-ux-4.9.3.tgz",
+      "integrity": "sha512-/1owvF0SZ5Gn54cgrikJ0QskgTzeg30HGjkmjFoaHDJzAqFpuX1DBpFR8aLvsE1J5s9MgeYRENQK4BFwOag5VA==",
+      "dev": true,
+      "requires": {
+        "@oclif/errors": "^1.2.2",
+        "@oclif/linewrap": "^1.0.0",
+        "@oclif/screen": "^1.0.3",
+        "ansi-escapes": "^3.1.0",
+        "ansi-styles": "^3.2.1",
+        "cardinal": "^2.1.1",
+        "chalk": "^2.4.1",
+        "clean-stack": "^2.0.0",
+        "extract-stack": "^1.0.0",
+        "fs-extra": "^7.0.0",
+        "hyperlinker": "^1.0.0",
+        "indent-string": "^3.2.0",
+        "is-wsl": "^1.1.0",
+        "lodash": "^4.17.11",
+        "password-prompt": "^1.0.7",
+        "semver": "^5.6.0",
+        "strip-ansi": "^5.0.0",
+        "supports-color": "^5.5.0",
+        "supports-hyperlinks": "^1.0.1",
+        "treeify": "^1.1.0",
+        "tslib": "^1.9.3"
+      },
+      "dependencies": {
+        "clean-stack": {
+          "version": "2.2.0",
+          "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz",
+          "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==",
+          "dev": true
+        }
+      }
+    },
+    "cli-width": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz",
+      "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk="
+    },
+    "clone-response": {
+      "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"
+      }
+    },
+    "co": {
+      "version": "4.6.0",
+      "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
+      "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=",
+      "dev": true
+    },
+    "co-wait": {
+      "version": "0.0.0",
+      "resolved": "https://registry.npmjs.org/co-wait/-/co-wait-0.0.0.tgz",
+      "integrity": "sha1-wiNyAyIY7b9u2RXkM1RsIeRFYos=",
+      "dev": true
+    },
+    "color-convert": {
+      "version": "1.9.3",
+      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+      "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+      "requires": {
+        "color-name": "1.1.3"
+      }
+    },
+    "color-name": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+      "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
+    },
+    "colors": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz",
+      "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==",
+      "dev": true
+    },
+    "commander": {
+      "version": "2.20.3",
+      "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
+      "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
+      "dev": true
+    },
+    "commondir": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
+      "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=",
+      "dev": true
+    },
+    "component-bind": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz",
+      "integrity": "sha1-AMYIq33Nk4l8AAllGx06jh5zu9E="
+    },
+    "component-emitter": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz",
+      "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY="
+    },
+    "component-inherit": {
+      "version": "0.0.3",
+      "resolved": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz",
+      "integrity": "sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM="
+    },
+    "concat-map": {
+      "version": "0.0.1",
+      "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+      "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
+    },
+    "content-type": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
+      "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==",
+      "dev": true
+    },
+    "cookie": {
+      "version": "0.3.1",
+      "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz",
+      "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s="
+    },
+    "core-js": {
+      "version": "3.6.4",
+      "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.6.4.tgz",
+      "integrity": "sha512-4paDGScNgZP2IXXilaffL9X7968RuvwlkK3xWtZRVqgd8SYNiVKRJvkFd1aqqEuPfN7E68ZHEp9hDj6lHj4Hyw==",
+      "dev": true
+    },
+    "core-util-is": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
+      "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
+      "dev": true
+    },
+    "cross-spawn": {
+      "version": "6.0.5",
+      "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
+      "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
+      "requires": {
+        "nice-try": "^1.0.4",
+        "path-key": "^2.0.1",
+        "semver": "^5.5.0",
+        "shebang-command": "^1.2.0",
+        "which": "^1.2.9"
+      }
+    },
+    "cross-spawn-async": {
+      "version": "2.2.5",
+      "resolved": "https://registry.npmjs.org/cross-spawn-async/-/cross-spawn-async-2.2.5.tgz",
+      "integrity": "sha1-hF/wwINKPe2dFg2sptOQkGuyiMw=",
+      "dev": true,
+      "requires": {
+        "lru-cache": "^4.0.0",
+        "which": "^1.2.8"
+      }
+    },
+    "date-fns": {
+      "version": "2.11.0",
+      "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.11.0.tgz",
+      "integrity": "sha512-8P1cDi8ebZyDxUyUprBXwidoEtiQAawYPGvpfb+Dg0G6JrQ+VozwOmm91xYC0vAv1+0VmLehEPb+isg4BGUFfA==",
+      "dev": true
+    },
+    "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"
+      }
+    },
+    "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
+    },
+    "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"
+      }
+    },
+    "defer-to-connect": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz",
+      "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==",
+      "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"
+      }
+    },
+    "denque": {
+      "version": "1.4.1",
+      "resolved": "https://registry.npmjs.org/denque/-/denque-1.4.1.tgz",
+      "integrity": "sha512-OfzPuSZKGcgr96rf1oODnfjqBFmr1DVoc/TrItj3Ohe0Ah1C5WX5Baquw/9U9KovnQ88EqmJbD66rKYUQYN1tQ=="
+    },
+    "dotenv": {
+      "version": "8.2.0",
+      "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.2.0.tgz",
+      "integrity": "sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw=="
+    },
+    "duplexer3": {
+      "version": "0.1.4",
+      "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz",
+      "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=",
+      "dev": true
+    },
+    "edit-string": {
+      "version": "1.1.6",
+      "resolved": "https://registry.npmjs.org/edit-string/-/edit-string-1.1.6.tgz",
+      "integrity": "sha1-HJqInbx+YAdn9P7KadCKfOFZYvQ=",
+      "dev": true,
+      "requires": {
+        "debug": "^3.1.0",
+        "execa": "^0.10.0",
+        "lodash": "^4.17.10",
+        "tmp": "^0.0.33",
+        "tslib": "^1.9.0"
+      },
+      "dependencies": {
+        "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"
+          }
+        },
+        "execa": {
+          "version": "0.10.0",
+          "resolved": "https://registry.npmjs.org/execa/-/execa-0.10.0.tgz",
+          "integrity": "sha512-7XOMnz8Ynx1gGo/3hyV9loYNPWM94jG3+3T3Y8tsfSstFmETmENCMU/A/zj8Lyaj1lkgEepKepvd6240tBRvlw==",
+          "dev": true,
+          "requires": {
+            "cross-spawn": "^6.0.0",
+            "get-stream": "^3.0.0",
+            "is-stream": "^1.1.0",
+            "npm-run-path": "^2.0.0",
+            "p-finally": "^1.0.0",
+            "signal-exit": "^3.0.0",
+            "strip-eof": "^1.0.0"
+          }
+        },
+        "is-stream": {
+          "version": "1.1.0",
+          "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
+          "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=",
+          "dev": true
+        }
+      }
+    },
+    "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
+    },
+    "end-of-stream": {
+      "version": "1.4.4",
+      "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
+      "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
+      "dev": true,
+      "requires": {
+        "once": "^1.4.0"
+      }
+    },
+    "engine.io": {
+      "version": "3.4.0",
+      "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.4.0.tgz",
+      "integrity": "sha512-XCyYVWzcHnK5cMz7G4VTu2W7zJS7SM1QkcelghyIk/FmobWBtXE7fwhBusEKvCSqc3bMh8fNFMlUkCKTFRxH2w==",
+      "requires": {
+        "accepts": "~1.3.4",
+        "base64id": "2.0.0",
+        "cookie": "0.3.1",
+        "debug": "~4.1.0",
+        "engine.io-parser": "~2.2.0",
+        "ws": "^7.1.2"
+      }
+    },
+    "engine.io-client": {
+      "version": "3.4.0",
+      "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.4.0.tgz",
+      "integrity": "sha512-a4J5QO2k99CM2a0b12IznnyQndoEvtA4UAldhGzKqnHf42I3Qs2W5SPnDvatZRcMaNZs4IevVicBPayxYt6FwA==",
+      "requires": {
+        "component-emitter": "1.2.1",
+        "component-inherit": "0.0.3",
+        "debug": "~4.1.0",
+        "engine.io-parser": "~2.2.0",
+        "has-cors": "1.1.0",
+        "indexof": "0.0.1",
+        "parseqs": "0.0.5",
+        "parseuri": "0.0.5",
+        "ws": "~6.1.0",
+        "xmlhttprequest-ssl": "~1.5.4",
+        "yeast": "0.1.2"
+      },
+      "dependencies": {
+        "ws": {
+          "version": "6.1.4",
+          "resolved": "https://registry.npmjs.org/ws/-/ws-6.1.4.tgz",
+          "integrity": "sha512-eqZfL+NE/YQc1/ZynhojeV8q+H050oR8AZ2uIev7RU10svA9ZnJUddHcOUZTJLinZ9yEfdA2kSATS2qZK5fhJA==",
+          "requires": {
+            "async-limiter": "~1.0.0"
+          }
+        }
+      }
+    },
+    "engine.io-parser": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.2.0.tgz",
+      "integrity": "sha512-6I3qD9iUxotsC5HEMuuGsKA0cXerGz+4uGcXQEkfBidgKf0amsjrrtwcbwK/nzpZBxclXlV7gGl9dgWvu4LF6w==",
+      "requires": {
+        "after": "0.8.2",
+        "arraybuffer.slice": "~0.0.7",
+        "base64-arraybuffer": "0.1.5",
+        "blob": "0.0.5",
+        "has-binary2": "~1.0.2"
+      }
+    },
+    "error-ex": {
+      "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.17.5",
+      "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.5.tgz",
+      "integrity": "sha512-BR9auzDbySxOcfog0tLECW8l28eRGpDpU3Dm3Hp4q/N+VtLTmyj4EUN088XZWQDW/hzj6sYRDXeOFsaAODKvpg==",
+      "dev": true,
+      "requires": {
+        "es-to-primitive": "^1.2.1",
+        "function-bind": "^1.1.1",
+        "has": "^1.0.3",
+        "has-symbols": "^1.0.1",
+        "is-callable": "^1.1.5",
+        "is-regex": "^1.0.5",
+        "object-inspect": "^1.7.0",
+        "object-keys": "^1.1.1",
+        "object.assign": "^4.1.0",
+        "string.prototype.trimleft": "^2.1.1",
+        "string.prototype.trimright": "^2.1.1"
+      }
+    },
+    "es-to-primitive": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz",
+      "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==",
+      "dev": true,
+      "requires": {
+        "is-callable": "^1.1.4",
+        "is-date-object": "^1.0.1",
+        "is-symbol": "^1.0.2"
+      }
+    },
+    "escape-string-regexp": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+      "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
+    },
+    "esprima": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
+      "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A=="
+    },
+    "eventemitter3": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.0.tgz",
+      "integrity": "sha512-qerSRB0p+UDEssxTtm6EDKcE7W4OaoisfIMl4CngyEhjpYglocpNg6UEqCvemdGhosAsg4sO2dXJOdyBifPGCg==",
+      "dev": true
+    },
+    "execa": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz",
+      "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==",
+      "dev": true,
+      "requires": {
+        "cross-spawn": "^6.0.0",
+        "get-stream": "^4.0.0",
+        "is-stream": "^1.1.0",
+        "npm-run-path": "^2.0.0",
+        "p-finally": "^1.0.0",
+        "signal-exit": "^3.0.0",
+        "strip-eof": "^1.0.0"
+      },
+      "dependencies": {
+        "get-stream": {
+          "version": "4.1.0",
+          "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz",
+          "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==",
+          "dev": true,
+          "requires": {
+            "pump": "^3.0.0"
+          }
+        },
+        "is-stream": {
+          "version": "1.1.0",
+          "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
+          "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=",
+          "dev": true
+        }
+      }
+    },
+    "external-editor": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz",
+      "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==",
+      "requires": {
+        "chardet": "^0.7.0",
+        "iconv-lite": "^0.4.24",
+        "tmp": "^0.0.33"
+      }
+    },
+    "extract-stack": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/extract-stack/-/extract-stack-1.0.0.tgz",
+      "integrity": "sha1-uXrK+UQe6iMyUpYktzL8WhyBZfo=",
+      "dev": true
+    },
+    "fast-levenshtein": {
+      "version": "2.0.6",
+      "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+      "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc="
+    },
+    "figures": {
+      "version": "3.2.0",
+      "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz",
+      "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==",
+      "dev": true,
+      "requires": {
+        "escape-string-regexp": "^1.0.5"
+      }
+    },
+    "filesize": {
+      "version": "4.2.1",
+      "resolved": "https://registry.npmjs.org/filesize/-/filesize-4.2.1.tgz",
+      "integrity": "sha512-bP82Hi8VRZX/TUBKfE24iiUGsB/sfm2WUrwTQyAzQrhO3V9IhcBBNBXMyzLY5orACxRyYJ3d2HeRVX+eFv4lmA==",
+      "dev": true
+    },
+    "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==",
+      "dev": true,
+      "requires": {
+        "commondir": "^1.0.1",
+        "make-dir": "^2.0.0",
+        "pkg-dir": "^3.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"
+      }
+    },
+    "follow-redirects": {
+      "version": "1.10.0",
+      "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.10.0.tgz",
+      "integrity": "sha512-4eyLK6s6lH32nOvLLwlIOnr9zrL8Sm+OvW4pVTJNoXeGzYIkHVf+pADQi+OJ0E67hiuSLezPVPyBcIZO50TmmQ==",
+      "dev": true,
+      "requires": {
+        "debug": "^3.0.0"
+      },
+      "dependencies": {
+        "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"
+          }
+        }
+      }
+    },
+    "foreman": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/foreman/-/foreman-3.0.1.tgz",
+      "integrity": "sha512-ek/qoM0vVKpxzkBUQN9k4Fs7l0XsHv4bqxuEW6oqIS4s0ouYKsQ19YjBzUJKTFRumFiSpUv7jySkrI6lfbhjlw==",
+      "dev": true,
+      "requires": {
+        "commander": "^2.15.1",
+        "http-proxy": "^1.17.0",
+        "mustache": "^2.2.1",
+        "shell-quote": "^1.6.1"
+      }
+    },
+    "from2": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz",
+      "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=",
+      "dev": true,
+      "requires": {
+        "inherits": "^2.0.1",
+        "readable-stream": "^2.0.0"
+      }
+    },
+    "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
+    },
+    "fs-extra": {
+      "version": "7.0.1",
+      "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz",
+      "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==",
+      "dev": true,
+      "requires": {
+        "graceful-fs": "^4.1.2",
+        "jsonfile": "^4.0.0",
+        "universalify": "^0.1.0"
+      }
+    },
+    "fs.realpath": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+      "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
+      "dev": true
+    },
+    "function-bind": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
+      "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
+      "dev": true
+    },
+    "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
+    },
+    "github-url-to-object": {
+      "version": "4.0.4",
+      "resolved": "https://registry.npmjs.org/github-url-to-object/-/github-url-to-object-4.0.4.tgz",
+      "integrity": "sha512-1Ri1pR8XTfzLpbtPz5MlW/amGNdNReuExPsbF9rxLsBfO1GH9RtDBamhJikd0knMWq3RTTQDbTtw0GGvvEAJEA==",
+      "dev": true,
+      "requires": {
+        "is-url": "^1.1.0"
+      }
+    },
+    "glob": {
+      "version": "7.1.6",
+      "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
+      "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
+      "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"
+      }
+    },
+    "got": {
+      "version": "8.3.2",
+      "resolved": "https://registry.npmjs.org/got/-/got-8.3.2.tgz",
+      "integrity": "sha512-qjUJ5U/hawxosMryILofZCkm3C84PLJS/0grRIpjAwu+Lkxxj5cxeCU25BG0/3mDSpXKTyZr8oh8wIgLaH0QCw==",
+      "dev": true,
+      "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"
+      },
+      "dependencies": {
+        "pify": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
+          "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
+          "dev": true
+        }
+      }
+    },
+    "graceful-fs": {
+      "version": "4.2.3",
+      "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz",
+      "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==",
+      "dev": true
+    },
+    "growly": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/growly/-/growly-1.3.0.tgz",
+      "integrity": "sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=",
+      "dev": true
+    },
+    "has": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
+      "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
+      "dev": true,
+      "requires": {
+        "function-bind": "^1.1.1"
+      }
+    },
+    "has-ansi": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
+      "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=",
+      "dev": true,
+      "requires": {
+        "ansi-regex": "^2.0.0"
+      },
+      "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
+        }
+      }
+    },
+    "has-binary2": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.3.tgz",
+      "integrity": "sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw==",
+      "requires": {
+        "isarray": "2.0.1"
+      }
+    },
+    "has-cors": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz",
+      "integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk="
+    },
+    "has-flag": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+      "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0="
+    },
+    "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==",
+      "dev": true
+    },
+    "has-symbols": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz",
+      "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==",
+      "dev": true
+    },
+    "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==",
+      "dev": true,
+      "requires": {
+        "has-symbol-support-x": "^1.4.1"
+      }
+    },
+    "here": {
+      "version": "0.0.2",
+      "resolved": "https://registry.npmjs.org/here/-/here-0.0.2.tgz",
+      "integrity": "sha1-acGvPwISHz2HiOAuhNyLOQXXEZU=",
+      "dev": true
+    },
+    "heroku": {
+      "version": "7.39.1",
+      "resolved": "https://registry.npmjs.org/heroku/-/heroku-7.39.1.tgz",
+      "integrity": "sha512-7EFpuhgUmldQq1Nk31XH0B921DMJqk7Bw0hACAN6Z+qV6rjQn0pwhmzcokl3+iZOOcfZjbkLmN28lajyhOEGPg==",
+      "dev": true,
+      "requires": {
+        "@heroku-cli/color": "1.1.14",
+        "@heroku-cli/command": "^8.3.0",
+        "@heroku-cli/plugin-addons-v5": "^7.24.0",
+        "@heroku-cli/plugin-apps": "^7.38.2",
+        "@heroku-cli/plugin-apps-v5": "^7.39.1",
+        "@heroku-cli/plugin-auth": "^7.39.1",
+        "@heroku-cli/plugin-autocomplete": "^7.39.1",
+        "@heroku-cli/plugin-buildpacks": "^7.39.1",
+        "@heroku-cli/plugin-certs": "^7.39.1",
+        "@heroku-cli/plugin-certs-v5": "^7.39.0",
+        "@heroku-cli/plugin-ci": "^7.39.1",
+        "@heroku-cli/plugin-ci-v5": "^7.39.1",
+        "@heroku-cli/plugin-config": "^7.39.1",
+        "@heroku-cli/plugin-container-registry-v5": "^7.28.0",
+        "@heroku-cli/plugin-git": "^7.39.1",
+        "@heroku-cli/plugin-local": "^7.38.1",
+        "@heroku-cli/plugin-oauth-v5": "^7.39.1",
+        "@heroku-cli/plugin-orgs-v5": "^7.38.1",
+        "@heroku-cli/plugin-pg-v5": "^7.37.0",
+        "@heroku-cli/plugin-pipelines": "^7.38.1",
+        "@heroku-cli/plugin-ps": "^7.39.1",
+        "@heroku-cli/plugin-ps-exec": "2.3.8",
+        "@heroku-cli/plugin-redis-v5": "^7.25.0",
+        "@heroku-cli/plugin-run-v5": "^7.39.1",
+        "@heroku-cli/plugin-spaces": "^7.38.1",
+        "@heroku-cli/plugin-status": "^7.38.1",
+        "@heroku-cli/plugin-webhooks": "^7.38.1",
+        "@oclif/command": "1.5.18",
+        "@oclif/config": "1.13.2",
+        "@oclif/errors": "1.2.2",
+        "@oclif/plugin-commands": "^1.2.2",
+        "@oclif/plugin-help": "2.2.0",
+        "@oclif/plugin-legacy": "1.1.4",
+        "@oclif/plugin-not-found": "1.2.2",
+        "@oclif/plugin-plugins": "1.7.9",
+        "@oclif/plugin-update": "1.3.9",
+        "@oclif/plugin-warn-if-update-available": "1.7.0",
+        "@oclif/plugin-which": "1.0.3",
+        "cli-ux": "4.9.3",
+        "debug": "4.1.1",
+        "execa": "1.0.0",
+        "fs-extra": "7.0.1",
+        "http-call": "5.2.3",
+        "netrc-parser": "3.1.6",
+        "semver": "5.6.0",
+        "tslib": "1.9.3",
+        "uuid": "3.3.2"
+      },
+      "dependencies": {
+        "semver": {
+          "version": "5.6.0",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz",
+          "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==",
+          "dev": true
+        }
+      }
+    },
+    "heroku-cli-util": {
+      "version": "8.0.12",
+      "resolved": "https://registry.npmjs.org/heroku-cli-util/-/heroku-cli-util-8.0.12.tgz",
+      "integrity": "sha512-63wB17oSktlA/HzpIV/PGe8Isq5AZArT51KAW1gg54zyYRIiHOwXik93HZuuRVUaVrWvVUhItFeLgqMwAwlTsw==",
+      "dev": true,
+      "requires": {
+        "@heroku-cli/color": "^1.1.3",
+        "ansi-escapes": "^3.1.0",
+        "ansi-styles": "^3.2.1",
+        "cardinal": "^2.0.1",
+        "chalk": "^2.4.1",
+        "co": "^4.6.0",
+        "got": "^8.3.1",
+        "heroku-client": "^3.1.0",
+        "lodash": "^4.17.10",
+        "netrc-parser": "^3.1.4",
+        "opn": "^3.0.3",
+        "strip-ansi": "^4.0.0",
+        "supports-color": "^5.4.0",
+        "tslib": "^1.9.0",
+        "tunnel-agent": "^0.6.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
+        },
+        "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"
+          }
+        }
+      }
+    },
+    "heroku-client": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/heroku-client/-/heroku-client-3.1.0.tgz",
+      "integrity": "sha512-UfGKwUm5duzzSVI8uUXlNAE1mus6uPxmZPji4vuG1ArV5DYL1rXsZShp0OoxraWdEwYoxCUrM6KGztC68x5EZQ==",
+      "dev": true,
+      "requires": {
+        "is-retry-allowed": "^1.0.0",
+        "tunnel-agent": "^0.6.0"
+      }
+    },
+    "heroku-exec-util": {
+      "version": "0.7.5",
+      "resolved": "https://registry.npmjs.org/heroku-exec-util/-/heroku-exec-util-0.7.5.tgz",
+      "integrity": "sha512-br2hIJN0y0yO+EOxV9qn+i6zhRpZTWa+ECKSpjwtAHsG3dFp+cZkHoVm6QxC/9XypCILFBN0LRlOoVNWs/IUhQ==",
+      "dev": true,
+      "requires": {
+        "@heroku/socksv5": "^0.0.9",
+        "co-wait": "0.0.0",
+        "heroku-cli-util": "^8.0.9",
+        "keypair": "1.0.1",
+        "node-forge": "0.7.5",
+        "smooth-progress": "1.1.0",
+        "ssh2": "0.6.1",
+        "temp": "0.8.3",
+        "uuid": "3.2.1"
+      },
+      "dependencies": {
+        "rimraf": {
+          "version": "2.2.8",
+          "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz",
+          "integrity": "sha1-5Dm+Kq7jJzIZUnMPmaiSnk/FBYI=",
+          "dev": true
+        },
+        "ssh2": {
+          "version": "0.6.1",
+          "resolved": "https://registry.npmjs.org/ssh2/-/ssh2-0.6.1.tgz",
+          "integrity": "sha512-fNvocq+xetsaAZtBG/9Vhh0GDjw1jQeW7Uq/DPh4fVrJd0XxSfXAqBjOGVk4o2jyWHvyC6HiaPFpfHlR12coDw==",
+          "dev": true,
+          "requires": {
+            "ssh2-streams": "~0.2.0"
+          }
+        },
+        "ssh2-streams": {
+          "version": "0.2.1",
+          "resolved": "https://registry.npmjs.org/ssh2-streams/-/ssh2-streams-0.2.1.tgz",
+          "integrity": "sha512-3zCOsmunh1JWgPshfhKmBCL3lUtHPoh+a/cyQ49Ft0Q0aF7xgN06b76L+oKtFi0fgO57FLjFztb1GlJcEZ4a3Q==",
+          "dev": true,
+          "requires": {
+            "asn1": "~0.2.0",
+            "semver": "^5.1.0",
+            "streamsearch": "~0.1.2"
+          }
+        },
+        "temp": {
+          "version": "0.8.3",
+          "resolved": "https://registry.npmjs.org/temp/-/temp-0.8.3.tgz",
+          "integrity": "sha1-4Ma8TSa5AxJEEOT+2BEDAU38H1k=",
+          "dev": true,
+          "requires": {
+            "os-tmpdir": "^1.0.0",
+            "rimraf": "~2.2.6"
+          }
+        },
+        "uuid": {
+          "version": "3.2.1",
+          "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz",
+          "integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==",
+          "dev": true
+        }
+      }
+    },
+    "homedir-polyfill": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz",
+      "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==",
+      "dev": true,
+      "requires": {
+        "parse-passwd": "^1.0.0"
+      }
+    },
+    "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==",
+      "dev": true
+    },
+    "http-call": {
+      "version": "5.2.3",
+      "resolved": "https://registry.npmjs.org/http-call/-/http-call-5.2.3.tgz",
+      "integrity": "sha512-IkwGruHVHATmnonLKMGX5tkpM0KSn/C240o8/OfBsESRaJacykSia+akhD0d3fljQ5rQPXtBvSrVShAsj+EOUQ==",
+      "dev": true,
+      "requires": {
+        "content-type": "^1.0.4",
+        "debug": "^3.1.0",
+        "is-retry-allowed": "^1.1.0",
+        "is-stream": "^1.1.0",
+        "tunnel-agent": "^0.6.0"
+      },
+      "dependencies": {
+        "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"
+          }
+        },
+        "is-stream": {
+          "version": "1.1.0",
+          "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
+          "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=",
+          "dev": true
+        }
+      }
+    },
+    "http-proxy": {
+      "version": "1.18.0",
+      "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.0.tgz",
+      "integrity": "sha512-84I2iJM/n1d4Hdgc6y2+qY5mDaz2PUVjlg9znE9byl+q0uC3DeByqBGReQu5tpLK0TAqTIXScRUV+dg7+bUPpQ==",
+      "dev": true,
+      "requires": {
+        "eventemitter3": "^4.0.0",
+        "follow-redirects": "^1.0.0",
+        "requires-port": "^1.0.0"
+      }
+    },
+    "hyperlinker": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/hyperlinker/-/hyperlinker-1.0.0.tgz",
+      "integrity": "sha512-Ty8UblRWFEcfSuIaajM34LdPXIhbs1ajEX/BBPv24J+enSVaEVY63xQ6lTO9VRYS5LAoghIG0IDJ+p+IPzKUQQ==",
+      "dev": true
+    },
+    "iconv-lite": {
+      "version": "0.4.24",
+      "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
+      "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
+      "requires": {
+        "safer-buffer": ">= 2.1.2 < 3"
+      }
+    },
+    "indent-string": {
+      "version": "3.2.0",
+      "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz",
+      "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=",
+      "dev": true
+    },
+    "indexof": {
+      "version": "0.0.1",
+      "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz",
+      "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10="
+    },
+    "inflight": {
+      "version": "1.0.6",
+      "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+      "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
+      "dev": true,
+      "requires": {
+        "once": "^1.3.0",
+        "wrappy": "1"
+      }
+    },
+    "inherits": {
+      "version": "2.0.4",
+      "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+      "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+      "dev": true
+    },
+    "inquirer": {
+      "version": "7.1.0",
+      "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.1.0.tgz",
+      "integrity": "sha512-5fJMWEmikSYu0nv/flMc475MhGbB7TSPd/2IpFV4I4rMklboCH2rQjYY5kKiYGHqUF9gvaambupcJFFG9dvReg==",
+      "dev": true,
+      "requires": {
+        "ansi-escapes": "^4.2.1",
+        "chalk": "^3.0.0",
+        "cli-cursor": "^3.1.0",
+        "cli-width": "^2.0.0",
+        "external-editor": "^3.0.3",
+        "figures": "^3.0.0",
+        "lodash": "^4.17.15",
+        "mute-stream": "0.0.8",
+        "run-async": "^2.4.0",
+        "rxjs": "^6.5.3",
+        "string-width": "^4.1.0",
+        "strip-ansi": "^6.0.0",
+        "through": "^2.3.6"
+      },
+      "dependencies": {
+        "ansi-escapes": {
+          "version": "4.3.1",
+          "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.1.tgz",
+          "integrity": "sha512-JWF7ocqNrp8u9oqpgV+wH5ftbt+cfvv+PTjOvKLT3AdYly/LmORARfEVT1iyjwN+4MqE5UmVKoAdIBqeoCHgLA==",
+          "dev": true,
+          "requires": {
+            "type-fest": "^0.11.0"
+          }
+        },
+        "ansi-regex": {
+          "version": "5.0.0",
+          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
+          "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==",
+          "dev": true
+        },
+        "ansi-styles": {
+          "version": "4.2.1",
+          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz",
+          "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==",
+          "dev": true,
+          "requires": {
+            "@types/color-name": "^1.1.1",
+            "color-convert": "^2.0.1"
+          }
+        },
+        "chalk": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz",
+          "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==",
+          "dev": true,
+          "requires": {
+            "ansi-styles": "^4.1.0",
+            "supports-color": "^7.1.0"
+          }
+        },
+        "color-convert": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+          "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+          "dev": true,
+          "requires": {
+            "color-name": "~1.1.4"
+          }
+        },
+        "color-name": {
+          "version": "1.1.4",
+          "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+          "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+          "dev": true
+        },
+        "emoji-regex": {
+          "version": "8.0.0",
+          "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+          "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+          "dev": true
+        },
+        "has-flag": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+          "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+          "dev": true
+        },
+        "is-fullwidth-code-point": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+          "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+          "dev": true
+        },
+        "string-width": {
+          "version": "4.2.0",
+          "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz",
+          "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==",
+          "dev": true,
+          "requires": {
+            "emoji-regex": "^8.0.0",
+            "is-fullwidth-code-point": "^3.0.0",
+            "strip-ansi": "^6.0.0"
+          }
+        },
+        "strip-ansi": {
+          "version": "6.0.0",
+          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
+          "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
+          "dev": true,
+          "requires": {
+            "ansi-regex": "^5.0.0"
+          }
+        },
+        "supports-color": {
+          "version": "7.1.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
+          "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==",
+          "dev": true,
+          "requires": {
+            "has-flag": "^4.0.0"
+          }
+        }
+      }
+    },
+    "into-stream": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/into-stream/-/into-stream-3.1.0.tgz",
+      "integrity": "sha1-lvsKk2wSur1v8XUqF9BWFqvQlMY=",
+      "dev": true,
+      "requires": {
+        "from2": "^2.1.1",
+        "p-is-promise": "^1.1.0"
+      }
+    },
+    "ip-address": {
+      "version": "5.9.4",
+      "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-5.9.4.tgz",
+      "integrity": "sha512-dHkI3/YNJq4b/qQaz+c8LuarD3pY24JqZWfjB8aZx1gtpc2MDILu9L9jpZe1sHpzo/yWFweQVn+U//FhazUxmw==",
+      "dev": true,
+      "requires": {
+        "jsbn": "1.1.0",
+        "lodash": "^4.17.15",
+        "sprintf-js": "1.1.2"
+      },
+      "dependencies": {
+        "sprintf-js": {
+          "version": "1.1.2",
+          "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz",
+          "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==",
+          "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
+    },
+    "is-callable": {
+      "version": "1.1.5",
+      "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz",
+      "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==",
+      "dev": true
+    },
+    "is-date-object": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz",
+      "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==",
+      "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
+    },
+    "is-object": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.1.tgz",
+      "integrity": "sha1-iVJojF7C/9awPsyF52ngKQMINHA=",
+      "dev": true
+    },
+    "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=",
+      "dev": true
+    },
+    "is-promise": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz",
+      "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o="
+    },
+    "is-regex": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz",
+      "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==",
+      "dev": true,
+      "requires": {
+        "has": "^1.0.3"
+      }
+    },
+    "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==",
+      "dev": true
+    },
+    "is-stream": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz",
+      "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==",
+      "dev": true
+    },
+    "is-symbol": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz",
+      "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==",
+      "dev": true,
+      "requires": {
+        "has-symbols": "^1.0.1"
+      }
+    },
+    "is-url": {
+      "version": "1.2.4",
+      "resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz",
+      "integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==",
+      "dev": true
+    },
+    "is-wsl": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz",
+      "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=",
+      "dev": true
+    },
+    "isarray": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz",
+      "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4="
+    },
+    "isexe": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+      "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA="
+    },
+    "isurl": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/isurl/-/isurl-1.0.0.tgz",
+      "integrity": "sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w==",
+      "dev": true,
+      "requires": {
+        "has-to-string-tag-x": "^1.2.0",
+        "is-object": "^1.0.1"
+      }
+    },
+    "iterm2-version": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/iterm2-version/-/iterm2-version-2.3.0.tgz",
+      "integrity": "sha1-rmQABGHgK18f5TMfC58Oxxzg4Tg=",
+      "dev": true,
+      "requires": {
+        "app-path": "^2.1.0",
+        "plist": "^2.0.1"
+      }
+    },
+    "js-yaml": {
+      "version": "3.13.1",
+      "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz",
+      "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==",
+      "requires": {
+        "argparse": "^1.0.7",
+        "esprima": "^4.0.0"
+      }
+    },
+    "jsbn": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz",
+      "integrity": "sha1-sBMHyym2GKHtJux56RH4A8TaAEA=",
+      "dev": true
+    },
+    "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
+    },
+    "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==",
+      "dev": true
+    },
+    "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"
+      }
+    },
+    "keypair": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/keypair/-/keypair-1.0.1.tgz",
+      "integrity": "sha1-dgNxknCvtlZO04oiCHoG/Jqk6hs=",
+      "dev": true
+    },
+    "keyv": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.0.0.tgz",
+      "integrity": "sha512-eguHnq22OE3uVoSYG0LVWNP+4ppamWr9+zWBe1bsNcovIMy6huUJFPgy4mGwCd/rnl3vOLGW1MTlu4c57CT1xA==",
+      "dev": true,
+      "requires": {
+        "json-buffer": "3.0.0"
+      }
+    },
+    "load-json-file": {
+      "version": "5.3.0",
+      "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-5.3.0.tgz",
+      "integrity": "sha512-cJGP40Jc/VXUsp8/OrnyKyTZ1y6v/dphm3bioS+RrKXjK2BB6wHUd6JptZEFDGgGahMT+InnZO5i1Ei9mpC8Bw==",
+      "dev": true,
+      "requires": {
+        "graceful-fs": "^4.1.15",
+        "parse-json": "^4.0.0",
+        "pify": "^4.0.1",
+        "strip-bom": "^3.0.0",
+        "type-fest": "^0.3.0"
+      },
+      "dependencies": {
+        "type-fest": {
+          "version": "0.3.1",
+          "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.3.1.tgz",
+          "integrity": "sha512-cUGJnCdr4STbePCgqNFbpVNCepa+kAVohJs1sLhxzdH+gnEoOd8VhbYa7pD3zZYGiURWM2xzEII3fQcRizDkYQ==",
+          "dev": true
+        }
+      }
+    },
+    "locate-path": {
+      "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"
+      }
+    },
+    "lodash": {
+      "version": "4.17.15",
+      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
+      "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A=="
+    },
+    "lodash._reinterpolate": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz",
+      "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=",
+      "dev": true
+    },
+    "lodash.defaults": {
+      "version": "4.2.0",
+      "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz",
+      "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=",
+      "dev": true
+    },
+    "lodash.flatten": {
+      "version": "4.4.0",
+      "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz",
+      "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=",
+      "dev": true
+    },
+    "lodash.keyby": {
+      "version": "4.6.0",
+      "resolved": "https://registry.npmjs.org/lodash.keyby/-/lodash.keyby-4.6.0.tgz",
+      "integrity": "sha1-f2oavak/0k4icopNNh7YvLpaQ1Q=",
+      "dev": true
+    },
+    "lodash.sortby": {
+      "version": "4.7.0",
+      "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz",
+      "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=",
+      "dev": true
+    },
+    "lodash.template": {
+      "version": "4.5.0",
+      "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.5.0.tgz",
+      "integrity": "sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A==",
+      "dev": true,
+      "requires": {
+        "lodash._reinterpolate": "^3.0.0",
+        "lodash.templatesettings": "^4.0.0"
+      }
+    },
+    "lodash.templatesettings": {
+      "version": "4.2.0",
+      "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz",
+      "integrity": "sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ==",
+      "dev": true,
+      "requires": {
+        "lodash._reinterpolate": "^3.0.0"
+      }
+    },
+    "log-chopper": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/log-chopper/-/log-chopper-1.0.2.tgz",
+      "integrity": "sha512-tEWS6Fb+Xv0yLChJ6saA1DP3H1yPL0PfiIN7SDJ+U/CyP+fD4G/dhKfow+P5UuJWi6BdE4mUcPkJclGXCWxDrg==",
+      "dev": true,
+      "requires": {
+        "byline": "5.x"
+      }
+    },
+    "long": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz",
+      "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA=="
+    },
+    "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
+    },
+    "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"
+      }
+    },
+    "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==",
+      "dev": true,
+      "requires": {
+        "pify": "^4.0.1",
+        "semver": "^5.6.0"
+      }
+    },
+    "mariadb": {
+      "version": "2.3.1",
+      "resolved": "https://registry.npmjs.org/mariadb/-/mariadb-2.3.1.tgz",
+      "integrity": "sha512-suv+ygoiS+tQSKmxgzJsGV9R+USN8g6Ql+GuMo9k7alD6FxOT/lwebLHy63/7yPZfVtlyAitK1tPd7ZoFhN/Sg==",
+      "requires": {
+        "@types/geojson": "^7946.0.7",
+        "@types/node": ">=8.0.0",
+        "denque": "^1.4.1",
+        "iconv-lite": "^0.5.1",
+        "long": "^4.0.0",
+        "moment-timezone": "^0.5.27"
+      },
+      "dependencies": {
+        "iconv-lite": {
+          "version": "0.5.1",
+          "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.5.1.tgz",
+          "integrity": "sha512-ONHr16SQvKZNSqjQT9gy5z24Jw+uqfO02/ngBSBoqChZ+W8qXX7GPRa1RoUnzGADw8K63R1BXUMzarCVQBpY8Q==",
+          "requires": {
+            "safer-buffer": ">= 2.1.2 < 3"
+          }
+        }
+      }
+    },
+    "mime-db": {
+      "version": "1.43.0",
+      "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz",
+      "integrity": "sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ=="
+    },
+    "mime-types": {
+      "version": "2.1.26",
+      "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.26.tgz",
+      "integrity": "sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ==",
+      "requires": {
+        "mime-db": "1.43.0"
+      }
+    },
+    "mimic-fn": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
+      "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg=="
+    },
+    "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
+    },
+    "minimatch": {
+      "version": "3.0.4",
+      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
+      "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+      "requires": {
+        "brace-expansion": "^1.1.7"
+      }
+    },
+    "minimist": {
+      "version": "1.2.5",
+      "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
+      "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw=="
+    },
+    "mkdirp": {
+      "version": "0.5.4",
+      "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.4.tgz",
+      "integrity": "sha512-iG9AK/dJLtJ0XNgTuDbSyNS3zECqDlAhnQW4CsNxBG3LQJBbHmRX1egw39DmtOdCAqY+dKXV+sgPgilNWUKMVw==",
+      "requires": {
+        "minimist": "^1.2.5"
+      }
+    },
+    "moment": {
+      "version": "2.24.0",
+      "resolved": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz",
+      "integrity": "sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg=="
+    },
+    "moment-timezone": {
+      "version": "0.5.28",
+      "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.28.tgz",
+      "integrity": "sha512-TDJkZvAyKIVWg5EtVqRzU97w0Rb0YVbfpqyjgu6GwXCAohVRqwZjf4fOzDE6p1Ch98Sro/8hQQi65WDXW5STPw==",
+      "requires": {
+        "moment": ">= 2.9.0"
+      }
+    },
+    "ms": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+      "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
+    },
+    "mustache": {
+      "version": "2.3.2",
+      "resolved": "https://registry.npmjs.org/mustache/-/mustache-2.3.2.tgz",
+      "integrity": "sha512-KpMNwdQsYz3O/SBS1qJ/o3sqUJ5wSb8gb0pul8CO0S56b9Y2ALm8zCfsjPXsqGFfoNBkDwZuZIAjhsZI03gYVQ==",
+      "dev": true
+    },
+    "mute-stream": {
+      "version": "0.0.8",
+      "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz",
+      "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==",
+      "dev": true
+    },
+    "natural-orderby": {
+      "version": "2.0.3",
+      "resolved": "https://registry.npmjs.org/natural-orderby/-/natural-orderby-2.0.3.tgz",
+      "integrity": "sha512-p7KTHxU0CUrcOXe62Zfrb5Z13nLvPhSWR/so3kFulUQU0sgUll2Z0LwpsLN351eOOD+hRGu/F1g+6xDfPeD++Q==",
+      "dev": true
+    },
+    "negotiator": {
+      "version": "0.6.2",
+      "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
+      "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw=="
+    },
+    "netrc-parser": {
+      "version": "3.1.6",
+      "resolved": "https://registry.npmjs.org/netrc-parser/-/netrc-parser-3.1.6.tgz",
+      "integrity": "sha512-lY+fmkqSwntAAjfP63jB4z5p5WbuZwyMCD3pInT7dpHU/Gc6Vv90SAC6A0aNiqaRGHiuZFBtiwu+pu8W/Eyotw==",
+      "dev": true,
+      "requires": {
+        "debug": "^3.1.0",
+        "execa": "^0.10.0"
+      },
+      "dependencies": {
+        "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"
+          }
+        },
+        "execa": {
+          "version": "0.10.0",
+          "resolved": "https://registry.npmjs.org/execa/-/execa-0.10.0.tgz",
+          "integrity": "sha512-7XOMnz8Ynx1gGo/3hyV9loYNPWM94jG3+3T3Y8tsfSstFmETmENCMU/A/zj8Lyaj1lkgEepKepvd6240tBRvlw==",
+          "dev": true,
+          "requires": {
+            "cross-spawn": "^6.0.0",
+            "get-stream": "^3.0.0",
+            "is-stream": "^1.1.0",
+            "npm-run-path": "^2.0.0",
+            "p-finally": "^1.0.0",
+            "signal-exit": "^3.0.0",
+            "strip-eof": "^1.0.0"
+          }
+        },
+        "is-stream": {
+          "version": "1.1.0",
+          "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
+          "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=",
+          "dev": true
+        }
+      }
+    },
+    "nice-try": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
+      "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ=="
+    },
+    "node-environment-flags": {
+      "version": "1.0.6",
+      "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.6.tgz",
+      "integrity": "sha512-5Evy2epuL+6TM0lCQGpFIj6KwiEsGh1SrHUhTbNX+sLbBtjidPZFAnVK9y5yU1+h//RitLbRHTIMyxQPtxMdHw==",
+      "dev": true,
+      "requires": {
+        "object.getownpropertydescriptors": "^2.0.3",
+        "semver": "^5.7.0"
+      }
+    },
+    "node-fetch": {
+      "version": "2.6.0",
+      "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz",
+      "integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA==",
+      "dev": true
+    },
+    "node-forge": {
+      "version": "0.7.5",
+      "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.7.5.tgz",
+      "integrity": "sha512-MmbQJ2MTESTjt3Gi/3yG1wGpIMhUfcIypUCGtTizFR9IiccFwxSpfp0vtIZlkFclEqERemxfnSdZEMR9VqqEFQ==",
+      "dev": true
+    },
+    "node-modules-regexp": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz",
+      "integrity": "sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA=",
+      "dev": true
+    },
+    "node-notifier": {
+      "version": "5.4.3",
+      "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-5.4.3.tgz",
+      "integrity": "sha512-M4UBGcs4jeOK9CjTsYwkvH6/MzuUmGCyTW+kCY7uO+1ZVr0+FHGdPdIf5CCLqAaxnRrWidyoQlNkMIIVwbKB8Q==",
+      "dev": true,
+      "requires": {
+        "growly": "^1.3.0",
+        "is-wsl": "^1.1.0",
+        "semver": "^5.5.0",
+        "shellwords": "^0.1.1",
+        "which": "^1.3.0"
+      }
+    },
+    "nopt": {
+      "version": "4.0.3",
+      "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz",
+      "integrity": "sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==",
+      "dev": true,
+      "requires": {
+        "abbrev": "1",
+        "osenv": "^0.1.4"
+      }
+    },
+    "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==",
+      "dev": true,
+      "requires": {
+        "prepend-http": "^2.0.0",
+        "query-string": "^5.0.1",
+        "sort-keys": "^2.0.0"
+      }
+    },
+    "npm-run-path": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz",
+      "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=",
+      "dev": true,
+      "requires": {
+        "path-key": "^2.0.0"
+      }
+    },
+    "object-assign": {
+      "version": "4.1.1",
+      "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+      "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
+      "dev": true
+    },
+    "object-component": {
+      "version": "0.0.3",
+      "resolved": "https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz",
+      "integrity": "sha1-8MaapQ78lbhmwYb0AKM3acsvEpE="
+    },
+    "object-inspect": {
+      "version": "1.7.0",
+      "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz",
+      "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==",
+      "dev": true
+    },
+    "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.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"
+      }
+    },
+    "object.getownpropertydescriptors": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz",
+      "integrity": "sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg==",
+      "dev": true,
+      "requires": {
+        "define-properties": "^1.1.3",
+        "es-abstract": "^1.17.0-next.1"
+      }
+    },
+    "once": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+      "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
+      "dev": true,
+      "requires": {
+        "wrappy": "1"
+      }
+    },
+    "onetime": {
+      "version": "5.1.0",
+      "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.0.tgz",
+      "integrity": "sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q==",
+      "dev": true,
+      "requires": {
+        "mimic-fn": "^2.1.0"
+      }
+    },
+    "open": {
+      "version": "6.4.0",
+      "resolved": "https://registry.npmjs.org/open/-/open-6.4.0.tgz",
+      "integrity": "sha512-IFenVPgF70fSm1keSd2iDBIDIBZkroLeuffXq+wKTzTJlBpesFWojV9lb8mzOfaAzM1sr7HQHuO0vtV0zYekGg==",
+      "dev": true,
+      "requires": {
+        "is-wsl": "^1.1.0"
+      }
+    },
+    "opn": {
+      "version": "3.0.3",
+      "resolved": "https://registry.npmjs.org/opn/-/opn-3.0.3.tgz",
+      "integrity": "sha1-ttmec5n3jWXDuq/+8fsojpuFJDo=",
+      "dev": true,
+      "requires": {
+        "object-assign": "^4.0.1"
+      }
+    },
+    "original": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/original/-/original-1.0.2.tgz",
+      "integrity": "sha512-hyBVl6iqqUOJ8FqRe+l/gS8H+kKYjrEndd5Pm1MfBtsEKA038HkkdbAl/72EAXGyonD/PFsvmVG+EvcIpliMBg==",
+      "dev": true,
+      "requires": {
+        "url-parse": "^1.4.3"
+      }
+    },
+    "os-homedir": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
+      "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=",
+      "dev": true
+    },
+    "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="
+    },
+    "osenv": {
+      "version": "0.1.5",
+      "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz",
+      "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==",
+      "dev": true,
+      "requires": {
+        "os-homedir": "^1.0.0",
+        "os-tmpdir": "^1.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==",
+      "dev": true
+    },
+    "p-finally": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz",
+      "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=",
+      "dev": true
+    },
+    "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=",
+      "dev": true
+    },
+    "p-limit": {
+      "version": "2.2.2",
+      "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.2.tgz",
+      "integrity": "sha512-WGR+xHecKTr7EbUEhyLSh5Dube9JtdiG78ufaeLxTgpudf/20KqyMioIUZJAezlTIi6evxuoUs9YXc11cU+yzQ==",
+      "dev": true,
+      "requires": {
+        "p-try": "^2.0.0"
+      }
+    },
+    "p-locate": {
+      "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==",
+      "dev": true,
+      "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
+    },
+    "parse-json": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
+      "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=",
+      "dev": true,
+      "requires": {
+        "error-ex": "^1.3.1",
+        "json-parse-better-errors": "^1.0.1"
+      }
+    },
+    "parse-passwd": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz",
+      "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=",
+      "dev": true
+    },
+    "parseqs": {
+      "version": "0.0.5",
+      "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz",
+      "integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=",
+      "requires": {
+        "better-assert": "~1.0.0"
+      }
+    },
+    "parseuri": {
+      "version": "0.0.5",
+      "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz",
+      "integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=",
+      "requires": {
+        "better-assert": "~1.0.0"
+      }
+    },
+    "password-prompt": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/password-prompt/-/password-prompt-1.1.2.tgz",
+      "integrity": "sha512-bpuBhROdrhuN3E7G/koAju0WjVw9/uQOG5Co5mokNj0MiOSBVZS1JTwM4zl55hu0WFmIEFvO9cU9sJQiBIYeIA==",
+      "dev": true,
+      "requires": {
+        "ansi-escapes": "^3.1.0",
+        "cross-spawn": "^6.0.5"
+      }
+    },
+    "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
+    },
+    "path-is-absolute": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+      "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
+      "dev": true
+    },
+    "path-key": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
+      "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A="
+    },
+    "phoenix": {
+      "version": "1.4.16",
+      "resolved": "https://registry.npmjs.org/phoenix/-/phoenix-1.4.16.tgz",
+      "integrity": "sha512-XmKVTlFQuRwTYBO1WU1OaN2tzywRAtY6haUpxHPGxNZuyPEgmo+Caw7+BMlIPhipM197+d962i6sGZLylBtCbA==",
+      "dev": true
+    },
+    "pify": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz",
+      "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==",
+      "dev": true
+    },
+    "pirates": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.1.tgz",
+      "integrity": "sha512-WuNqLTbMI3tmfef2TKxlQmAiLHKtFhlsCZnPIpuv2Ow0RDVO8lfy1Opf4NUzlMXLjPl+Men7AuVdX6TA+s+uGA==",
+      "dev": true,
+      "requires": {
+        "node-modules-regexp": "^1.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==",
+      "dev": true,
+      "requires": {
+        "find-up": "^3.0.0"
+      }
+    },
+    "plist": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/plist/-/plist-2.1.0.tgz",
+      "integrity": "sha1-V8zbeggh3yGDEhejytVOPhRqECU=",
+      "dev": true,
+      "requires": {
+        "base64-js": "1.2.0",
+        "xmlbuilder": "8.2.2",
+        "xmldom": "0.1.x"
+      }
+    },
+    "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
+    },
+    "printf": {
+      "version": "0.5.1",
+      "resolved": "https://registry.npmjs.org/printf/-/printf-0.5.1.tgz",
+      "integrity": "sha512-UaE/jO0hNsrvPGQEb4LyNzcrJv9Z00tsreBduOSxMtrebvoUhxiEJ4YCHX8YHf6akwfKsC2Gyv5zv47UXhMiLg==",
+      "dev": true
+    },
+    "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
+    },
+    "pseudomap": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
+      "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=",
+      "dev": true
+    },
+    "psl": {
+      "version": "1.8.0",
+      "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz",
+      "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==",
+      "dev": true
+    },
+    "pump": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
+      "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
+      "dev": true,
+      "requires": {
+        "end-of-stream": "^1.1.0",
+        "once": "^1.3.1"
+      }
+    },
+    "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==",
+      "dev": true,
+      "requires": {
+        "decode-uri-component": "^0.2.0",
+        "object-assign": "^4.1.0",
+        "strict-uri-encode": "^1.0.0"
+      }
+    },
+    "querystringify": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.1.1.tgz",
+      "integrity": "sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA==",
+      "dev": true
+    },
+    "readable-stream": {
+      "version": "2.3.7",
+      "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
+      "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
+      "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"
+      },
+      "dependencies": {
+        "isarray": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+          "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
+          "dev": true
+        },
+        "safe-buffer": {
+          "version": "5.1.2",
+          "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+          "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+          "dev": true
+        }
+      }
+    },
+    "redeyed": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/redeyed/-/redeyed-2.1.1.tgz",
+      "integrity": "sha1-iYS1gV2ZyyIEacme7v/jiRPmzAs=",
+      "dev": true,
+      "requires": {
+        "esprima": "~4.0.0"
+      }
+    },
+    "redis-errors": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz",
+      "integrity": "sha1-62LSrbFeTq9GEMBK/hUpOEJQq60=",
+      "dev": true
+    },
+    "redis-parser": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz",
+      "integrity": "sha1-tm2CjNyv5rS4pCin3vTGvKwxyLQ=",
+      "dev": true,
+      "requires": {
+        "redis-errors": "^1.0.0"
+      }
+    },
+    "regenerator-runtime": {
+      "version": "0.13.5",
+      "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz",
+      "integrity": "sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA==",
+      "dev": true
+    },
+    "requires-port": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
+      "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=",
+      "dev": true
+    },
+    "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": "3.1.0",
+      "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz",
+      "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==",
+      "dev": true,
+      "requires": {
+        "onetime": "^5.1.0",
+        "signal-exit": "^3.0.2"
+      }
+    },
+    "rimraf": {
+      "version": "2.7.1",
+      "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
+      "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
+      "dev": true,
+      "requires": {
+        "glob": "^7.1.3"
+      }
+    },
+    "run-async": {
+      "version": "2.4.0",
+      "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.0.tgz",
+      "integrity": "sha512-xJTbh/d7Lm7SBhc1tNvTpeCHaEzoyxPrqNlvSdMfBTYwaY++UJFyXUOxAtsRUXjlqOfj8luNaR9vjCh4KeV+pg==",
+      "requires": {
+        "is-promise": "^2.1.0"
+      }
+    },
+    "rxjs": {
+      "version": "6.5.4",
+      "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.4.tgz",
+      "integrity": "sha512-naMQXcgEo3csAEGvw/NydRA0fuS2nDZJiw1YUWFKU7aPPAPGZEsD4Iimit96qwCieH6y614MCLYwdkrWx7z/7Q==",
+      "requires": {
+        "tslib": "^1.9.0"
+      }
+    },
+    "safe-buffer": {
+      "version": "5.2.0",
+      "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz",
+      "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==",
+      "dev": true
+    },
+    "safer-buffer": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+      "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
+    },
+    "semver": {
+      "version": "5.7.1",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+      "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="
+    },
+    "shebang-command": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
+      "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=",
+      "requires": {
+        "shebang-regex": "^1.0.0"
+      }
+    },
+    "shebang-regex": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
+      "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM="
+    },
+    "shell-escape": {
+      "version": "0.2.0",
+      "resolved": "https://registry.npmjs.org/shell-escape/-/shell-escape-0.2.0.tgz",
+      "integrity": "sha1-aP0CXrBJC09WegJ/C/IkgLX4QTM=",
+      "dev": true
+    },
+    "shell-quote": {
+      "version": "1.7.2",
+      "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.2.tgz",
+      "integrity": "sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg==",
+      "dev": true
+    },
+    "shellwords": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/shellwords/-/shellwords-0.1.1.tgz",
+      "integrity": "sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==",
+      "dev": true
+    },
+    "signal-exit": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
+      "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0="
+    },
+    "smooth-progress": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/smooth-progress/-/smooth-progress-1.1.0.tgz",
+      "integrity": "sha1-pR1tvCscRjWslL9L6JNk1c6RzjI=",
+      "dev": true,
+      "requires": {
+        "ansi-escapes": "1.4.0",
+        "chalk": "^1.1.1"
+      },
+      "dependencies": {
+        "ansi-escapes": {
+          "version": "1.4.0",
+          "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz",
+          "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=",
+          "dev": true
+        },
+        "ansi-regex": {
+          "version": "2.1.1",
+          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+          "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
+          "dev": true
+        },
+        "ansi-styles": {
+          "version": "2.2.1",
+          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+          "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
+          "dev": true
+        },
+        "chalk": {
+          "version": "1.1.3",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+          "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+          "dev": true,
+          "requires": {
+            "ansi-styles": "^2.2.1",
+            "escape-string-regexp": "^1.0.2",
+            "has-ansi": "^2.0.0",
+            "strip-ansi": "^3.0.0",
+            "supports-color": "^2.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"
+          }
+        },
+        "supports-color": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
+          "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
+          "dev": true
+        }
+      }
+    },
+    "socket.io": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.3.0.tgz",
+      "integrity": "sha512-2A892lrj0GcgR/9Qk81EaY2gYhCBxurV0PfmmESO6p27QPrUK1J3zdns+5QPqvUYK2q657nSj0guoIil9+7eFg==",
+      "requires": {
+        "debug": "~4.1.0",
+        "engine.io": "~3.4.0",
+        "has-binary2": "~1.0.2",
+        "socket.io-adapter": "~1.1.0",
+        "socket.io-client": "2.3.0",
+        "socket.io-parser": "~3.4.0"
+      }
+    },
+    "socket.io-adapter": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-1.1.2.tgz",
+      "integrity": "sha512-WzZRUj1kUjrTIrUKpZLEzFZ1OLj5FwLlAFQs9kuZJzJi5DKdU7FsWc36SNmA8iDOtwBQyT8FkrriRM8vXLYz8g=="
+    },
+    "socket.io-client": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.3.0.tgz",
+      "integrity": "sha512-cEQQf24gET3rfhxZ2jJ5xzAOo/xhZwK+mOqtGRg5IowZsMgwvHwnf/mCRapAAkadhM26y+iydgwsXGObBB5ZdA==",
+      "requires": {
+        "backo2": "1.0.2",
+        "base64-arraybuffer": "0.1.5",
+        "component-bind": "1.0.0",
+        "component-emitter": "1.2.1",
+        "debug": "~4.1.0",
+        "engine.io-client": "~3.4.0",
+        "has-binary2": "~1.0.2",
+        "has-cors": "1.1.0",
+        "indexof": "0.0.1",
+        "object-component": "0.0.3",
+        "parseqs": "0.0.5",
+        "parseuri": "0.0.5",
+        "socket.io-parser": "~3.3.0",
+        "to-array": "0.1.4"
+      },
+      "dependencies": {
+        "ms": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+          "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+        },
+        "socket.io-parser": {
+          "version": "3.3.0",
+          "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.3.0.tgz",
+          "integrity": "sha512-hczmV6bDgdaEbVqhAeVMM/jfUfzuEZHsQg6eOmLgJht6G3mPKMxYm75w2+qhAQZ+4X+1+ATZ+QFKeOZD5riHng==",
+          "requires": {
+            "component-emitter": "1.2.1",
+            "debug": "~3.1.0",
+            "isarray": "2.0.1"
+          },
+          "dependencies": {
+            "debug": {
+              "version": "3.1.0",
+              "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
+              "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
+              "requires": {
+                "ms": "2.0.0"
+              }
+            }
+          }
+        }
+      }
+    },
+    "socket.io-parser": {
+      "version": "3.4.0",
+      "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.4.0.tgz",
+      "integrity": "sha512-/G/VOI+3DBp0+DJKW4KesGnQkQPFmUCbA/oO2QGT6CWxU7hLGWqU3tyuzeSK/dqcyeHsQg1vTe9jiZI8GU9SCQ==",
+      "requires": {
+        "component-emitter": "1.2.1",
+        "debug": "~4.1.0",
+        "isarray": "2.0.1"
+      }
+    },
+    "sort-keys": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-2.0.0.tgz",
+      "integrity": "sha1-ZYU1WEhh7JfXMNbPQYIuH1ZoQSg=",
+      "dev": true,
+      "requires": {
+        "is-plain-obj": "^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==",
+      "dev": true
+    },
+    "source-map-support": {
+      "version": "0.5.16",
+      "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.16.tgz",
+      "integrity": "sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ==",
+      "dev": true,
+      "requires": {
+        "buffer-from": "^1.0.0",
+        "source-map": "^0.6.0"
+      }
+    },
+    "sparkline": {
+      "version": "0.2.0",
+      "resolved": "https://registry.npmjs.org/sparkline/-/sparkline-0.2.0.tgz",
+      "integrity": "sha1-vJqI17g4j8GpUf3hJ1+c5A/ssiI=",
+      "dev": true,
+      "requires": {
+        "here": "0.0.2",
+        "nopt": "~4.0.1"
+      }
+    },
+    "sprintf-js": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
+      "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw="
+    },
+    "ssh2": {
+      "version": "0.5.4",
+      "resolved": "https://registry.npmjs.org/ssh2/-/ssh2-0.5.4.tgz",
+      "integrity": "sha1-G/a2soyW6u8mf01sRqWiUXpZnic=",
+      "dev": true,
+      "requires": {
+        "ssh2-streams": "~0.1.15"
+      }
+    },
+    "ssh2-streams": {
+      "version": "0.1.20",
+      "resolved": "https://registry.npmjs.org/ssh2-streams/-/ssh2-streams-0.1.20.tgz",
+      "integrity": "sha1-URGNFUVV31Rp7h9n4M8efoosDjo=",
+      "dev": true,
+      "requires": {
+        "asn1": "~0.2.0",
+        "semver": "^5.1.0",
+        "streamsearch": "~0.1.2"
+      }
+    },
+    "streamsearch": {
+      "version": "0.1.2",
+      "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz",
+      "integrity": "sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo=",
+      "dev": true
+    },
+    "strftime": {
+      "version": "0.10.0",
+      "resolved": "https://registry.npmjs.org/strftime/-/strftime-0.10.0.tgz",
+      "integrity": "sha1-s/D6QZKVICpaKJ9ta+n0kJphcZM=",
+      "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=",
+      "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"
+      },
+      "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
+        },
+        "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"
+          }
+        }
+      }
+    },
+    "string.prototype.trimleft": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.1.tgz",
+      "integrity": "sha512-iu2AGd3PuP5Rp7x2kEZCrB2Nf41ehzh+goo8TV7z8/XDBbsvc6HQIlUl9RjkZ4oyrW1XM5UwlGl1oVEaDjg6Ag==",
+      "dev": true,
+      "requires": {
+        "define-properties": "^1.1.3",
+        "function-bind": "^1.1.1"
+      }
+    },
+    "string.prototype.trimright": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.1.tgz",
+      "integrity": "sha512-qFvWL3/+QIgZXVmJBfpHmxLB7xsUXz6HsUmP8+5dRaC3Q7oKUv9Vo6aMCRZC1smrtyECFsIT30PqBJ1gTjAs+g==",
+      "dev": true,
+      "requires": {
+        "define-properties": "^1.1.3",
+        "function-bind": "^1.1.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"
+      },
+      "dependencies": {
+        "safe-buffer": {
+          "version": "5.1.2",
+          "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+          "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+          "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==",
+      "requires": {
+        "ansi-regex": "^4.1.0"
+      }
+    },
+    "strip-bom": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
+      "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=",
+      "dev": true
+    },
+    "strip-eof": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz",
+      "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=",
+      "dev": true
+    },
+    "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"
+      }
+    },
+    "supports-hyperlinks": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-1.0.1.tgz",
+      "integrity": "sha512-HHi5kVSefKaJkGYXbDuKbUGRVxqnWGn3J2e39CYcNJEfWciGq2zYtOhXLTlvrOZW1QU7VX67w7fMmWafHX9Pfw==",
+      "dev": true,
+      "requires": {
+        "has-flag": "^2.0.0",
+        "supports-color": "^5.0.0"
+      },
+      "dependencies": {
+        "has-flag": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz",
+          "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=",
+          "dev": true
+        }
+      }
+    },
+    "tar-fs": {
+      "version": "1.16.3",
+      "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-1.16.3.tgz",
+      "integrity": "sha512-NvCeXpYx7OsmOh8zIOP/ebG55zZmxLE0etfWRbWok+q2Qo8x/vOR/IJT1taADXPe+jsiu9axDb3X4B+iIgNlKw==",
+      "dev": true,
+      "requires": {
+        "chownr": "^1.0.1",
+        "mkdirp": "^0.5.1",
+        "pump": "^1.0.0",
+        "tar-stream": "^1.1.2"
+      },
+      "dependencies": {
+        "pump": {
+          "version": "1.0.3",
+          "resolved": "https://registry.npmjs.org/pump/-/pump-1.0.3.tgz",
+          "integrity": "sha512-8k0JupWme55+9tCVE+FS5ULT3K6AbgqrGa58lTT49RpyfwwcGedHqaC5LlQNdEAumn/wFsu6aPwkuPMioy8kqw==",
+          "dev": true,
+          "requires": {
+            "end-of-stream": "^1.1.0",
+            "once": "^1.3.1"
+          }
+        }
+      }
+    },
+    "tar-stream": {
+      "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",
+        "end-of-stream": "^1.0.0",
+        "fs-constants": "^1.0.0",
+        "readable-stream": "^2.3.0",
+        "to-buffer": "^1.1.1",
+        "xtend": "^4.0.0"
+      }
+    },
+    "temp": {
+      "version": "0.8.4",
+      "resolved": "https://registry.npmjs.org/temp/-/temp-0.8.4.tgz",
+      "integrity": "sha512-s0ZZzd0BzYv5tLSptZooSjK8oj6C+c19p7Vqta9+6NPOf7r+fxq0cJe6/oN4LTC79sy5NY8ucOJNgwsKCSbfqg==",
+      "dev": true,
+      "requires": {
+        "rimraf": "~2.6.2"
+      },
+      "dependencies": {
+        "rimraf": {
+          "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"
+          }
+        }
+      }
+    },
+    "term-img": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/term-img/-/term-img-2.1.0.tgz",
+      "integrity": "sha512-j78Y+26QYTTWvtVVCmDx94idvQm6p59E+xRfQDSevIyM8dg45uUAtr/xbu13l0BeKrebPyUpgh8PM3noXlIBkw==",
+      "dev": true,
+      "requires": {
+        "ansi-escapes": "^2.0.0",
+        "iterm2-version": "^2.1.0"
+      },
+      "dependencies": {
+        "ansi-escapes": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-2.0.0.tgz",
+          "integrity": "sha1-W65SvkJIeN2Xg+iRDj/Cki6DyBs=",
+          "dev": true
+        }
+      }
+    },
+    "through": {
+      "version": "2.3.8",
+      "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
+      "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU="
+    },
+    "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=",
+      "dev": true
+    },
+    "tmp": {
+      "version": "0.0.33",
+      "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
+      "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
+      "requires": {
+        "os-tmpdir": "~1.0.2"
+      }
+    },
+    "to-array": {
+      "version": "0.1.4",
+      "resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz",
+      "integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA="
+    },
+    "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
+    },
+    "to-readable-stream": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz",
+      "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==",
+      "dev": true
+    },
+    "treeify": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/treeify/-/treeify-1.1.0.tgz",
+      "integrity": "sha512-1m4RA7xVAJrSGrrXGs0L3YTwyvBs2S8PbRHaLZAkFw7JR8oIFwYtysxlBZhYIa7xSyiYJKZ3iGrrk55cGA3i9A==",
+      "dev": true
+    },
+    "true-myth": {
+      "version": "2.2.3",
+      "resolved": "https://registry.npmjs.org/true-myth/-/true-myth-2.2.3.tgz",
+      "integrity": "sha512-ZdlJjMyNBtOjlR0qbYboAfdnXYhUPuD5F5QOAaKEgdUPg3UTxuTfC5cu3MidWIRemI3iWcuUZEwKybDJXP0Ocw==",
+      "dev": true
+    },
+    "tslib": {
+      "version": "1.9.3",
+      "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz",
+      "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ=="
+    },
+    "tunnel-agent": {
+      "version": "0.6.0",
+      "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
+      "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=",
+      "dev": true,
+      "requires": {
+        "safe-buffer": "^5.0.1"
+      }
+    },
+    "tunnel-ssh": {
+      "version": "4.1.4",
+      "resolved": "https://registry.npmjs.org/tunnel-ssh/-/tunnel-ssh-4.1.4.tgz",
+      "integrity": "sha512-CjBqboGvAbM7iXSX2F95kzoI+c2J81YkrHbyyo4SWNKCzU6w5LfEvXBCHu6PPriYaNvfhMKzD8bFf5Vl14YTtg==",
+      "dev": true,
+      "requires": {
+        "debug": "2.6.9",
+        "lodash.defaults": "^4.1.0",
+        "ssh2": "0.5.4"
+      },
+      "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"
+          }
+        },
+        "ms": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+          "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+          "dev": true
+        }
+      }
+    },
+    "type-fest": {
+      "version": "0.11.0",
+      "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.11.0.tgz",
+      "integrity": "sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ==",
+      "dev": true
+    },
+    "universalify": {
+      "version": "0.1.2",
+      "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
+      "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==",
+      "dev": true
+    },
+    "urijs": {
+      "version": "1.19.2",
+      "resolved": "https://registry.npmjs.org/urijs/-/urijs-1.19.2.tgz",
+      "integrity": "sha512-s/UIq9ap4JPZ7H1EB5ULo/aOUbWqfDi7FKzMC2Nz+0Si8GiT1rIEaprt8hy3Vy2Ex2aJPpOQv4P4DuOZ+K1c6w==",
+      "dev": true
+    },
+    "url-parse": {
+      "version": "1.4.7",
+      "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.7.tgz",
+      "integrity": "sha512-d3uaVyzDB9tQoSXFvuSUNFibTd9zxd2bkVrDRvF5TmvWWQwqE4lgYJ5m+x1DbecWkw+LK4RNl2CU1hHuOKPVlg==",
+      "dev": true,
+      "requires": {
+        "querystringify": "^2.1.1",
+        "requires-port": "^1.0.0"
+      }
+    },
+    "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=",
+      "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
+    },
+    "uuid": {
+      "version": "3.3.2",
+      "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz",
+      "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==",
+      "dev": true
+    },
+    "v8flags": {
+      "version": "3.1.3",
+      "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.1.3.tgz",
+      "integrity": "sha512-amh9CCg3ZxkzQ48Mhcb8iX7xpAfYJgePHxWMQCBWECpOSqJUXgY26ncA61UTV0BkPqfhcy6mzwCIoP4ygxpW8w==",
+      "dev": true,
+      "requires": {
+        "homedir-polyfill": "^1.0.1"
+      }
+    },
+    "valid-url": {
+      "version": "1.0.9",
+      "resolved": "https://registry.npmjs.org/valid-url/-/valid-url-1.0.9.tgz",
+      "integrity": "sha1-HBRHm0DxOXp1eC8RXkCGRHQzogA=",
+      "dev": true
+    },
+    "validator": {
+      "version": "10.11.0",
+      "resolved": "https://registry.npmjs.org/validator/-/validator-10.11.0.tgz",
+      "integrity": "sha512-X/p3UZerAIsbBfN/IwahhYaBbY68EN/UQBWHtsbXGT5bfrH/p4NQzUCG1kF/rtKaNpnJ7jAu6NGTdSNtyNIXMw==",
+      "dev": true
+    },
+    "which": {
+      "version": "1.3.1",
+      "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
+      "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
+      "requires": {
+        "isexe": "^2.0.0"
+      }
+    },
+    "widest-line": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-2.0.1.tgz",
+      "integrity": "sha512-Ba5m9/Fa4Xt9eb2ELXt77JxVDV8w7qQrH0zS/TWSJdLyAwQjWoOzpzj5lwVftDz6n/EOu3tNACS84v509qwnJA==",
+      "dev": true,
+      "requires": {
+        "string-width": "^2.1.1"
+      }
+    },
+    "wrap-ansi": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-4.0.0.tgz",
+      "integrity": "sha512-uMTsj9rDb0/7kk1PbcbCcwvHUxp60fGDB/NNXpVa0Q+ic/e7y5+BwTxKfQ33VYgDppSwi/FBzpetYzo8s6tfbg==",
+      "dev": true,
+      "requires": {
+        "ansi-styles": "^3.2.0",
+        "string-width": "^2.1.1",
+        "strip-ansi": "^4.0.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
+        },
+        "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"
+          }
+        }
+      }
+    },
+    "wrappy": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+      "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
+      "dev": true
+    },
+    "ws": {
+      "version": "7.2.3",
+      "resolved": "https://registry.npmjs.org/ws/-/ws-7.2.3.tgz",
+      "integrity": "sha512-HTDl9G9hbkNDk98naoR/cHDws7+EyYMOdL1BmjsZXRUjf7d+MficC4B7HLUPlSiho0vg+CWKrGIt/VJBd1xunQ=="
+    },
+    "xmlbuilder": {
+      "version": "8.2.2",
+      "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-8.2.2.tgz",
+      "integrity": "sha1-aSSGc0ELS6QuGmE2VR0pIjNap3M=",
+      "dev": true
+    },
+    "xmldom": {
+      "version": "0.1.31",
+      "resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.1.31.tgz",
+      "integrity": "sha512-yS2uJflVQs6n+CyjHoaBmVSqIDevTAWrzMmjG1Gc7h1qQ7uVozNhEPJAwZXWyGQ/Gafo3fCwrcaokezLPupVyQ==",
+      "dev": true
+    },
+    "xmlhttprequest-ssl": {
+      "version": "1.5.5",
+      "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz",
+      "integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4="
+    },
+    "xtend": {
+      "version": "4.0.2",
+      "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
+      "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
+      "dev": true
+    },
+    "yallist": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
+      "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=",
+      "dev": true
+    },
+    "yarn": {
+      "version": "1.22.4",
+      "resolved": "https://registry.npmjs.org/yarn/-/yarn-1.22.4.tgz",
+      "integrity": "sha512-oYM7hi/lIWm9bCoDMEWgffW8aiNZXCWeZ1/tGy0DWrN6vmzjCXIKu2Y21o8DYVBUtiktwKcNoxyGl/2iKLUNGA==",
+      "dev": true
+    },
+    "yeast": {
+      "version": "0.1.2",
+      "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz",
+      "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk="
+    }
+  }
+}

+ 24 - 0
server/package.json

@@ -0,0 +1,24 @@
+{
+  "name": "twelve-heroes-server",
+  "version": "1.0.0",
+  "description": "twelve heroes game server",
+  "keywords": [
+    "Server"
+  ],
+  "scripts": {
+    "start": "babel-node server.js",
+    "server-dev": "babel-node -r ../node_modules/dotenv/config server.js dotenv_config_path=../.env",
+    "tools": "node tools/server-tools.js"
+  },
+  "author": "JOJO",
+  "license": "MIT",
+  "dependencies": {
+    "mariadb": "^2.3.1",
+    "socket.io": "^2.3.0"
+  },
+  "devDependencies": {
+    "@babel/node": "7.6.2",
+    "heroku": "^7.39.1",
+    "socket.io-client": "^2.3.0"
+  }
+}

+ 15 - 2
server/players/player-id.js

@@ -1,16 +1,29 @@
 'use strict';
 
 export default class PlayerId {
-  constructor(playerSocket, playerName = '', playerColor = 'unk') {
-    this.playerSocket = playerSocket;
+  constructor(playerName = '', playerColor = 'unk') {
+    this.playerSocket = null;
     this.playerName = playerName;
     this.playerColor = playerColor;
+    this.connected=false;
   }
 
+  getSocket() {
+    return this.playerSocket;
+  }
+  setSocket(socket) {
+    this.playerSocket = socket;
+  }
   setPlayerName(playerName) {
     this.playerName = playerName;
   }
   setPlayerColor(playerColor) {
     this.playerColor = playerColor;
   }
+  setConnected(connected) {
+    this.connected = connected;
+  }
+  isConnected() {
+    return this.connected;
+  }
 }

+ 238 - 0
server/server.js

@@ -0,0 +1,238 @@
+'use strict';
+import PlayerId from './players/player-id';
+import DuelController from './game-server/duel-controller';
+import MariadbConnector from './db/mariadb-connector';
+import ServerToolListner from './tools/server-tool-listener';
+
+
+function Server() {
+  console.log('Starting 12 heroes server');
+
+  const io = require('socket.io');
+  const server = io.listen(2610);
+
+  let mariadbConn = new MariadbConnector();
+
+
+  let authorizedPlayers = new Map();
+  let connectedPlayers = new Map();
+  let authorizedPlayersNames = new Set();
+
+
+
+  // let players = [];
+
+
+  // let addNewPlayer = function (playerSocket, playerName) {
+  //   console.log('players length : ' + players.length + ' : ' + players);
+  //   if (players.length < 2) {
+  //     let newPlayer = new PlayerId(playerSocket, playerName);
+  //     console.log('push player : ' + newPlayer);
+  //     players.push(newPlayer);
+  //   }
+  //   if (players.length === 2) {
+  //     let duelController = new DuelController(players[0], players[1]);
+  //   }
+  // };
+
+  server.on('connection', function (socket) {
+    console.log("A player connected with id : " + socket.id);
+
+    socket.on('disconnect', (reason) => {
+      if (reason === 'client namespace disconnect') {
+        console.log("A player disconnected with id : " + socket.id);
+        let playerName = connectedPlayers.get(socket.id);
+        if (playerName) {
+          connectedPlayers.delete(socket.id);
+          authorizedPlayers.get(playerName).setConnected(false);
+          authorizedPlayers.get(playerName).setSocket(null);
+          console.log(playerName + " disconnected");
+        }
+      } else {
+        console.log("disconnected unexpectidly with reason : " + reason);
+      }
+    });
+    socket.on('connect', () => {
+      console.log("Connected to server");
+
+    });
+    socket.on('auth', async (playerName, callback) => {
+      console.log(' Received auth message, player name : ' + playerName);
+      await updatePlayersFromDb();
+
+      let response = {};
+      let kickout = false;
+      if (!authorizedPlayersNames.has(playerName)) {
+        response = {
+          res: "ko",
+          message: playerName + " Not found"
+        };
+        kickout = true;
+      }
+      // If the player is already connected and active
+      else if (authorizedPlayers.get(playerName).isConnected()
+        && authorizedPlayers.get(playerName).getSocket().connected) {
+        response = {
+          res: "ko",
+          message: playerName + " already connected"
+        };
+        kickout = true;
+      }
+      else {
+        // Player marked as connected but socket is down
+        if (authorizedPlayers.get(playerName).isConnected()) {
+          authorizedPlayers.get(playerName).getSocket().disconnect(true);
+        }
+        response = {
+          res: "ok",
+          message: playerName + " connected"
+        };
+        authorizedPlayers.get(playerName).setConnected(true);
+        authorizedPlayers.get(playerName).setSocket(socket);
+        connectedPlayers.set(socket.id, playerName);
+      }
+
+      callback(response);
+      if (kickout === true) {
+        setTimeout(() => {
+          socket.disconnect(true);
+        }, 600);
+      }
+    });
+
+    socket.on('games-list', async (playerName, callback) => {
+      console.log(' Received games-list message, player name : ' + playerName);
+      let response = {};
+      try {
+        let games = await getNonFinishedGames(playerName);
+        response = {
+          res: "ok",
+          message: games
+        };
+      } catch (error) {
+
+        response = {
+          res: "ko",
+          message: 'Error from server'
+        };
+      }
+      callback(response);
+    });
+
+  });
+
+  let updatePlayersFromDb = async function () {
+    try {
+      let usernames = await mariadbConn.getUsernames();
+      authorizedPlayersNames = new Set(usernames);
+      console.log('authorizedPlayersNames update : ', authorizedPlayersNames);
+      authorizedPlayersNames.forEach(name => {
+        if (!authorizedPlayers.has(name)) {
+          console.log('New username authorized :', name);
+          authorizedPlayers.set(name, new PlayerId(name));
+        }
+      });
+      return 'ok';
+    } catch (error) {
+      console.log('Error getting usernames from DB : ', error);
+      return error.Error;
+    }
+  };
+
+  let getCurrentListAuthorizedPlayers = function () {
+    return [...authorizedPlayersNames];
+  };
+  let addPlayerDb = async function (username) {
+
+    console.log('add player in db : ' + username);
+    try {
+      let response = await mariadbConn.addPlayer(username);
+      authorizedPlayersNames.add(username);
+      authorizedPlayers.set(username, new PlayerId(username));
+      return 'OK ' + JSON.stringify(response);
+    } catch (err) {
+      return 'KO ' + err.message;
+    }
+  };
+  let removePlayerDb = async function (username) {
+
+    console.log('remove player in db : ' + username);
+    try {
+      let response = await mariadbConn.removePlayer(username);
+      authorizedPlayersNames.delete(username);
+      authorizedPlayers.delete(username);
+      return 'OK ' + JSON.stringify(response);
+    } catch (err) {
+      return 'KO ' + err.message;
+    }
+  };
+
+  let addGameDb = async function (game) {
+
+    try {
+      let response = await mariadbConn.addNewGame(game);
+      return 'OK ' + JSON.stringify(response);
+    } catch (err) {
+      return 'KO ' + err.message;
+    }
+  };
+
+  let removeGameDb = async function (method, ...args) {
+    try {
+      let response;
+      switch (method) {
+        case 'byId':
+          response = await mariadbConn.removeGameById(args[0]);
+          break;
+        case 'byPlayer1':
+          response = await mariadbConn.removeGamesByPlayer1(args[0]);
+          break;
+        case 'byPlayerAny':
+          response = await mariadbConn.removeGamesByPlayerAny(args[0]);
+          break;
+        case 'byStatus':
+          response = await mariadbConn.removeGamesByStatus(args[0]);
+          break;
+        case 'byDays':
+          response = await mariadbConn.removeGamesByDays(args[0]);
+          break;
+        case 'finishedByDays':
+          response = await mariadbConn.removeFinishedGamesByDays(args[0]);
+          break;
+
+        default:
+          return 'KO : Unknown method to remove game from DB : ' + method;
+      }
+      return 'OK ' + JSON.stringify(response);
+    } catch (err) {
+      return 'KO ' + err.message;
+    }
+  };
+
+  let getNonFinishedGames = async function (username) {
+
+    try {
+      let games = await mariadbConn.getNonFinishedGamesForPlayer(username);
+      return games;
+    } catch (err) {
+      console.log('KO : not able to get games : ' + err);
+      throw err;
+    }
+  };
+
+  return {
+    updatePlayersFromDb,
+    getCurrentListAuthorizedPlayers,
+    addPlayerDb,
+    removePlayerDb,
+    addGameDb,
+    removeGameDb,
+    getNonFinishedGames
+  };
+
+}
+
+let server = new Server();
+
+let serverToolListner = new ServerToolListner(server);
+serverToolListner.listen(1664);

+ 49 - 0
server/tools/server-tool-listener.js

@@ -0,0 +1,49 @@
+'use strict';
+
+import io from 'socket.io';
+
+export default class ServerToolListner {
+  constructor(server) {
+    this.server=server;
+  }
+
+  listen(port) {
+    let server = this.server;
+    this.serverTool = io.listen(port);
+    this.serverTool.on('connection', function (socket) {
+      console.log('tool connected');
+
+      socket.on('players', (option,callback) =>  {
+        callback(server.getCurrentListAuthorizedPlayers());
+        socket.disconnect(false);
+      });
+      socket.on('syncdb', async (option,callback) =>  {
+        let response = await server.updatePlayersFromDb();
+        callback(response);
+        socket.disconnect(false);
+      });
+
+      socket.on('add-player', async (username,callback) =>  {
+        let response = await server.addPlayerDb(...username);
+        callback(response);
+        socket.disconnect(false);
+      });
+      socket.on('remove-player', async (username,callback) =>  {
+        let response = await server.removePlayerDb(...username);
+        callback(response);
+        socket.disconnect(false);
+      });
+
+      socket.on('add-game', async (game,callback) =>  {
+        let response = await server.addGameDb(...game);
+        callback(response);
+        socket.disconnect(false);
+      });
+      socket.on('remove-game', async (options,callback) =>  {
+        let response = await server.removeGameDb(...options);
+        callback(response);
+        socket.disconnect(false);
+      });
+    });
+  }
+}

+ 82 - 0
server/tools/server-tools.js

@@ -0,0 +1,82 @@
+'use strict';
+
+// process.exit(1);
+var usage = function () {
+  var text = `
+    USAGE : npm run tools <option>
+      with <option> :
+       - players : get authorized players
+       - add-player <username> : Add a new authorized player
+       - remove-player <username> : Remove an authorized player
+       - syncdb : Force server to sync with db
+       - add-game <json>: Add new game into DB
+          '{"player1":"","player2":"","deck":"","advRules":[],"status":"","data":"{}"}'
+            deck     : faction tournament draft  (one of these)
+            advRules : popularity discard        (0 or any of these)
+            status   : CREATED ONGOING FINISHED  (one of these)
+       - remove-game <method> <filter> : Remove game(s) from DB
+          <method>          /  <filter>
+            byId                 gameId
+            byPlayer1            username
+            byPlayerAny          username
+            byStatus             CREATED ONGOING FINISHED  (one of these)
+            byDays               number of days old is last connection
+            finishedByDays       number of days old is last connection(only finished)
+       `;
+  console.log(text);
+};
+
+var args = process.argv.slice(2);
+
+if (args.length === 0) {
+  usage();
+  process.exit(0);
+}
+var command = "";
+var option = "";
+switch (args[0]) {
+  case "players":
+  case "syncdb":
+    command = args[0];
+    break;
+
+  case "add-player":
+  case "remove-player":
+  case "add-game":
+  case "remove-game":
+
+    if (args[0] === "remove-game" && args.length < 3) {
+      usage();
+      process.exit(0);
+    }
+    if (args[1] && args[1] !== "") {
+      command = args[0];
+      if (args[0] === "add-game") {
+        try {
+          option = [JSON.parse(args[1])];
+        } catch (error) {
+          console.log(error);
+          process.exit(0);
+        }
+      } else {
+        args.shift();
+        option = args;
+      }
+    } else {
+      console.log('error ; specify a username');
+      usage();
+    }
+    break;
+
+  default:
+    usage();
+    break;
+}
+
+if (command !== "") {
+  console.log('Connecting to server...');
+  var socket = require('socket.io-client')("http://localhost:1664");
+  socket.emit(command, option,function (response) {
+    console.log('Done, response from server : ', response);
+  });
+}

+ 0 - 3
settings.json

@@ -1,3 +0,0 @@
-{
-    "git.ignoreLimitWarning": true
-}

+ 180 - 0
src/assets/html/css/style.css

@@ -0,0 +1,180 @@
+#login, #online-room {
+  background: #C7CC2D;
+  border: 1px solid #972620;
+  border-radius: 6px;
+  height: 300px;
+  margin-top: 20px;
+  margin-left: auto;
+  width: 300px;
+}
+#online-room {
+  position: relative;
+  width: 500px;
+  margin-left: -150px;
+}
+
+input[type="password"], input[type="text"] {
+  background: linear-gradient(top, #C7CC2D, #e6e6e6);
+  border: 1px solid #C7CC2D;
+  border-radius: 4px;
+  box-shadow: 0 1px #C7CC2D;
+  box-sizing: border-box;
+  color: #567199;
+  height: 39px;
+  margin: 24px 0 0 29px;
+  padding-left: 37px;
+  transition: box-shadow 0.3s;
+  width: 240px;
+}
+input[type="password"]:focus, input[type="text"]:focus {
+  box-shadow: 0 0 4px 1px rgba(55, 166, 155, 0.3);
+  outline: 0;
+}
+.show-password {
+  display: block;
+  height: 16px;
+  margin: 26px 0 0 28px;
+  width: 87px;
+}
+input[type="checkbox"] {
+  cursor: pointer;
+  height: 16px;
+  opacity: 0;
+  position: relative;
+  width: 64px;
+}
+input[type="checkbox"]:checked {
+  left: 29px;
+  width: 58px;
+}
+.toggle {
+  display: block;
+  height: 16px;
+  margin-top: -20px;
+  width: 87px;
+  z-index: -1;
+}
+input[type="checkbox"]:checked + .toggle { background-position: 0 -16px }
+
+input[type="button"] {
+  width:240px;
+  height:35px;
+  display:block;
+  font-family:Arial, "Helvetica", sans-serif;
+  font-size:16px;
+  font-weight:bold;
+  color:#F8E15E;
+  text-decoration:none;
+  text-transform:uppercase;
+  text-align:center;
+  text-shadow:1px 1px 0px #567199;
+  padding-top:6px;
+  margin: 23px 0 0 29px;
+  position:relative;
+  cursor:pointer;
+  border: none;
+  background-color: #567199;
+  background-image: linear-gradient(top,#567199,rgba(252, 4, 4, 0.067));
+  border-top-left-radius: 5px;
+  border-top-right-radius: 5px;
+  border-bottom-right-radius: 5px;
+  border-bottom-left-radius:5px;
+  box-shadow: inset 0px 1px 0px #567199, 0px 5px 0px 0px #324F70, 0px 10px 5px #C7CC2D;
+}
+
+input[type="button"]:hover:enabled, input[type="text"]:hover:enabled {
+  transform:scale(1.1);
+  }
+input[type="button"]:disabled {
+  width:240px;
+  height:35px;
+  display:block;
+  font-family:Arial, "Helvetica", sans-serif;
+  font-size:16px;
+  font-weight:bold;
+  color:#F8E15E;
+  text-decoration:none;
+  text-transform:uppercase;
+  text-align:center;
+  text-shadow:1px 1px 0px #909998;
+  padding-top:6px;
+  margin: 23px 0 0 29px;
+  position:relative;
+  cursor:pointer;
+  border: none;
+  background-color: #7e7e7e;
+  background-image: linear-gradient(top,#909998,#82a09c);
+  border-top-left-radius: 5px;
+  border-top-right-radius: 5px;
+  border-bottom-right-radius: 5px;
+  border-bottom-left-radius:5px;
+  box-shadow: inset 0px 1px 0px #7e7e7e, 0px 5px 0px 0px #808586, 0px 7px 5px #C7CC2D;
+}
+.shadow {
+  background: #000;
+  border-radius: 12px 12px 4px 4px;
+  box-shadow: 0 0 20px 10px #000;
+  height: 12px;
+  margin: 30px auto;
+  opacity: 0.2;
+  width: 270px;
+}
+
+input[type="button"]:enabled:active {
+  top:3px;
+  box-shadow: inset 0px 1px 0px #567199, 0px 2px 0px 0px #324F70, 0px 5px 3px #C7CC2D;
+}
+.connection {
+  font-family:Arial, "Helvetica", sans-serif;
+  font-size:14px;
+  color: #972620;
+  text-align:center;
+}
+
+#online-room-buttons {
+  position: absolute;
+  top:50px;
+  left:205px;
+}
+
+#online-games {
+  background: #567199;
+  border: 1px solid #567199;
+  border-radius: 3px;
+  margin: 20px 20px;
+  height: 250px;
+  width: 185px;
+  overflow: hidden;
+  font-family:Arial, "Helvetica", sans-serif;
+  font-size:16px;
+  font-weight:bold;
+  color:#F8E15E;
+  text-decoration:none;
+  text-transform:uppercase;
+  text-align:center;
+  text-shadow:1px 1px 0px #567199;
+  vertical-align: middle;
+  padding-top: 8px;
+}
+#list-games {
+  padding: 0;
+  list-style:none;
+}
+
+#list-games li {
+  font-family:Arial, "Helvetica", sans-serif;
+  font-size:14px;
+  margin: 7px 10px 0px 10px;
+}
+
+#list-games span {
+  width:155px;
+  height:35px;
+  background-color:#333;
+  padding-left:10px;
+  text-decoration:none;
+  color:#bfe1f1;
+  display: table-cell;
+  vertical-align: middle;
+}
+

+ 404 - 0
src/assets/html/main-menu.html

@@ -0,0 +1,404 @@
+<style type="text/css">
+.main-div {
+  background: #03c11b;
+  border: 1px solid #013007;
+  border-radius: 6px;
+  height: 300px;
+  margin-top: 0px;
+  margin-left: auto;
+  width: 300px;
+}
+#online-room {
+  position: relative;
+  width: 500px;
+  margin-left: -150px;
+}
+
+input[type="password"], input[type="text"] {
+  background: linear-gradient(top, #03c11b, #e6e6e6);
+  border: 1px solid #03c11b;
+  border-radius: 4px;
+  box-shadow: 0 1px #03c11b;
+  box-sizing: border-box;
+  color: #567199;
+  height: 39px;
+  margin: 24px 0 0 29px;
+  padding-left: 37px;
+  transition: box-shadow 0.3s;
+  width: 240px;
+}
+input[type="password"]:focus, input[type="text"]:focus {
+  box-shadow: 0 0 4px 1px rgba(55, 166, 155, 0.3);
+  outline: 0;
+}
+.show-password {
+  display: block;
+  height: 16px;
+  margin: 26px 0 0 28px;
+  width: 87px;
+}
+input[type="checkbox"] {
+  cursor: pointer;
+  height: 16px;
+  width: 64px;
+}
+input[type="checkbox"]:checked {
+  left: 29px;
+  width: 58px;
+}
+.toggle {
+  display: block;
+  height: 16px;
+  margin-top: 20px;
+  width: 87px;
+  z-index: -1;
+}
+input[type="checkbox"]:checked + .toggle { background-position: 0 -16px }
+
+input[type="button"] {
+  width:240px;
+  height:35px;
+  display:block;
+  font-family:Arial, "Helvetica", sans-serif;
+  font-size:16px;
+  font-weight:bold;
+  color:#F8E15E;
+  text-decoration:none;
+  text-transform:uppercase;
+  text-align:center;
+  text-shadow:1px 1px 0px #567199;
+  padding-top:6px;
+  margin: 23px 0 0 29px;
+  position:relative;
+  cursor:pointer;
+  border: none;
+  background-color: #567199;
+  background-image: linear-gradient(top,#567199,rgba(252, 4, 4, 0.067));
+  border-top-left-radius: 5px;
+  border-top-right-radius: 5px;
+  border-bottom-right-radius: 5px;
+  border-bottom-left-radius:5px;
+  box-shadow: inset 0px 1px 0px #567199, 0px 5px 0px 0px #324F70, 0px 10px 5px #03c11b;
+}
+
+input[type="button"]:hover:enabled, input[type="text"]:hover:enabled {
+  transform:scale(1.1);
+  }
+input[type="button"]:disabled {
+  width:240px;
+  height:35px;
+  display:block;
+  font-family:Arial, "Helvetica", sans-serif;
+  font-size:16px;
+  font-weight:bold;
+  color:#F8E15E;
+  text-decoration:none;
+  text-transform:uppercase;
+  text-align:center;
+  text-shadow:1px 1px 0px #909998;
+  padding-top:6px;
+  margin: 23px 0 0 29px;
+  position:relative;
+  cursor:pointer;
+  border: none;
+  background-color: #7e7e7e;
+  background-image: linear-gradient(top,#909998,#82a09c);
+  border-top-left-radius: 5px;
+  border-top-right-radius: 5px;
+  border-bottom-right-radius: 5px;
+  border-bottom-left-radius:5px;
+  box-shadow: inset 0px 1px 0px #7e7e7e, 0px 5px 0px 0px #808586, 0px 7px 5px #03c11b;
+}
+.shadow {
+  background: #000;
+  border-radius: 12px 12px 4px 4px;
+  box-shadow: 0 0 20px 10px #000;
+  height: 12px;
+  margin: 30px auto;
+  opacity: 0.2;
+  width: 270px;
+}
+
+input[type="button"]:enabled:active {
+  top:3px;
+  box-shadow: inset 0px 1px 0px #567199, 0px 2px 0px 0px #324F70, 0px 5px 3px #03c11b;
+}
+.connection {
+  font-family:Arial, "Helvetica", sans-serif;
+  font-size:14px;
+  color: #660c07;
+  text-align:center;
+}
+
+#online-room-buttons {
+  position: absolute;
+  top:20px;
+  left:205px;
+}
+#online-room-buttons p {
+margin-left: 20px;
+}
+#online-room-buttons div {
+  margin-top: 50px;
+}
+
+#online-games {
+  background: #567199;
+  border: 1px solid #567199;
+  border-radius: 3px;
+  margin: 20px 20px;
+  height: 250px;
+  width: 185px;
+  overflow: hidden;
+  font-family:Arial, "Helvetica", sans-serif;
+  font-size:16px;
+  font-weight:bold;
+  color:#F8E15E;
+  text-decoration:none;
+  text-transform:uppercase;
+  text-align:center;
+  text-shadow:1px 1px 0px #567199;
+  vertical-align: middle;
+  padding-top: 8px;
+}
+#list-games {
+  display: none;
+  padding: 0;
+  list-style:none;
+  margin-top: 1px;
+}
+
+#list-games li {
+  margin: 7px 5px 0px 5px;
+
+  width:170px;
+  height:35px;
+  background-color:#191817;
+  padding-left:5px;
+  font-weight:normal;
+  text-transform: none;
+  text-shadow:none;
+  text-align: left;
+
+}
+
+.el-selected {
+border: 2px solid #f10505;
+  margin-left: 3px;
+}
+
+#list-games li div {
+  margin-bottom: -3px;
+}
+#list-games li span {
+  -webkit-touch-callout: none;
+  -webkit-user-select: none;
+  -khtml-user-select: none;
+  -moz-user-select: none;
+  -ms-user-select: none;
+  user-select: none;
+}
+.game-entry-title {
+  font-family:Arial, "Helvetica", sans-serif;
+  font-size:14px;
+  color:#F8E15E;
+  padding-left: 10px;
+}
+.game-entry-desc {
+  text-decoration:none;
+  font-size:11px;
+  color:#F8E15E;
+}
+#loader-online-games {
+  display: block;
+  margin-top: 50px;
+  margin-left: 62px;
+  border: 8px solid #f3f3f3;
+  border-radius: 50%;
+  border-top: 8px solid #F8E15E;
+  width: 40px;
+  height: 40px;
+  -webkit-animation: spin 1.5s linear infinite; /* Safari */
+  animation: spin 1.5s linear infinite;
+}
+
+/* Safari */
+@-webkit-keyframes spin {
+  0% { -webkit-transform: rotate(0deg); }
+  100% { -webkit-transform: rotate(360deg); }
+}
+
+@keyframes spin {
+  0% { transform: rotate(0deg); }
+  100% { transform: rotate(360deg); }
+}
+
+#game-creation {
+
+  color: #567199;
+  font-family:Arial, "Helvetica", sans-serif;
+  font-size:16px;
+  font-weight:bold;
+  text-align: center;
+  padding-top: 15px;
+  height: 280px;
+}
+
+#deck-mode-select {
+  margin-top: 10px;
+  margin-bottom: 10px;
+}
+.checkbox-div {
+  text-align: left;
+  margin-top: 5px;
+  margin-bottom: 5px;
+}
+/* The container */
+.container {
+  display: block;
+  position: relative;
+  padding-left: 55px;
+  padding-top: 1px;
+  margin-bottom: 10px;
+  margin-left: 40px;
+  cursor: pointer;
+  font-size: 14px;
+  -webkit-user-select: none;
+  -moz-user-select: none;
+  -ms-user-select: none;
+  user-select: none;
+}
+
+/* Hide the browser's default checkbox */
+.container input {
+  position: absolute;
+  opacity: 0;
+  cursor: pointer;
+  height: 0;
+  width: 0;
+}
+
+/* Create a custom checkbox */
+.checkmark {
+  position: absolute;
+  top: 0;
+  left: 15px;
+  right: 15px;
+  height: 20px;
+  width: 20px;
+  background-color: #eee;
+}
+
+/* On mouse-over, add a grey background color */
+.container:hover input ~ .checkmark {
+  background-color: #ccc;
+}
+
+/* When the checkbox is checked, add a blue background */
+.container input:checked ~ .checkmark {
+  background-color: #567199;
+}
+
+/* Create the checkmark/indicator (hidden when not checked) */
+.checkmark:after {
+  content: "";
+  position: absolute;
+  display: none;
+}
+
+/* Show the checkmark when checked */
+.container input:checked ~ .checkmark:after {
+  display: block;
+}
+
+/* Style the checkmark/indicator */
+.container .checkmark:after {
+  left: 6px;
+  top: 2px;
+  width: 5px;
+  height: 10px;
+  border: solid white;
+  border-width: 0 3px 3px 0;
+  -webkit-transform: rotate(45deg);
+  -ms-transform: rotate(45deg);
+  transform: rotate(45deg);
+}
+</style>
+<!DOCTYPE html>
+<html>
+
+<head>
+  <!-- <link rel="stylesheet" type="text/css" href="assets/html/css/style.css"> -->
+  <!-- <link rel="stylesheet" type="text/css" href="css/style.css"> -->
+</head>
+
+<body class="body">
+  <div id="login" class="main-div" style="display:none">
+    <input type="text" placeholder="Username" id="username" name="username" autocomplete="off">
+    <input type="button" value="Connect" name="loginButton">
+    <p class="connection" id="connectionStatus">Not Connected</p>
+    <input type="button" value="Online Game" name="onlineGame" disabled>
+    <input type="button" value="Local game" name="localGame">
+  </div>
+
+  <div id="online-room" class="main-div" style="display:none">
+    <div id="online-games">
+      Existing Games
+      <hr>
+      <div id="loader-online-games"></div>
+      <ul id="list-games">
+        <li>
+          <span class="game-entry-title">Resume jojo VS lily</span>
+          <div></div>
+          <span class="game-entry-desc">Factions + no adv. rules</span>
+        </li>
+        <li>
+          <span class="game-entry-title">mart waiting...</span>
+          <div></div>
+          <span class="game-entry-desc">Tournament + popularity + discard</span>
+        </li>
+      </ul>
+    </div>
+
+    <div id="online-room-buttons">
+      <p class="connection" id="connectionStatusOnline"></p>
+      <div>
+        <input type="button" value="Create new game" name="createOnlineGame">
+        <input type="button" value="Join / Resume game" name="joinOnlineGame" disabled>
+        <input type="button" value="Back to Menu" name="backToMain">
+      </div>
+    </div>
+  </div>
+
+  <div id="game-creation" class="main-div" style="display:none">
+    Select how you will build your deck
+    <div id="deck-mode-select">
+      <select>
+        <option value="0">Select Deck mode</option>
+        <option value="1">Faction</option>
+        <option value="2">Draft</option>
+        <option value="3">Tournament</option>
+      </select>
+    </div>
+    <hr>
+    Select advandced rules
+    <div class="checkbox-div">
+
+      <label class="container">Popularity
+        <input type="checkbox" id="popularity">
+        <span class="checkmark"></span>
+      </label>
+      <label class="container">Discard for an action
+        <input type="checkbox" id="discardForAction">
+        <span class="checkmark"></span>
+      </label>
+    </div>
+    <hr>
+    <input type="button" value="CREATE" name="validGameCreation" disabled>
+    <input type="button" value="Back" name="backToPrev">
+
+  </div>
+
+</body>
+
+</html>

BIN
src/assets/logo.png


+ 73 - 14
src/common/socket-service.js

@@ -1,6 +1,6 @@
 'use strict';
 import io from 'socket.io-client';
-
+// import promiseTimeout from './utils/promise-timeout';
 /*
   Messages :
     - disconnect
@@ -9,27 +9,86 @@ import io from 'socket.io-client';
     - reconnect_failed
     -
 */
-const SERVER_URL = process.env.SERVER_URL || 'http://localhost';
-const SERVER_PORT = process.env.SERVER_PORT || 4000;
+const SERVER_URL = 'http://' + process.env.SERVER_HOST;
+const SERVER_PORT = process.env.SERVER_PORT;
+
+
 
 export default class SocketService {
-  constructor(namespace) {
+  constructor() {
+    this.lostConnectionListeners = new Set();
+  }
+
+  addlostConnectionListener(listener) {
+    this.lostConnectionListeners.add(listener);
+  }
+
 
-    this.ioClient = io.connect(SERVER_URL + ":" + SERVER_PORT + '/');
+  removelostConnectionListener(listener) {
+    this.lostConnectionListeners.delete(listener);
   }
 
-  connect(serverUrl, serverPort) {
-    this.disconnected=false;
-    this.ioClient = io.connect(serverUrl + ":" + serverPort);
+  connect(name) {
+    let promise = new Promise((resolve, reject) => {
+      console.log('Connecting socket service to : ' + SERVER_URL + ':' + SERVER_PORT);
+      this.ioClient = io(SERVER_URL+':'+SERVER_PORT,
+        { reconnectionAttempts: 2 });
 
-    console.log("is connected : " + this.ioClient.connected);
-    this.ioClient.on('disconnect', () => {
-      console.log("Connection with server lost");
+      this.ioClient.on('disconnect', (reason) => {
+        if (reason !== 'io client disconnect') {
+          console.log("Connection with server lost unexpectidly : " + reason);
+          //this.ioClient.close();
+        }
+      });
+
+      this.ioClient.on('connect', () => {
+        console.log("Connected to server");
+          this.ioClient.emit('auth', name, function (response) {
+            if (response.res === "ok") {
+              resolve(response.message);
+            } else {
+              reject(response.message);
+            }
+          });
+      });
+
+      this.ioClient.on('connect_error', () => {
+        console.log("connect_error to server");
+      });
+
+      this.ioClient.on('reconnect_failed', () => {
+        console.log("reconnect_failed to server");
+        reject('Cannot reach server');
+      });
 
     });
+    return promise;
+  }
+
+  checkConnection(playername) {
+    if (this.ioClient.connected === false) {
+      return this.connect(playername);
+    } else {
+      return Promise.resolve('Still connected');
+    }
+  }
+
+  disconnect() {
+    console.log('Manual client disconnect');
+    this.ioClient.close();
   }
-  auth(name) {
-    console.log("Authenticate to server player name : " + name);
-    this.ioClient.emit('auth', name);
+  getGamesList(playername) {
+    return this.checkConnection(playername).then( () => {
+      return new Promise( (resolve, reject) => {
+        this.ioClient.emit('games-list', playername, function (response) {
+          if (response.res === "ok") {
+            resolve(response.message);
+          } else {
+            reject(response.message);
+          }
+        });
+      });
+    },
+    (error) => Promise.reject(error));
   }
 }

+ 0 - 16
src/game/control/behaviors/deck-building-steps.js

@@ -1,16 +0,0 @@
-'use strict';
-
-
-export const DeckBuildingSteps = self => ({
-  selectFactionDeck: (renderer,heroFactory) => {
-    self.player.faction = renderer.getInput(self.player.name + ' to choose faction');
-    self.player.setHeroesDeck(heroFactory.getFactionRandom(self.player.faction));
-  },
-  selectDraftHeroes: (heroesDraftBurst) => {
-    console.log('Choose 2 heroes among : ', heroesDraftBurst);
-  },
-  selectTournamentDeck: (allHeroes) => {
-    console.log('Choose 12 heroes among : ', allHeroes);
-  }
-
-});

+ 0 - 10
src/game/control/player-controller.js

@@ -1,10 +0,0 @@
-'use-strict';
-import {DeckBuildingSteps} from './behaviors/deck-building-steps';
-
-export const PlayerControllerLocal = function(player) {
-  const self = {
-    player
-  };
-
-  return Object.assign(self, DeckBuildingSteps(self));
-};

+ 4 - 3
src/game/views/faction-deck-building-scene.js

@@ -21,10 +21,11 @@ export default class FactionDeckBuildingScene extends DeckBuildingScene {
 
     setTimeout(() => {
       let factionOptions = Object.values(Faction).filter(faction => faction !== Faction.NONE);
-      let pBlueFaction = Utils.promptSelectAmongOptions("Select Player Blue Faction", factionOptions);
-
+      //let pBlueFaction = Utils.promptSelectAmongOptions("Select Player Blue Faction", factionOptions);
+      let pBlueFaction = "meca";
       factionOptions = factionOptions.filter(faction => faction !== pBlueFaction);
-      let pRedFaction = Utils.promptSelectAmongOptions("Select Player Red Faction", factionOptions);
+      //let pRedFaction = Utils.promptSelectAmongOptions("Select Player Red Faction", factionOptions);
+      let pRedFaction = "orcs";
       this.gameEventListener.onFactionsSelected(pBlueFaction, pRedFaction );
     }, 100);
   }

+ 2 - 3
src/index.html

@@ -34,14 +34,13 @@
   <meta name="msapplication-tap-highlight" content="no">
   <meta name="viewport" content="initial-scale=1, width=device-width, viewport-fit=cover">
   <!-- <link rel="stylesheet" type="text/css" href="css/index.css"> -->
-  <title>Hello World</title>
+  <title>Twelve Heroes</title>
 </head>
 
 <body>
-  <% if (process.env.CORDOVA) { %>
+  <% if (process.env.CORDOVA === "true") { %>
 
   <div class="app">
-    <h1>Twelve Heroes</h1>
     <div id="deviceready" class="blink">
       <p class="event listening"></p>
       <p class="event received"></p>

+ 21 - 25
src/main.js

@@ -9,17 +9,29 @@ function startGame() {
   console.log('start Game');
 
   let phaserConfig = {
-    type: Phaser.CANVAS,
-    width: 1200,
-    height: 500,
-    scene: [],
-    backgroundColor: 'rgba(34,139,34 ,1 )'
+    type: Phaser.AUTO,
+    pixelArt: true,
+    scale: {
+      mode: Phaser.Scale.RESIZE,
+      autoCenter: Phaser.Scale.CENTER_BOTH,
+      width: window.innerWidth,
+      height: window.innerHeight
+    },
+    physics: {
+      default: 'arcade',
+      arcade: {
+        debug: true,
+        gravity: { y: 250 },
+      }
+    },
+    parent: 'phaser-parent',
+    dom: {
+      createContainer: true
+    }
   };
   let phaserEngine = new Phaser.Game(phaserConfig);
   let menuController = new MenuController(phaserEngine);
-
   menuController.displayMainMenu();
-
 }
 
 let app = {
@@ -29,31 +41,15 @@ let app = {
     document.addEventListener('deviceready', this.onDeviceReady.bind(this), false);
   },
 
-  // deviceready Event Handler
-  //
-  // Bind any cordova events here. Common events are:
-  // 'pause', 'resume', etc.
   onDeviceReady: function () {
-    this.receivedEvent('deviceready');
     startGame();
   },
 
-  // Update DOM on a Received Event
-  receivedEvent: function (id) {
-    var parentElement = document.getElementById(id);
-    var listeningElement = parentElement.querySelector('.listening');
-    var receivedElement = parentElement.querySelector('.received');
-
-    listeningElement.setAttribute('style', 'display:none;');
-    receivedElement.setAttribute('style', 'display:block;');
-
-    console.log('Received Event: ' + id);
-  }
 };
 
-console.log('cordova  :', process.env.CORDOVA );
+console.log('cordova env ? :', process.env.CORDOVA);
 
-if (process.env.CORDOVA) {
+if (process.env.CORDOVA && process.env.CORDOVA === true) {
 
   app.initialize();
 } else {

+ 18 - 6
src/menu/control/menu-controller.js

@@ -10,13 +10,10 @@ export default class MenuController {
 
   constructor(phaserEngine) {
     this.phaserEngine = phaserEngine;
-    console.log("In constructor MenuController " + this.phaserEngine);
 
-    this.mainMenuScene = new MainMenuScene(this.menuEventListener());
+    this.socketService = new SocketService();
 
-    //this.socketService = new SocketService();
-    //this.socketService.connect('http://localhost', 4000);
-    //this.socketService.auth('Jojo');
+    this.mainMenuScene = new MainMenuScene(this.menuEventListener());
   }
 
   displayMainMenu() {
@@ -25,9 +22,21 @@ export default class MenuController {
     this.phaserEngine.scene.start(PhaserScene.MAIN_MENU);
   }
 
+
+  tryConnect(username) {
+    return this.socketService.connect(username);
+  }
+
+  onRequestDisconnection() {
+    this.socketService.disconnect();
+  }
+
   menuEventListener() {
     return {
-      onNewPnpGame: this.onNewPnpGame.bind(this)
+      onNewPnpGame: this.onNewPnpGame.bind(this),
+      onOnlineGamesListRequested: this.onOnlineGamesListRequested.bind(this),
+      onTryConnect: this.tryConnect.bind(this),
+      onRequestDisconnection: this.onRequestDisconnection.bind(this),
     };
   }
 
@@ -38,4 +47,7 @@ export default class MenuController {
       gameControllerPnp.displayDeckBuilding();
   }
 
+  onOnlineGamesListRequested(playername) {
+    return this.socketService.getGamesList(playername);
+  }
 }

+ 7 - 0
src/menu/control/server-login.js

@@ -0,0 +1,7 @@
+'use strict';
+
+export default class ServerLogin {
+  constructor() {
+
+  }
+}

+ 99 - 20
src/menu/views/main-menu-scene.js

@@ -1,8 +1,13 @@
 'use strict';
-import {GameDeckMode} from '../../common/utils/const/game-deck-mode-enum';
 import { PhaserScene } from '../../common/utils/const/phaser-scene-enum';
 import Phaser from 'phaser';
-import * as Utils from '../../common/utils/prompt-renderer';
+
+import LoginDivPage from './menu-pages/login-div-page';
+import OnlineRoomDivPage from './menu-pages/online-room-div-page';
+import GameCreationDivPage from './menu-pages/game-creation-div-page';
+
+import MenuPages from '../../assets/html/main-menu.html';
+import Cover from '../../assets/twelveHeroes_cover.png';
 
 export default class MainMenuScene extends Phaser.Scene {
 
@@ -10,20 +15,41 @@ export default class MainMenuScene extends Phaser.Scene {
     super({ key: PhaserScene.MAIN_MENU, active: false });
     this.menuEventListener = menuEventListener;
 
+    this.username = '';
+    this.previousPages = new Array();
   }
 
   preload() {
-    console.log('Preload');
-    this.load.image('game-cover', '../../assets/twelveHeroes_cover.png');
+    this.load.image('game-cover', Cover);
   }
 
+
+  // create is call automatically by Phaser engine
   create() {
-    console.log('create');
-    let logo = this.add.image(0,0,'game-cover');
-    logo.setOrigin(0,0);
+    let background = this.add.image(0, 0, 'game-cover');
+    background.setOrigin(0, 0);
+
+    // Add main-menu HTML
+    let element = this.add.dom(250, 0).createFromHTML(MenuPages);
+    element.setPerspective(800);
+
+    // Menu div pages
+    this.loginDivPage = new LoginDivPage(element,this.loginPageListener());
+    this.onlineRoomDivPage = new OnlineRoomDivPage(element, this.onlineRoomPageListener());
+    this.gameCreationDivPage = new GameCreationDivPage(element, this.gameCreationPageListener());
+
+
+    setTimeout(() => {
+      this.loginDivPage.show();
+      this.tweens.add({
+        targets: element,
+        y: 190,
+        duration: 2300,
+        ease: 'Power3'
 
+      });
 
-    //this.add.dom
+     }, 700);
 
 
 
@@ -32,24 +58,77 @@ export default class MainMenuScene extends Phaser.Scene {
     // Pass to them the event listener
     // On local player room, user can enter player names, selected color, game deck mode & rules
 
-    // FOR TESTING
-    this.fakeNewPnpGameSelected();
   }
 
   update() {
+  }
 
+
+  // Listener for login page events
+  loginPageListener() {
+    return {
+      onRequestConnection: this.onRequestConnection.bind(this),
+      onRequestDisconnection: this.onRequestDisconnection.bind(this),
+      onGoOnlineRoom: this.onGoOnlineRoom.bind(this)
+    };
   }
 
-  fakeNewPnpGameSelected() {
-    setTimeout(() => {
-      let pBlueName = prompt("Player blue name : ");
-      let pRedName = prompt("Player red name : ");
+  // Listener for online room page events
+  onlineRoomPageListener() {
+    return {
+      onRequestOnlineGamesList: this.onRequestOnlineGamesList.bind(this),
+      onGoGameCreation: this.onGoGameCreation.bind(this),
+      onGoPreviousPage: this.onGoPreviousPage.bind(this)
+    };
+  }
+
+  // Listener for game creation page events
+  gameCreationPageListener() {
+    return {
+      onGoPreviousPage: this.onGoPreviousPage.bind(this)
+    };
+  }
 
-      let gameDeckModeOptions = Object.values(GameDeckMode);
-      let gameDeckMode = Utils.promptSelectAmongOptions("Select Deck Mode", gameDeckModeOptions);
-      let advancedRules = [];
-      console.log("Calling listener");
-      this.menuEventListener.onNewPnpGame(pBlueName, pRedName, gameDeckMode, advancedRules);
-    }, 1000);
+  // Callbacks implementation
+  onGoPreviousPage(fromPage) {
+    fromPage.hide();
+    this.previousPages.pop().show();
   }
+
+  // Login page specific
+  onGoOnlineRoom() {
+
+    this.loginDivPage.hide();
+    this.previousPages.push(this.loginDivPage);
+    this.onlineRoomDivPage.setConnectionStatus(this.loginDivPage.getConnectionStatus());
+    this.onlineRoomDivPage.show();
+  }
+  onRequestConnection(username) {
+    this.username=username;
+    return this.menuEventListener.onTryConnect(username);
+  }
+  onRequestDisconnection() {
+    this.menuEventListener.onRequestDisconnection();
+  }
+
+  // Online room specific
+  onRequestOnlineGamesList() {
+    return this.menuEventListener.onOnlineGamesListRequested(this.username);
+  }
+
+  onGoGameCreation() {
+    this.onlineRoomDivPage.hide();
+    this.previousPages.push(this.onlineRoomDivPage);
+    this.gameCreationDivPage.show();
+  }
+
+  // Game cration specific
+  onGameCreated() {
+
+    // let gameDeckMode = "factions";
+    // let advancedRules = [];
+    // console.log("Calling listener");
+    // this.menuEventListener.onNewPnpGame(pBlueName, pRedName, gameDeckMode, advancedRules)
+  }
+
 }

+ 32 - 0
src/menu/views/menu-pages/div-page-common.js

@@ -0,0 +1,32 @@
+
+export const canShow = (page) => ({
+  show() {
+    page.div.style.display = 'block';
+    if (typeof page.onShow === 'function') {
+      page.onShow();
+    } else {
+      console.log('Warning : class ' + page.className + ' needs to implement onShow()');
+    }
+  }
+});
+
+export const canHide = (page) => ({
+  hide() {
+    page.div.style.display = 'none';
+    if (typeof page.onHide === 'function') {
+      page.onHide();
+    } else {
+      console.log('Warning : class ' + page.className + ' needs to implement onHide()');
+    }
+  }
+});
+
+export const hasConnectionState = (page) => ({
+  getConnectionStatus() {
+    return page.connectionStatus.innerText;
+  },
+
+  setConnectionStatus(connectionStatus) {
+    page.connectionStatus.innerText=connectionStatus;
+  }
+});

+ 51 - 0
src/menu/views/menu-pages/game-creation-div-page.js

@@ -0,0 +1,51 @@
+import * as DivCommon from './div-page-common';
+
+export default function GameCreationDivPage(element, listener) {
+
+  const id='game-creation';
+  const className=GameCreationDivPage.name;
+
+  let div = element.getChildByID(id);
+  let connectButton = element.getChildByName('loginButton');
+  let username = element.getChildByName('username');
+  let connectionStatus = element.getChildByID('connectionStatus');
+  let onlineGame = element.getChildByName('onlineGame');
+
+  let eventListener = function(event) {
+    let eventName = event.target.name;
+    switch (eventName) {
+        case "backToPrev":
+          listener.onGoPreviousPage(gameCreationDivPage);
+          break;
+
+      default:
+        break;
+    }
+  };
+
+  div.addEventListener('click',eventListener);
+
+  let onShow = function() {
+
+  };
+
+  let onHide = function() {
+
+  };
+
+  let gameCreationDivPage = {
+    className,
+    div,
+    onShow,
+    onHide
+  };
+  return Object.assign(
+    gameCreationDivPage,
+    DivCommon.canShow(gameCreationDivPage),
+    DivCommon.canHide(gameCreationDivPage)
+  );
+
+}
+
+
+

+ 106 - 0
src/menu/views/menu-pages/login-div-page.js

@@ -0,0 +1,106 @@
+import * as DivCommon from './div-page-common';
+
+export default function LoginDivPage(element, listener) {
+
+  const id = 'login';
+  const className = LoginDivPage.name;
+
+  let div = element.getChildByID(id);
+  let connectButton = element.getChildByName('loginButton');
+  let username = element.getChildByName('username');
+  let connectionStatus = element.getChildByID('connectionStatus');
+  let onlineGame = element.getChildByName('onlineGame');
+
+
+  username.addEventListener("keyup", event => {
+    if (connectButton.value === 'Connect') {
+      if (event.key !== "Enter") return;
+      connectButton.click();
+      event.preventDefault();
+    }
+  });
+
+  let eventListener = function (event) {
+    let eventName = event.target.name;
+    switch (eventName) {
+      case "loginButton":
+        if (connectButton.value === 'Connect') {
+          if (username.value !== '') {
+            connectButton.disabled = true;
+            connectionStatus.innerText = 'Connecting...';
+            username.disabled = true;
+            listener.onRequestConnection(username.value).then(
+              () => {
+                connectionStatus.innerText = 'Connected as ' + username.value;
+                this.username = username.value;
+                onlineGame.disabled = false;
+                connectButton.value = "Disconnect";
+                connectButton.disabled = false;
+              },
+              (error) => {
+                console.log(`Could not connect as ${username.value} : ${error}`);
+                connectButton.disabled = false;
+                connectionStatus.innerText = error;
+                username.disabled = false;
+              }
+            );
+          } else {
+            connectionStatus.innerText = 'Not Connected : Enter Username';
+          }
+        } else {
+          connectButton.disabled = true;
+          connectionStatus.innerText = `Disconnecting ${this.username}...`;
+          onlineGame.disabled = true;
+          listener.onRequestDisconnection();
+          connectionStatus.innerText = 'Not Connected';
+          connectButton.value = "Connect";
+          connectButton.disabled = false;
+          username.value = '';
+          this.username = username.value;
+          username.disabled = false;
+        }
+        break;
+      case "onlineGame":
+        listener.onGoOnlineRoom();
+        break;
+      case "localGame":
+        alert("Feature not yet implemented!");
+        break;
+      default:
+        break;
+    }
+  };
+
+  div.addEventListener('click', eventListener);
+
+  let onShow = function () {
+
+    connectionStatus.focus();
+  };
+
+  let onHide = function () {
+
+  };
+
+  let loginDivPage = {
+    className,
+    div,
+    connectButton,
+    username,
+    connectionStatus,
+    onlineGame,
+    onShow,
+    onHide
+  };
+
+  return Object.assign(
+    loginDivPage,
+    DivCommon.canShow(loginDivPage),
+    DivCommon.canHide(loginDivPage),
+    DivCommon.hasConnectionState(loginDivPage)
+  );
+
+}
+
+
+

+ 112 - 0
src/menu/views/menu-pages/online-room-div-page.js

@@ -0,0 +1,112 @@
+import * as DivCommon from './div-page-common';
+
+export default function OnlineRoomDivPage(element, listener) {
+
+  const id='online-room';
+  const className=OnlineRoomDivPage.name;
+  let div = element.getChildByID(id);
+
+  let createOnlineGameButton = element.getChildByName('createOnlineGame');
+  let joinOnlineGameButton = element.getChildByName('joinOnlineGame');
+  let backToMainButton = element.getChildByName('backToMain');
+  let listOnlineGames = element.getChildByID('list-games');
+  let connectionStatus = element.getChildByID('connectionStatusOnline');
+  let loaderOnlineGames = element.getChildByID('loader-online-games');
+
+  let eventListener = function(event) {
+    let eventName = event.target.name;
+    switch (eventName) {
+      case "backToMain":
+        console.log('in online room div page, backToMain clicked');
+        listener.onGoPreviousPage(onlineRoomDivPage);
+        break;
+      case "createOnlineGame":
+        listener.onGoGameCreation();
+        break;
+
+      default:
+        break;
+    }
+
+  };
+
+  div.addEventListener('click',eventListener);
+
+  let onShow = function() {
+    listener.onRequestOnlineGamesList()
+      .then( (games) => {
+        console.log('received games : ', games);
+
+        while(listOnlineGames.firstChild) listOnlineGames.removeChild(listOnlineGames.firstChild);
+        console.log('removed ex list');
+        games.forEach(game => {
+          console.log(game);
+          let title='';
+          let desc='';
+          let rules= '';
+          if (game.adv_rules.length !== 0) {
+            game.adv_rules.forEach(rule => {
+              rules += ' + ' + rule;
+            });
+          } else {
+            rules= ' + no adv. rules';
+          }
+          desc=`${game.deck}${rules}`;
+          if (game.player2 !== '') {
+            title=`Resume ${game.player1} VS ${game.player2}`;
+          } else {
+            title=`${game.player1} waiting...`;
+          }
+          let li = document.createElement("li");
+          let spanTitle = document.createElement("span");
+          let spanDesc = document.createElement("span");
+          let div = document.createElement("div");
+          spanTitle.setAttribute("class", "game-entry-title");
+          spanDesc.setAttribute("class", "game-entry-desc");
+          spanTitle.appendChild(document.createTextNode(title));
+          spanDesc.appendChild(document.createTextNode(desc));
+          li.appendChild(spanTitle);
+          li.appendChild(div);
+          li.appendChild(spanDesc);
+          listOnlineGames.appendChild(li);
+        });
+        loaderOnlineGames.style.display= 'none';
+        listOnlineGames.style.display= 'block';
+      })
+      .catch( (error) => {
+        loaderOnlineGames.style.display= 'none';
+        listOnlineGames.style.display= 'block';
+        listOnlineGames.innerText=error;
+        connectionStatus.innerText=error;
+        createOnlineGameButton.disabled=true;
+        console.log('error to receive games : ' + error);
+      });
+  };
+
+  let onHide = function() {
+
+    listOnlineGames.style.display= 'none';
+    loaderOnlineGames.style.display= 'block';
+    createOnlineGameButton.disabled=false;
+    listOnlineGames.innerText='';
+  };
+
+  let onlineRoomDivPage = {
+    className,
+    div,
+    connectionStatus,
+    onShow,
+    onHide
+  };
+
+  return Object.assign(
+    onlineRoomDivPage,
+    DivCommon.canShow(onlineRoomDivPage),
+    DivCommon.canHide(onlineRoomDivPage),
+    DivCommon.hasConnectionState(onlineRoomDivPage)
+  );
+
+}
+
+
+

+ 65 - 46
webpack.config.js

@@ -2,75 +2,79 @@ var path = require('path');
 var webpack = require('webpack');
 var HtmlWebpackPlugin = require('html-webpack-plugin');
 var BrowserSyncPlugin = require('browser-sync-webpack-plugin');
-var CopyWebpackPlugin = require('copy-webpack-plugin');
+// var CopyWebpackPlugin = require('copy-webpack-plugin');
 var { CleanWebpackPlugin } = require('clean-webpack-plugin');
 
+if (process.env.DEV) {
+  console.log('Loading .env variables');
+  require('dotenv').config({path: __dirname + '/.env'});
+}
+
+const JOJOAPPS_SERVER = '149.91.81.94';
+const JOJOAPPS_SERVER_PORT = 2610;
+
+// Env variables have effect in app : main.js & socket-service.js & index.html
+// Also in Server : mariadb-connector.js
 var definePlugin = new webpack.DefinePlugin({
-  'process.env.CORDOVA': JSON.stringify(JSON.parse(process.env.CORDOVA || 'false'))
+  'process.env.DEV': JSON.stringify(JSON.parse(process.env.DEV || 'false')),
+  'process.env.WEB': JSON.stringify(JSON.parse(process.env.WEB || 'false')),
+  'process.env.CORDOVA': JSON.stringify(JSON.parse(process.env.CORDOVA || 'false')),
+  'process.env.SERVER_HOST': JSON.stringify(process.env.SERVER_HOST || JOJOAPPS_SERVER),
+  'process.env.SERVER_PORT': JSON.stringify(process.env.SERVER_PORT || JOJOAPPS_SERVER_PORT)
 });
 
 var outpath = './webpack/';
 
-if (process.env.CORDOVA) {
-  outpath = 'www/';
+if (process.env.CORDOVA === "true") {
+  outpath = './www/';
+  console.log('CORDOVA environment : output in ',outpath);
+} else if (process.env.WEB === "true") {
+  outpath = './www_web/';
+  console.log('WEB environment : output in ',outpath);
+} else {
+  console.log('DEV env : output in ', outpath);
 }
 
+// new CopyWebpackPlugin([
+//   {
+//     context: path.resolve(__dirname, 'src', 'assets'),
+//     from: '**/*',
+//     to: path.resolve(__dirname, outpath, 'assets')
+//   }
+// ]),
 module.exports = {
   devtool: 'cheap-source-map',
   mode: 'development',
   entry: {
-    polyfills: './src/polyfills.js',
-    app: path.resolve(__dirname, 'src/main.js'),
+    app: path.resolve(__dirname, 'src/main.js')
   },
-  target: 'web',
-  watch: true,
   output: {
-    pathinfo: true,
-    filename: '[name].bundle.js',
-    chunkFilename: '[name].bundle.js',
-    path: path.resolve(__dirname, outpath + 'dist')
-  },
-  optimization: {
-    splitChunks: {
-      cacheGroups: {
-        commons: { test: /[\\/]node_modules[\\/]/, name: "vendors", chunks: "all" }
-      }
-    }
+    filename: 'app.bundle.js',
+    path: path.resolve(__dirname, outpath)
   },
+
   plugins: [
     definePlugin,
     new CleanWebpackPlugin(),
-    new CopyWebpackPlugin([
-      {
-        context: path.resolve(__dirname, 'src', 'assets'),
-        from: '**/*',
-        to: path.resolve(__dirname, outpath, 'assets')
-      }
-    ]),
+
     new HtmlWebpackPlugin({
-      filename: '../index.html',
-      template: './src/index.html',
-      chunksSortMode: "manual",
-      chunks: ['polyfills', 'vendors', 'app'],
-      minify: {
-        removeAttributeQuotes: false,
-        collapseWhitespace: false,
-        html5: false,
-        minifyCSS: false,
-        minifyJS: false,
-        minifyURLs: false,
-        removeComments: false,
-        removeEmptyAttributes: false
-      },
-      hash: false,
-      inject: true
+      template: './src/index.html'
     }),
     new BrowserSyncPlugin({
       host: process.env.IP || 'localhost',
       port: process.env.PORT || 3000,
       server: {
         baseDir: [outpath, './build']
-      }
+      },
+      browser: ["firefox"]
+    }),
+    new BrowserSyncPlugin({
+      host: process.env.IP || 'localhost',
+      port: process.env.PORT || 3005,
+      server: {
+        baseDir: [outpath, './build']
+      },
+      browser: ["firefox"]
     }),
     new webpack.DefinePlugin({
       CANVAS_RENDERER: JSON.stringify(true),
@@ -79,10 +83,25 @@ module.exports = {
   ],
   module: {
     rules: [
-      { test: /\.js$/, exclude: /node_modules/, loaders: "babel-loader" },
+      { test: /\.js$/, exclude: /(node_modules|server)/, loaders: "babel-loader" },
+      {
+        test: /\.(png|svg|jpg|gif)$/,
+        use: {
+          loader: 'file-loader',
+          options: {
+            esModule: false
+          }
+        }
+      },
       {
-        test: /\.(gif|png|jpe?g|svg|xml)$/i,
-        use: "file-loader"
+        test: /\.html$/,
+        exclude: /index.html/,
+        use: [
+          {
+            loader: 'html-loader',
+            options: { minimize: true }
+          }
+        ]
       },
       {
         test: [/\.vert$/, /\.frag$/],

+ 0 - 4
www/.gitignore

@@ -1,4 +0,0 @@
-# Ignore everything in this directory
-*
-# Except this file
-!.gitignore

Some files were not shown because too many files changed in this diff